Merge
authorjrose
Thu, 24 Mar 2011 00:17:59 -0700
changeset 8823 7cd28219a1e4
parent 8717 f75a1efb1412 (current diff)
parent 8822 8145ab9f5f86 (diff)
child 8824 0762fa26f813
child 9033 a88f5656f05d
Merge
jdk/make/common/Release.gmk
jdk/make/java/dyn/Makefile
jdk/src/share/classes/java/dyn/CallSite.java
jdk/src/share/classes/java/dyn/ClassValue.java
jdk/src/share/classes/java/dyn/ConstantCallSite.java
jdk/src/share/classes/java/dyn/InvokeDynamic.java
jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java
jdk/src/share/classes/java/dyn/Linkage.java
jdk/src/share/classes/java/dyn/MethodHandle.java
jdk/src/share/classes/java/dyn/MethodHandles.java
jdk/src/share/classes/java/dyn/MethodType.java
jdk/src/share/classes/java/dyn/MethodTypeForm.java
jdk/src/share/classes/java/dyn/MutableCallSite.java
jdk/src/share/classes/java/dyn/SwitchPoint.java
jdk/src/share/classes/java/dyn/VolatileCallSite.java
jdk/src/share/classes/java/dyn/WrongMethodTypeException.java
jdk/src/share/classes/java/dyn/package-info.java
jdk/src/share/classes/sun/dyn/Access.java
jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java
jdk/src/share/classes/sun/dyn/BoundMethodHandle.java
jdk/src/share/classes/sun/dyn/CallSiteImpl.java
jdk/src/share/classes/sun/dyn/DirectMethodHandle.java
jdk/src/share/classes/sun/dyn/FilterGeneric.java
jdk/src/share/classes/sun/dyn/FilterOneArgument.java
jdk/src/share/classes/sun/dyn/FromGeneric.java
jdk/src/share/classes/sun/dyn/InvokeGeneric.java
jdk/src/share/classes/sun/dyn/Invokers.java
jdk/src/share/classes/sun/dyn/MemberName.java
jdk/src/share/classes/sun/dyn/MethodHandleImpl.java
jdk/src/share/classes/sun/dyn/MethodHandleNatives.java
jdk/src/share/classes/sun/dyn/MethodTypeImpl.java
jdk/src/share/classes/sun/dyn/SpreadGeneric.java
jdk/src/share/classes/sun/dyn/ToGeneric.java
jdk/src/share/classes/sun/dyn/WrapperInstance.java
jdk/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java
jdk/src/share/classes/sun/dyn/anon/ConstantPoolParser.java
jdk/src/share/classes/sun/dyn/anon/ConstantPoolPatch.java
jdk/src/share/classes/sun/dyn/anon/ConstantPoolVisitor.java
jdk/src/share/classes/sun/dyn/anon/InvalidConstantPoolFormatException.java
jdk/src/share/classes/sun/dyn/empty/Empty.java
jdk/src/share/classes/sun/dyn/package-info.java
jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java
jdk/src/share/classes/sun/dyn/util/BytecodeName.java
jdk/src/share/classes/sun/dyn/util/ValueConversions.java
jdk/src/share/classes/sun/dyn/util/VerifyAccess.java
jdk/src/share/classes/sun/dyn/util/VerifyType.java
jdk/src/share/classes/sun/dyn/util/Wrapper.java
jdk/src/share/classes/sun/dyn/util/package-info.java
jdk/test/java/dyn/ClassValueTest.java
jdk/test/java/dyn/InvokeDynamicPrintArgs.java
jdk/test/java/dyn/InvokeGenericTest.java
jdk/test/java/dyn/JavaDocExamplesTest.java
jdk/test/java/dyn/MethodHandlesTest.java
jdk/test/java/dyn/MethodTypeTest.java
jdk/test/java/dyn/indify/Indify.java
--- a/jdk/make/common/Release.gmk	Wed Jul 05 17:38:31 2017 +0200
+++ b/jdk/make/common/Release.gmk	Thu Mar 24 00:17:59 2011 -0700
@@ -54,9 +54,6 @@
                         com.sun.java.swing.plaf.motif    \
                         com.sun.java.swing.plaf.gtk
 
-# This is a stopgap until 6839872 is fixed.
-EXCLUDE_PROPWARN_PKGS += sun.dyn
-
 #
 # Include the exported private packages in ct.sym.
 # This is an interim solution until the ct.sym is replaced
--- a/jdk/make/docs/CORE_PKGS.gmk	Wed Jul 05 17:38:31 2017 +0200
+++ b/jdk/make/docs/CORE_PKGS.gmk	Thu Mar 24 00:17:59 2011 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -55,7 +55,7 @@
 # This is a list of regular expressions. So foo.* matches "foo" and "foo.bar".
 #
 ACTIVE_JSR_PKGS= \
-  java.dyn \
+  java.lang.invoke \
   java.sql  \
   javax.activation  \
   javax.annotation.*  \
@@ -97,11 +97,11 @@
   java.awt.print                                 \
   java.beans                                     \
   java.beans.beancontext                         \
-  java.dyn                                       \
   java.io                                        \
   java.lang                                      \
   java.lang.annotation                           \
   java.lang.instrument                           \
+  java.lang.invoke                               \
   java.lang.management                           \
   java.lang.ref                                  \
   java.lang.reflect                              \
--- a/jdk/make/java/Makefile	Wed Jul 05 17:38:31 2017 +0200
+++ b/jdk/make/java/Makefile	Thu Mar 24 00:17:59 2011 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
 SUBDIRS_desktop    = awt applet beans
 SUBDIRS_management = management
 SUBDIRS_misc       = npt java_crw_demo java_hprof_demo \
-                     logging instrument dyn sql rmi
+                     logging instrument invoke sql rmi
 
 
 ifeq ($(PLATFORM), solaris)
--- a/jdk/make/java/dyn/Makefile	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-BUILDDIR = ../..
-
-PACKAGE = java.dyn
-PRODUCT = java
-include $(BUILDDIR)/common/Defs.gmk
-
-AUTO_FILES_JAVA_DIRS = java/dyn sun/dyn
-
-# The sources built here use new language syntax to generate
-# method handle calls.  Let's be sure we are using that format.
-LANGUAGE_VERSION = -source 7
-CLASS_VERSION = -target 7
-
-# Tell the compiler not to accept transitional forms.
-OTHER_JAVACFLAGS = -XDallowTransitionalJSR292=no
-
-include $(BUILDDIR)/common/Classes.gmk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/java/invoke/Makefile	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+BUILDDIR = ../..
+
+PACKAGE = java.lang.invoke
+PRODUCT = java
+include $(BUILDDIR)/common/Defs.gmk
+
+AUTO_FILES_JAVA_DIRS = java/lang/invoke sun/invoke
+FILES_java = \
+    java/lang/ClassValue.java \
+    java/lang/BootstrapMethodError.java
+
+# The sources built here use new language syntax to generate
+# method handle calls.  Let's be sure we are using that format.
+LANGUAGE_VERSION = -source 7
+CLASS_VERSION = -target 7
+
+include $(BUILDDIR)/common/Classes.gmk
--- a/jdk/src/share/classes/java/dyn/CallSite.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.*;
-import sun.dyn.empty.Empty;
-import sun.misc.Unsafe;
-import java.util.Collection;
-
-/**
- * A {@code CallSite} is a holder for a variable {@link MethodHandle},
- * which is called its {@code target}.
- * An {@code invokedynamic} instruction linked to a {@code CallSite} delegates
- * all calls to the site's current target.
- * A {@code CallSite} may be associated with several {@code invokedynamic}
- * instructions, or it may be "free floating", associated with none.
- * In any case, it may be invoked through an associated method handle
- * called its {@linkplain #dynamicInvoker dynamic invoker}.
- * <p>
- * {@code CallSite} is an abstract class which does not allow
- * direct subclassing by users.  It has three immediate,
- * concrete subclasses that may be either instantiated or subclassed.
- * <ul>
- * <li>If a mutable target is not required, an {@code invokedynamic} instruction
- * may be permanently bound by means of a {@linkplain ConstantCallSite constant call site}.
- * <li>If a mutable target is required which has volatile variable semantics,
- * because updates to the target must be immediately and reliably witnessed by other threads,
- * a {@linkplain VolatileCallSite volatile call site} may be used.
- * <li>Otherwise, if a mutable target is required,
- * a {@linkplain MutableCallSite mutable call site} may be used.
- * </ul>
- * <p>
- * A non-constant call site may be <em>relinked</em> by changing its target.
- * The new target must have the same {@linkplain MethodHandle#type() type}
- * as the previous target.
- * Thus, though a call site can be relinked to a series of
- * successive targets, it cannot change its type.
- * <p>
- * Here is a sample use of call sites and bootstrap methods which links every
- * dynamic call site to print its arguments:
-<blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
-static void test() throws Throwable {
-    // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
-    InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
-}
-private static void printArgs(Object... args) {
-  System.out.println(java.util.Arrays.deepToString(args));
-}
-private static final MethodHandle printArgs;
-static {
-  MethodHandles.Lookup lookup = MethodHandles.lookup();
-  Class thisClass = lookup.lookupClass();  // (who am I?)
-  printArgs = lookup.findStatic(thisClass,
-      "printArgs", MethodType.methodType(void.class, Object[].class));
-}
-private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
-  // ignore caller and name, but match the type:
-  return new ConstantCallSite(printArgs.asType(type));
-}
-</pre></blockquote>
- * @author John Rose, JSR 292 EG
- */
-abstract
-public class CallSite {
-    private static final Access IMPL_TOKEN = Access.getToken();
-    static { MethodHandleImpl.initStatics(); }
-
-    // Fields used only by the JVM.  Do not use or change.
-    private MemberName vmmethod; // supplied by the JVM (ref. to calling method)
-    private int        vmindex;  // supplied by the JVM (BCI within calling method)
-
-    // The actual payload of this call site:
-    /*package-private*/
-    MethodHandle target;
-
-    // Remove this field for PFD and delete deprecated methods:
-    private MemberName calleeNameRemoveForPFD;
-
-    /**
-     * Make a blank call site object with the given method type.
-     * An initial target method is supplied which will throw
-     * an {@link IllegalStateException} if called.
-     * <p>
-     * Before this {@code CallSite} object is returned from a bootstrap method,
-     * it is usually provided with a more useful target method,
-     * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
-     * @throws NullPointerException if the proposed type is null
-     */
-    /*package-private*/
-    CallSite(MethodType type) {
-        target = MethodHandles.invokers(type).uninitializedCallSite();
-    }
-
-    /**
-     * Make a blank call site object, possibly equipped with an initial target method handle.
-     * @param target the method handle which will be the initial target of the call site
-     * @throws NullPointerException if the proposed target is null
-     */
-    /*package-private*/
-    CallSite(MethodHandle target) {
-        target.type();  // null check
-        this.target = target;
-    }
-
-    /**
-     * Returns the type of this call site's target.
-     * Although targets may change, any call site's type is permanent, and can never change to an unequal type.
-     * The {@code setTarget} method enforces this invariant by refusing any new target that does
-     * not have the previous target's type.
-     * @return the type of the current target, which is also the type of any future target
-     */
-    public MethodType type() {
-        return target.type();
-    }
-
-    /** Called from JVM (or low-level Java code) after the BSM returns the newly created CallSite.
-     *  The parameters are JVM-specific.
-     */
-    void initializeFromJVM(String name,
-                           MethodType type,
-                           MemberName callerMethod,
-                           int        callerBCI) {
-        if (this.vmmethod != null) {
-            // FIXME
-            throw new InvokeDynamicBootstrapError("call site has already been linked to an invokedynamic instruction");
-        }
-        if (!this.type().equals(type)) {
-            throw wrongTargetType(target, type);
-        }
-        this.vmindex  = callerBCI;
-        this.vmmethod = callerMethod;
-    }
-
-    /**
-     * Returns the target method of the call site, according to the
-     * behavior defined by this call site's specific class.
-     * The immediate subclasses of {@code CallSite} document the
-     * class-specific behaviors of this method.
-     *
-     * @return the current linkage state of the call site, its target method handle
-     * @see ConstantCallSite
-     * @see VolatileCallSite
-     * @see #setTarget
-     * @see ConstantCallSite#getTarget
-     * @see MutableCallSite#getTarget
-     * @see VolatileCallSite#getTarget
-     */
-    public abstract MethodHandle getTarget();
-
-    /**
-     * Updates the target method of this call site, according to the
-     * behavior defined by this call site's specific class.
-     * The immediate subclasses of {@code CallSite} document the
-     * class-specific behaviors of this method.
-     * <p>
-     * The type of the new target must be {@linkplain MethodType#equals equal to}
-     * the type of the old target.
-     *
-     * @param newTarget the new target
-     * @throws NullPointerException if the proposed new target is null
-     * @throws WrongMethodTypeException if the proposed new target
-     *         has a method type that differs from the previous target
-     * @see CallSite#getTarget
-     * @see ConstantCallSite#setTarget
-     * @see MutableCallSite#setTarget
-     * @see VolatileCallSite#setTarget
-     */
-    public abstract void setTarget(MethodHandle newTarget);
-
-    void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
-        MethodType oldType = oldTarget.type();
-        MethodType newType = newTarget.type();  // null check!
-        if (!newType.equals(oldType))
-            throw wrongTargetType(newTarget, oldType);
-    }
-
-    private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
-        return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type);
-    }
-
-    /**
-     * Produce a method handle equivalent to an invokedynamic instruction
-     * which has been linked to this call site.
-     * <p>
-     * This method is equivalent to the following code:
-     * <blockquote><pre>
-     * MethodHandle getTarget, invoker, result;
-     * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
-     * invoker = MethodHandles.exactInvoker(this.type());
-     * result = MethodHandles.foldArguments(invoker, getTarget)
-     * </pre></blockquote>
-     *
-     * @return a method handle which always invokes this call site's current target
-     */
-    public abstract MethodHandle dynamicInvoker();
-
-    /*non-public*/ MethodHandle makeDynamicInvoker() {
-        MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
-        MethodHandle invoker = MethodHandles.exactInvoker(this.type());
-        return MethodHandles.foldArguments(invoker, getTarget);
-    }
-
-    private static final MethodHandle GET_TARGET;
-    static {
-        try {
-            GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP.
-                findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
-        } catch (ReflectiveOperationException ignore) {
-            throw new InternalError();
-        }
-    }
-
-    /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
-    /*package-private*/
-    static Empty uninitializedCallSite() {
-        throw new IllegalStateException("uninitialized call site");
-    }
-
-    // unsafe stuff:
-    private static final Unsafe unsafe = Unsafe.getUnsafe();
-    private static final long TARGET_OFFSET;
-
-    static {
-        try {
-            TARGET_OFFSET = unsafe.objectFieldOffset(CallSite.class.getDeclaredField("target"));
-        } catch (Exception ex) { throw new Error(ex); }
-    }
-
-    /*package-private*/
-    void setTargetNormal(MethodHandle newTarget) {
-        target = newTarget;
-        //CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
-    }
-    /*package-private*/
-    MethodHandle getTargetVolatile() {
-        return (MethodHandle) unsafe.getObjectVolatile(this, TARGET_OFFSET);
-    }
-    /*package-private*/
-    void setTargetVolatile(MethodHandle newTarget) {
-        unsafe.putObjectVolatile(this, TARGET_OFFSET, newTarget);
-        //CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
-    }
-}
--- a/jdk/src/share/classes/java/dyn/ClassValue.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.util.WeakHashMap;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.lang.reflect.UndeclaredThrowableException;
-
-/**
- * Lazily associate a computed value with (potentially) every type.
- * For example, if a dynamic language needs to construct a message dispatch
- * table for each class encountered at a message send call site,
- * it can use a {@code ClassValue} to cache information needed to
- * perform the message send quickly, for each class encountered.
- * @author John Rose, JSR 292 EG
- */
-public abstract class ClassValue<T> {
-    /**
-     * Compute the given class's derived value for this {@code ClassValue}.
-     * <p>
-     * This method will be invoked within the first thread that accesses
-     * the value with the {@link #get get} method.
-     * <p>
-     * Normally, this method is invoked at most once per class,
-     * but it may be invoked again if there has been a call to
-     * {@link #remove remove}.
-     * <p>
-     * If this method throws an exception, the corresponding call to {@code get}
-     * will terminate abnormally with that exception, and no class value will be recorded.
-     *
-     * @param type the type whose class value must be computed
-     * @return the newly computed value associated with this {@code ClassValue}, for the given class or interface
-     * @see #get
-     * @see #remove
-     */
-    protected abstract T computeValue(Class<?> type);
-
-    /**
-     * Returns the value for the given class.
-     * If no value has yet been computed, it is obtained by
-     * an invocation of the {@link #computeValue computeValue} method.
-     * <p>
-     * The actual installation of the value on the class
-     * is performed atomically.
-     * At that point, if several racing threads have
-     * computed values, one is chosen, and returned to
-     * all the racing threads.
-     * <p>
-     * The {@code type} parameter is typically a class, but it may be any type,
-     * such as an interface, a primitive type (like {@code int.class}), or {@code void.class}.
-     * <p>
-     * In the absence of {@code remove} calls, a class value has a simple
-     * state diagram:  uninitialized and initialized.
-     * When {@code remove} calls are made,
-     * the rules for value observation are more complex.
-     * See the documentation for {@link #remove remove} for more information.
-     *
-     * @param type the type whose class value must be computed or retrieved
-     * @return the current value associated with this {@code ClassValue}, for the given class or interface
-     * @throws NullPointerException if the argument is null
-     * @see #remove
-     * @see #computeValue
-     */
-    public T get(Class<?> type) {
-        ClassValueMap map = getMap(type);
-        if (map != null) {
-            Object x = map.get(this);
-            if (x != null) {
-                return (T) map.unmaskNull(x);
-            }
-        }
-        return setComputedValue(type);
-    }
-
-    /**
-     * Removes the associated value for the given class.
-     * If this value is subsequently {@linkplain #get read} for the same class,
-     * its value will be reinitialized by invoking its {@link #computeValue computeValue} method.
-     * This may result in an additional invocation of the
-     * {@code computeValue computeValue} method for the given class.
-     * <p>
-     * In order to explain the interaction between {@code get} and {@code remove} calls,
-     * we must model the state transitions of a class value to take into account
-     * the alternation between uninitialized and initialized states.
-     * To do this, number these states sequentially from zero, and note that
-     * uninitialized (or removed) states are numbered with even numbers,
-     * while initialized (or re-initialized) states have odd numbers.
-     * <p>
-     * When a thread {@code T} removes a class value in state {@code 2N},
-     * nothing happens, since the class value is already uninitialized.
-     * Otherwise, the state is advanced atomically to {@code 2N+1}.
-     * <p>
-     * When a thread {@code T} queries a class value in state {@code 2N},
-     * the thread first attempts to initialize the class value to state {@code 2N+1}
-     * by invoking {@code computeValue} and installing the resulting value.
-     * <p>
-     * When {@code T} attempts to install the newly computed value,
-     * if the state is still at {@code 2N}, the class value will be initialized
-     * with the computed value, advancing it to state {@code 2N+1}.
-     * <p>
-     * Otherwise, whether the new state is even or odd,
-     * {@code T} will discard the newly computed value
-     * and retry the {@code get} operation.
-     * <p>
-     * Discarding and retrying is an important proviso,
-     * since otherwise {@code T} could potentially install
-     * a disastrously stale value.  For example:
-     * <ul>
-     * <li>{@code T} calls {@code CV.get(C)} and sees state {@code 2N}
-     * <li>{@code T} quickly computes a time-dependent value {@code V0} and gets ready to install it
-     * <li>{@code T} is hit by an unlucky paging or scheduling event, and goes to sleep for a long time
-     * <li>...meanwhile, {@code T2} also calls {@code CV.get(C)} and sees state {@code 2N}
-     * <li>{@code T2} quickly computes a similar time-dependent value {@code V1} and installs it on {@code CV.get(C)}
-     * <li>{@code T2} (or a third thread) then calls {@code CV.remove(C)}, undoing {@code T2}'s work
-     * <li> the previous actions of {@code T2} are repeated several times
-     * <li> also, the relevant computed values change over time: {@code V1}, {@code V2}, ...
-     * <li>...meanwhile, {@code T} wakes up and attempts to install {@code V0}; <em>this must fail</em>
-     * </ul>
-     * We can assume in the above scenario that {@code CV.computeValue} uses locks to properly
-     * observe the time-dependent states as it computes {@code V1}, etc.
-     * This does not remove the threat of a stale value, since there is a window of time
-     * between the return of {@code computeValue} in {@code T} and the installation
-     * of the the new value.  No user synchronization is possible during this time.
-     *
-     * @param type the type whose class value must be removed
-     * @throws NullPointerException if the argument is null
-     */
-    public void remove(Class<?> type) {
-        ClassValueMap map = getMap(type);
-        if (map != null) {
-            synchronized (map) {
-                map.remove(this);
-            }
-        }
-    }
-
-    /// Implementation...
-
-    // The hash code for this type is based on the identity of the object,
-    // and is well-dispersed for power-of-two tables.
-    /** @deprecated This override, which is implementation-specific, will be removed for PFD. */
-    public final int hashCode() { return hashCode; }
-    private final int hashCode = HASH_CODES.getAndAdd(0x61c88647);
-    private static final AtomicInteger HASH_CODES = new AtomicInteger();
-
-    private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
-
-    /** Slow path for {@link #get}. */
-    private T setComputedValue(Class<?> type) {
-        ClassValueMap map = getMap(type);
-        if (map == null) {
-            map = initializeMap(type);
-        }
-        T value = computeValue(type);
-        STORE_BARRIER.lazySet(0);
-        // All stores pending from computeValue are completed.
-        synchronized (map) {
-            // Warm up the table with a null entry.
-            map.preInitializeEntry(this);
-        }
-        STORE_BARRIER.lazySet(0);
-        // All stores pending from table expansion are completed.
-        synchronized (map) {
-            value = (T) map.initializeEntry(this, value);
-            // One might fear a possible race condition here
-            // if the code for map.put has flushed the write
-            // to map.table[*] before the writes to the Map.Entry
-            // are done.  This is not possible, since we have
-            // warmed up the table with an empty entry.
-        }
-        return value;
-    }
-
-    // Replace this map by a per-class slot.
-    private static final WeakHashMap<Class<?>, ClassValueMap> ROOT
-        = new WeakHashMap<Class<?>, ClassValueMap>();
-
-    private static ClassValueMap getMap(Class<?> type) {
-        return ROOT.get(type);
-    }
-
-    private static ClassValueMap initializeMap(Class<?> type) {
-        synchronized (ClassValue.class) {
-            ClassValueMap map = ROOT.get(type);
-            if (map == null)
-                ROOT.put(type, map = new ClassValueMap());
-            return map;
-        }
-    }
-
-    static class ClassValueMap extends WeakHashMap<ClassValue, Object> {
-        /** Make sure this table contains an Entry for the given key, even if it is empty. */
-        void preInitializeEntry(ClassValue key) {
-            if (!this.containsKey(key))
-                this.put(key, null);
-        }
-        /** Make sure this table contains a non-empty Entry for the given key. */
-        Object initializeEntry(ClassValue key, Object value) {
-            Object prior = this.get(key);
-            if (prior != null) {
-                return unmaskNull(prior);
-            }
-            this.put(key, maskNull(value));
-            return value;
-        }
-
-        Object maskNull(Object x) {
-            return x == null ? this : x;
-        }
-        Object unmaskNull(Object x) {
-            return x == this ? null : x;
-        }
-    }
-}
--- a/jdk/src/share/classes/java/dyn/ConstantCallSite.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
- * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
- * bound to the call site's target.
- * @author John Rose, JSR 292 EG
- */
-public class ConstantCallSite extends CallSite {
-    /**
-     * Creates a call site with a permanent target.
-     * @param target the target to be permanently associated with this call site
-     * @throws NullPointerException if the proposed target is null
-     */
-    public ConstantCallSite(MethodHandle target) {
-        super(target);
-    }
-
-    /**
-     * Returns the target method of the call site, which behaves
-     * like a {@code final} field of the {@code ConstantCallSite}.
-     * That is, the the target is always the original value passed
-     * to the constructor call which created this instance.
-     *
-     * @return the immutable linkage state of this call site, a constant method handle
-     * @throws UnsupportedOperationException because this kind of call site cannot change its target
-     */
-    @Override public final MethodHandle getTarget() {
-        return target;
-    }
-
-    /**
-     * Always throws an {@link UnsupportedOperationException}.
-     * This kind of call site cannot change its target.
-     * @param ignore a new target proposed for the call site, which is ignored
-     * @throws UnsupportedOperationException because this kind of call site cannot change its target
-     */
-    @Override public final void setTarget(MethodHandle ignore) {
-        throw new UnsupportedOperationException("ConstantCallSite");
-    }
-
-    /**
-     * Returns this call site's permanent target.
-     * Since that target will never change, this is a correct implementation
-     * of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}.
-     * @return the immutable linkage state of this call site, a constant method handle
-     */
-    @Override
-    public final MethodHandle dynamicInvoker() {
-        return getTarget();
-    }
-}
--- a/jdk/src/share/classes/java/dyn/InvokeDynamic.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * This is a place-holder class.  Some HotSpot implementations need to see it.
- */
-final class InvokeDynamic {
-    private InvokeDynamic() { throw new InternalError(); }  // do not instantiate
-}
--- a/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * Thrown to indicate that an {@code invokedynamic} instruction has
- * failed to find its
- * {@linkplain BootstrapMethod bootstrap method},
- * or the bootstrap method has
- * failed to provide a
- * {@linkplain CallSite call site} with a {@linkplain CallSite#getTarget target}
- * of the correct {@linkplain MethodHandle#type method type}.
- *
- * @author John Rose, JSR 292 EG
- * @since 1.7
- */
-public class InvokeDynamicBootstrapError extends LinkageError {
-    private static final long serialVersionUID = 292L;
-
-    /**
-     * Constructs an {@code InvokeDynamicBootstrapError} with no detail message.
-     */
-    public InvokeDynamicBootstrapError() {
-        super();
-    }
-
-    /**
-     * Constructs an {@code InvokeDynamicBootstrapError} with the specified
-     * detail message.
-     *
-     * @param s the detail message.
-     */
-    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, may be {@code null}.
-     */
-    public InvokeDynamicBootstrapError(String s, Throwable cause) {
-        super(s, cause);
-    }
-
-    /**
-     * Constructs a {@code InvokeDynamicBootstrapError} with the specified
-     * cause.
-     *
-     * @param cause the cause, may be {@code null}.
-     */
-    public InvokeDynamicBootstrapError(Throwable cause) {
-        // cf. Throwable(Throwable cause) constructor.
-        super(cause == null ? null : cause.toString());
-        initCause(cause);
-    }
-}
--- a/jdk/src/share/classes/java/dyn/Linkage.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.dyn.MethodHandles.Lookup;
-import java.util.WeakHashMap;
-import sun.dyn.Access;
-import sun.dyn.MethodHandleImpl;
-import sun.dyn.util.VerifyAccess;
-import sun.reflect.Reflection;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-
-/**
- * <em>CLASS WILL BE REMOVED FOR PFD:</em>
- * Static routines for controlling invokedynamic behavior.
- * Replaced by non-static APIs.
- * @author John Rose, JSR 292 EG
- * @deprecated This class will be removed in the Public Final Draft.
- */
-public class Linkage {
-    private static final Access IMPL_TOKEN = Access.getToken();
-
-    private Linkage() {}  // do not instantiate
-
-    /**
-     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
-     * Register a <em>bootstrap method</em> to use when linking dynamic call sites within
-     * a given caller class.
-     * @deprecated Use @{@link BootstrapMethod} annotations instead.
-     */
-    public static
-    void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
-        Class callc = Reflection.getCallerClass(2);
-        if (callc != null && !VerifyAccess.isSamePackage(callerClass, callc))
-            throw new IllegalArgumentException("cannot set bootstrap method on "+callerClass);
-        MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
-    }
-
-    /**
-     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
-     * Simplified version of {@code registerBootstrapMethod} for self-registration,
-     * to be called from a static initializer.
-     * @deprecated Use @{@link BootstrapMethod} annotations instead.
-     */
-    public static
-    void registerBootstrapMethod(Class<?> runtime, String name) {
-        Class callerClass = Reflection.getCallerClass(2);
-        registerBootstrapMethodLookup(callerClass, runtime, name);
-    }
-
-    /**
-     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
-     * Simplified version of {@code registerBootstrapMethod} for self-registration,
-     * @deprecated Use @{@link BootstrapMethod} annotations instead.
-     */
-    public static
-    void registerBootstrapMethod(String name) {
-        Class callerClass = Reflection.getCallerClass(2);
-        registerBootstrapMethodLookup(callerClass, callerClass, name);
-    }
-
-    private static
-    void registerBootstrapMethodLookup(Class<?> callerClass, Class<?> runtime, String name) {
-        Lookup lookup = new Lookup(IMPL_TOKEN, callerClass);
-        MethodHandle bootstrapMethod;
-        try {
-            bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
-        } catch (ReflectiveOperationException ex) {
-            throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
-        }
-        MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
-    }
-
-    private static final MethodType BOOTSTRAP_METHOD_TYPE
-            = MethodType.methodType(CallSite.class,
-                                    Class.class, String.class, MethodType.class);
-
-    /**
-     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
-     * Invalidate all <code>invokedynamic</code> call sites everywhere.
-     * @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting},
-     * {@link MutableCallSite#syncAll call site update pushing},
-     * and {@link SwitchPoint#guardWithTest target switching} instead.
-     */
-    public static
-    Object invalidateAll() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
-     * Invalidate all {@code invokedynamic} call sites in the bytecodes
-     * of any methods of the given class.
-     * @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting},
-     * {@link MutableCallSite#syncAll call site update pushing},
-     * and {@link SwitchPoint#guardWithTest target switching} instead.
-     */
-    public static
-    Object invalidateCallerClass(Class<?> callerClass) {
-        throw new UnsupportedOperationException();
-    }
-}
--- a/jdk/src/share/classes/java/dyn/MethodHandle.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1009 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-//import sun.dyn.*;
-
-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, directly executable reference to an underlying method,
- * constructor, field, or similar low-level operation, with optional
- * transformations of arguments or return values.
- * These transformations are quite general, and include such patterns as
- * {@linkplain #asType conversion},
- * {@linkplain #bindTo insertion},
- * {@linkplain java.dyn.MethodHandles#dropArguments deletion},
- * and {@linkplain java.dyn.MethodHandles#filterArguments substitution}.
- * <p>
- * <em>Note: The super-class of MethodHandle is Object.
- *     Any other super-class visible in the Reference Implementation
- *     will be removed before the Proposed Final Draft.
- *     Also, the final version will not include any public or
- *     protected constructors.</em>
- *
- * <h3>Method handle contents</h3>
- * Method handles are dynamically and strongly typed according to type descriptor.
- * They are not distinguished by the name or defining class of their underlying methods.
- * A method handle must be invoked using type descriptor which matches
- * the method handle's own {@linkplain #type method type}.
- * <p>
- * Every method handle reports its type via the {@link #type type} accessor.
- * This type descriptor is a {@link java.dyn.MethodType MethodType} object,
- * whose structure is a series of classes, one of which is
- * the return type of the method (or {@code void.class} if none).
- * <p>
- * A method handle's type controls the types of invocations it accepts,
- * and the kinds of transformations that apply to it.
- * <p>
- * A method handle contains a pair of special invoker methods
- * called {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}.
- * Both invoker methods provide direct access to the method handle's
- * underlying method, constructor, field, or other operation,
- * as modified by transformations of arguments and return values.
- * Both invokers accept calls which exactly match the method handle's own type.
- * The {@code invokeGeneric} invoker also accepts a range of other call types.
- * <p>
- * Method handles are immutable and have no visible state.
- * Of course, they can be bound to underlying methods or data which exhibit state.
- * With respect to the Java Memory Model, any method handle will behave
- * as if all of its (internal) fields are final variables.  This means that any method
- * handle made visible to the application will always be fully formed.
- * This is true even if the method handle is published through a shared
- * variable in a data race.
- * <p>
- * Method handles cannot be subclassed by the user.
- * Implementations may (or may not) create internal subclasses of {@code MethodHandle}
- * which may be visible via the {@link java.lang.Object#getClass Object.getClass}
- * operation.  The programmer should not draw conclusions about a method handle
- * from its specific class, as the method handle class hierarchy (if any)
- * may change from time to time or across implementations from different vendors.
- *
- * <h3>Method handle compilation</h3>
- * A Java method call expression naming {@code invokeExact} or {@code invokeGeneric}
- * can invoke a method handle from Java source code.
- * From the viewpoint of source code, these methods can take any arguments
- * and their result can be cast to any return type.
- * Formally this is accomplished by giving the invoker methods
- * {@code Object} return types and variable-arity {@code Object} arguments,
- * but they have an additional quality called <em>signature polymorphism</em>
- * which connects this freedom of invocation directly to the JVM execution stack.
- * <p>
- * As is usual with virtual methods, source-level calls to {@code invokeExact}
- * and {@code invokeGeneric} compile to an {@code invokevirtual} instruction.
- * More unusually, the compiler must record the actual argument types,
- * and may not perform method invocation conversions on the arguments.
- * Instead, it must push them on the stack according to their own unconverted types.
- * The method handle object itself is pushed on the stack before the arguments.
- * The compiler then calls the method handle with a type descriptor which
- * describes the argument and return types.
- * <p>
- * To issue a complete type descriptor, the compiler must also determine
- * the return type.  This is based on a cast on the method invocation expression,
- * if there is one, or else {@code Object} if the invocation is an expression
- * or else {@code void} if the invocation is a statement.
- * The cast may be to a primitive type (but not {@code void}).
- * <p>
- * As a corner case, an uncasted {@code null} argument is given
- * a type descriptor of {@code java.lang.Void}.
- * The ambiguity with the type {@code Void} is harmless, since there are no references of type
- * {@code Void} except the null reference.
- *
- * <h3>Method handle invocation</h3>
- * The first time a {@code invokevirtual} instruction is executed
- * it is linked, by symbolically resolving the names in the instruction
- * and verifying that the method call is statically legal.
- * This is true of calls to {@code invokeExact} and {@code invokeGeneric}.
- * In this case, the type descriptor emitted by the compiler is checked for
- * correct syntax and names it contains are resolved.
- * Thus, an {@code invokevirtual} instruction which invokes
- * a method handle will always link, as long
- * as the type descriptor is syntactically well-formed
- * and the types exist.
- * <p>
- * When the {@code invokevirtual} is executed after linking,
- * the receiving method handle's type is first checked by the JVM
- * to ensure that it matches the descriptor.
- * If the type match fails, it means that the method which the
- * caller is invoking is not present on the individual
- * method handle being invoked.
- * <p>
- * In the case of {@code invokeExact}, the type descriptor of the invocation
- * (after resolving symbolic type names) must exactly match the method type
- * of the receiving method handle.
- * In the case of {@code invokeGeneric}, the resolved type descriptor
- * must be a valid argument to the receiver's {@link #asType asType} method.
- * Thus, {@code invokeGeneric} is more permissive than {@code invokeExact}.
- * <p>
- * After type matching, a call to {@code invokeExact} directly
- * and immediately invoke the method handle's underlying method
- * (or other behavior, as the case may be).
- * <p>
- * A call to {@code invokeGeneric} works the same as a call to
- * {@code invokeExact}, if the type descriptor specified by the caller
- * exactly matches the method handle's own type.
- * If there is a type mismatch, {@code invokeGeneric} attempts
- * to adjust the type of the receiving method handle,
- * as if by a call to {@link #asType asType},
- * to obtain an exactly invokable method handle {@code M2}.
- * This allows a more powerful negotiation of method type
- * between caller and callee.
- * <p>
- * (Note: The adjusted method handle {@code M2} is not directly observable,
- * and implementations are therefore not required to materialize it.)
- *
- * <h3>Invocation checking</h3>
- * In typical programs, method handle type matching will usually succeed.
- * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
- * either directly (in the case of {@code invokeExact}) or indirectly as if
- * by a failed call to {@code asType} (in the case of {@code invokeGeneric}).
- * <p>
- * Thus, a method type mismatch which might show up as a linkage error
- * in a statically typed program can show up as
- * a dynamic {@code WrongMethodTypeException}
- * in a program which uses method handles.
- * <p>
- * Because method types contain "live" {@code Class} objects,
- * method type matching takes into account both types names and class loaders.
- * Thus, even if a method handle {@code M} is created in one
- * class loader {@code L1} and used in another {@code L2},
- * method handle calls are type-safe, because the caller's type
- * descriptor, as resolved in {@code L2},
- * is matched against the original callee method's type descriptor,
- * as resolved in {@code L1}.
- * The resolution in {@code L1} happens when {@code M} is created
- * and its type is assigned, while the resolution in {@code L2} happens
- * when the {@code invokevirtual} instruction is linked.
- * <p>
- * Apart from the checking of type descriptors,
- * a method handle's capability to call its underlying method is unrestricted.
- * If a method handle is formed on a non-public method by a class
- * that has access to that method, the resulting handle can be used
- * in any place by any caller who receives a reference to it.
- * <p>
- * Unlike with the Core Reflection API, where access is checked every time
- * a reflective method is invoked,
- * method handle access checking is performed
- * <a href="MethodHandles.Lookup.html#access">when the method handle is created</a>.
- * In the case of {@code ldc} (see below), access checking is performed as part of linking
- * the constant pool entry underlying the constant method handle.
- * <p>
- * Thus, handles to non-public methods, or to methods in non-public classes,
- * should generally be kept secret.
- * They should not be passed to untrusted code unless their use from
- * the untrusted code would be harmless.
- *
- * <h3>Method handle creation</h3>
- * Java code can create a method handle that directly accesses
- * any method, constructor, or field that is accessible to that code.
- * This is done via a reflective, capability-based API called
- * {@link java.dyn.MethodHandles.Lookup MethodHandles.Lookup}
- * For example, a static method handle can be obtained
- * from {@link java.dyn.MethodHandles.Lookup#findStatic Lookup.findStatic}.
- * There are also conversion methods from Core Reflection API objects,
- * such as {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}.
- * <p>
- * Like classes and strings, method handles that correspond to accessible
- * fields, methods, and constructors can also be represented directly
- * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
- * A new type of constant pool entry, {@code CONSTANT_MethodHandle},
- * refers directly to an associated {@code CONSTANT_Methodref},
- * {@code CONSTANT_InterfaceMethodref}, or {@code CONSTANT_Fieldref}
- * constant pool entry.
- * (For more details on method handle constants,
- * see the <a href="package-summary.html#mhcon">package summary</a>.)
- * <p>
- * Method handles produced by lookups or constant loads from methods or
- * constructors with the variable arity modifier bit ({@code 0x0080})
- * have a corresponding variable arity, as if they were defined with
- * the help of {@link #asVarargsCollector asVarargsCollector}.
- * <p>
- * A method reference may refer either to a static or non-static method.
- * In the non-static case, the method handle type includes an explicit
- * receiver argument, prepended before any other arguments.
- * In the method handle's type, the initial receiver argument is typed
- * according to the class under which the method was initially requested.
- * (E.g., if a non-static method handle is obtained via {@code ldc},
- * the type of the receiver is the class named in the constant pool entry.)
- * <p>
- * When a method handle to a virtual method is invoked, the method is
- * always looked up in the receiver (that is, the first argument).
- * <p>
- * A non-virtual method handle to a specific virtual method implementation
- * 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} instruction to the same method.
- *
- * <h3>Usage examples</h3>
- * 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)String
-mt = MethodType.methodType(String.class, char.class, char.class);
-mh = lookup.findVirtual(String.class, "replace", mt);
-s = (String) mh.invokeExact("daddy",'d','n');
-// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
-assert(s.equals("nanny"));
-// weakly typed invocation (using MHs.invoke)
-s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
-assert(s.equals("savvy"));
-// mt is (Object[])List
-mt = MethodType.methodType(java.util.List.class, Object[].class);
-mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
-assert(mh.isVarargsCollector());
-x = mh.invokeGeneric("one", "two");
-// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
-assert(x.equals(java.util.Arrays.asList("one","two")));
-// mt is (Object,Object,Object)Object
-mt = MethodType.genericMethodType(3);
-mh = mh.asType(mt);
-x = mh.invokeExact((Object)1, (Object)2, (Object)3);
-// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-assert(x.equals(java.util.Arrays.asList(1,2,3)));
-// mt is { =&gt; int}
-mt = MethodType.methodType(int.class);
-mh = lookup.findVirtual(java.util.List.class, "size", mt);
-i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
-// invokeExact(Ljava/util/List;)I
-assert(i == 3);
-mt = MethodType.methodType(void.class, String.class);
-mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
-mh.invokeExact(System.out, "Hello, world.");
-// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
- * </pre></blockquote>
- * Each of the above calls to {@code invokeExact} or {@code invokeGeneric}
- * generates a single invokevirtual instruction with
- * the type descriptor indicated in the following comment.
- *
- * <h3>Exceptions</h3>
- * The methods {@code invokeExact} and {@code invokeGeneric} are declared
- * to throw {@link java.lang.Throwable Throwable},
- * 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 java.lang.Throwable Throwable}, or else must catch all
- * throwables locally, rethrowing only those which are legal in the context,
- * and wrapping ones which are illegal.
- *
- * <h3><a name="sigpoly"></a>Signature polymorphism</h3>
- * The unusual compilation and linkage behavior of
- * {@code invokeExact} and {@code invokeGeneric}
- * is referenced by the term <em>signature polymorphism</em>.
- * A signature polymorphic method is one which can operate with
- * any of a wide range of call signatures and return types.
- * In order to make this work, both the Java compiler and the JVM must
- * give special treatment to signature polymorphic methods.
- * <p>
- * In source code, a call to a signature polymorphic method will
- * compile, regardless of the requested type descriptor.
- * As usual, the Java compiler emits an {@code invokevirtual}
- * instruction with the given type descriptor against the named method.
- * The unusual part is that the type descriptor is derived from
- * the actual argument and return types, not from the method declaration.
- * <p>
- * When the JVM processes bytecode containing signature polymorphic calls,
- * it will successfully link any such call, regardless of its type descriptor.
- * (In order to retain type safety, the JVM will guard such calls with suitable
- * dynamic type checks, as described elsewhere.)
- * <p>
- * Bytecode generators, including the compiler back end, are required to emit
- * untransformed type descriptors for these methods.
- * Tools which determine symbolic linkage are required to accept such
- * untransformed descriptors, without reporting linkage errors.
- * <p>
- * For the sake of tools (but not as a programming API), the signature polymorphic
- * methods are marked with a private yet standard annotation,
- * {@code @java.dyn.MethodHandle.PolymorphicSignature}.
- * The annotation's retention is {@code RUNTIME}, so that all tools can see it.
- *
- * <h3>Formal rules for processing signature polymorphic methods</h3>
- * <p>
- * The following methods (and no others) are signature polymorphic:
- * <ul>
- * <li>{@link java.dyn.MethodHandle#invokeExact   MethodHandle.invokeExact}
- * <li>{@link java.dyn.MethodHandle#invokeGeneric MethodHandle.invokeGeneric}
- * </ul>
- * <p>
- * A signature polymorphic method will be declared with the following properties:
- * <ul>
- * <li>It must be native.
- * <li>It must take a single varargs parameter of the form {@code Object...}.
- * <li>It must produce a return value of type {@code Object}.
- * <li>It must be contained within the {@code java.dyn} package.
- * </ul>
- * Because of these requirements, a signature polymorphic method is able to accept
- * any number and type of actual arguments, and can, with a cast, produce a value of any type.
- * However, the JVM will treat these declaration features as a documentation convention,
- * rather than a description of the actual structure of the methods as executed.
- * <p>
- * When a call to a signature polymorphic method is compiled, the associated linkage information for
- * its arguments is not array of {@code Object} (as for other similar varargs methods)
- * but rather the erasure of the static types of all the arguments.
- * <p>
- * In an argument position of a method invocation on a signature polymorphic method,
- * a null literal has type {@code java.lang.Void}, unless cast to a reference type.
- * (Note: This typing rule allows the null type to have its own encoding in linkage information
- * distinct from other types.
- * <p>
- * The linkage information for the return type is derived from a context-dependent target typing convention.
- * The return type for a signature polymorphic method invocation is determined as follows:
- * <ul>
- * <li>If the method invocation expression is an expression statement, the method is {@code void}.
- * <li>Otherwise, if the method invocation expression is the immediate operand of a cast,
- * the return type is the erasure of the cast type.
- * <li>Otherwise, the return type is the method's nominal return type, {@code Object}.
- * </ul>
- * (Programmers are encouraged to use explicit casts unless it is clear that a signature polymorphic
- * call will be used as a plain {@code Object} expression.)
- * <p>
- * The linkage information for argument and return types is stored in the descriptor for the
- * compiled (bytecode) call site. As for any invocation instruction, the arguments and return value
- * will be passed directly on the JVM stack, in accordance with the descriptor,
- * and without implicit boxing or unboxing.
- *
- * <h3>Interoperation between method handles and the Core Reflection API</h3>
- * Using factory methods in the {@link java.dyn.MethodHandles.Lookup Lookup} API,
- * any class member represented by a Core Reflection API object
- * can be converted to a behaviorally equivalent method handle.
- * For example, a reflective {@link java.lang.reflect.Method Method} can
- * be converted to a method handle using
- * {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}.
- * The resulting method handles generally provide more direct and efficient
- * access to the underlying class members.
- * <p>
- * As a special case,
- * when the Core Reflection API is used to view the signature polymorphic
- * methods {@code invokeExact} or {@code invokeGeneric} in this class,
- * they appear as single, non-polymorphic native methods.
- * Calls to these native methods do not result in method handle invocations.
- * Since {@code invokevirtual} instructions can natively
- * invoke method handles under any type descriptor, this reflective view conflicts
- * with the normal presentation via bytecodes.
- * Thus, these two native methods, as viewed by
- * {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod},
- * are placeholders only.
- * If invoked via {@link java.lang.reflect.Method#invoke Method.invoke},
- * they will throw {@code UnsupportedOperationException}.
- * <p>
- * In order to obtain an invoker method for a particular type descriptor,
- * use {@link java.dyn.MethodHandles#exactInvoker MethodHandles.exactInvoker},
- * or {@link java.dyn.MethodHandles#genericInvoker MethodHandles.genericInvoker}.
- * The {@link java.dyn.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
- * API is also able to return a method handle
- * to call {@code invokeExact} or {@code invokeGeneric},
- * for any specified type descriptor .
- *
- * <h3>Interoperation between method handles and Java generics</h3>
- * A method handle can be obtained on a method, constructor, or field
- * which is declared with Java generic types.
- * As with the Core Reflection API, the type of the method handle
- * will constructed from the erasure of the source-level type.
- * When a method handle is invoked, the types of its arguments
- * or the return value cast type may be generic types or type instances.
- * If this occurs, the compiler will replace those
- * types by their erasures when when it constructs the type descriptor
- * for the {@code invokevirtual} instruction.
- * <p>
- * Method handles do not represent
- * their function-like types in terms of Java parameterized (generic) types,
- * because there are three mismatches between function-like types and parameterized
- * Java types.
- * <ul>
- * <li>Method types range over all possible arities,
- * from no arguments to up to 255 of arguments (a limit imposed by the JVM).
- * 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>
- * </ul>
- *
- * @see MethodType
- * @see MethodHandles
- * @author John Rose, JSR 292 EG
- */
-public abstract class MethodHandle
-        // 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 MethodHandleImpl
-{
-    private static Access IMPL_TOKEN = Access.getToken();
-    static { MethodHandleImpl.initStatics(); }
-
-    // interface MethodHandle<R throws X extends Exception,A...>
-    // { MethodType<R throws X,A...> type(); public R invokeExact(A...) throws X; }
-
-    /**
-     * Internal marker interface which distinguishes (to the Java compiler)
-     * those methods which are <a href="MethodHandle.html#sigpoly">signature polymorphic</a>.
-     */
-    @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
-    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
-    @interface PolymorphicSignature { }
-
-    private MethodType type;
-
-    /**
-     * Report the type of this method handle.
-     * Every invocation of this method handle via {@code invokeExact} must exactly match this type.
-     * @return the method handle type
-     */
-    public MethodType type() {
-        return type;
-    }
-
-    /**
-     * <em>CONSTRUCTOR WILL BE REMOVED FOR PFD:</em>
-     * Temporary constructor in early versions of the Reference Implementation.
-     * Method handle inheritance (if any) will be contained completely within
-     * the {@code java.dyn} package.
-     */
-    // The constructor for MethodHandle may only be called by privileged code.
-    // Subclasses may be in other packages, but must possess
-    // a token which they obtained from MH with a security check.
-    // @param token non-null object which proves access permission
-    // @param type type (permanently assigned) of the new method handle
-    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); }
-        });
-    }
-
-    /**
-     * Invoke the method handle, allowing any caller type descriptor, but requiring an exact type match.
-     * The type descriptor at the call site of {@code invokeExact} must
-     * exactly match this method handle's {@link #type type}.
-     * No conversions are allowed on arguments or return values.
-     * <p>
-     * When this method is observed via the Core Reflection API,
-     * it will appear as a single native method, taking an object array and returning an object.
-     * If this native method is invoked directly via
-     * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
-     * or indirectly via {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect},
-     * it will throw an {@code UnsupportedOperationException}.
-     * @throws WrongMethodTypeException if the target's type is not identical with the caller's type descriptor
-     * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
-     */
-    public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
-
-    /**
-     * Invoke the method handle, allowing any caller type descriptor,
-     * and optionally performing conversions on arguments and return values.
-     * <p>
-     * If the call site type descriptor exactly matches this method handle's {@link #type type},
-     * the call proceeds as if by {@link #invokeExact invokeExact}.
-     * <p>
-     * Otherwise, the call proceeds as if this method handle were first
-     * adjusted by calling {@link #asType asType} to adjust this method handle
-     * to the required type, and then the call proceeds as if by
-     * {@link #invokeExact invokeExact} on the adjusted method handle.
-     * <p>
-     * There is no guarantee that the {@code asType} call is actually made.
-     * If the JVM can predict the results of making the call, it may perform
-     * adaptations directly on the caller's arguments,
-     * and call the target method handle according to its own exact type.
-     * <p>
-     * The type descriptor at the call site of {@code invokeGeneric} must
-     * be a valid argument to the receivers {@code asType} method.
-     * In particular, the caller must specify the same argument arity
-     * as the callee's type,
-     * if the callee is not a {@linkplain #asVarargsCollector variable arity collector}.
-     * <p>
-     * When this method is observed via the Core Reflection API,
-     * it will appear as a single native method, taking an object array and returning an object.
-     * If this native method is invoked directly via
-     * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
-     * or indirectly via {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect},
-     * it will throw an {@code UnsupportedOperationException}.
-     * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type descriptor
-     * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
-     * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
-     */
-    public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable;
-
-    /**
-     * Perform a varargs invocation, passing the arguments in the given array
-     * to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
-     * which mentions only the type {@code Object}, and whose arity is the length
-     * of the argument array.
-     * <p>
-     * Specifically, execution proceeds as if by the following steps,
-     * although the methods are not guaranteed to be called if the JVM
-     * can predict their effects.
-     * <ul>
-     * <li>Determine the length of the argument array as {@code N}.
-     *     For a null reference, {@code N=0}. </li>
-     * <li>Determine the generic type {@code TN} of {@code N} arguments as
-     *     as {@code TN=MethodType.genericMethodType(N)}.</li>
-     * <li>Force the original target method handle {@code MH0} to the
-     *     required type, as {@code MH1 = MH0.asType(TN)}. </li>
-     * <li>Spread the array into {@code N} separate arguments {@code A0, ...}. </li>
-     * <li>Invoke the type-adjusted method handle on the unpacked arguments:
-     *     MH1.invokeExact(A0, ...). </li>
-     * <li>Take the return value as an {@code Object} reference. </li>
-     * </ul>
-     * <p>
-     * Because of the action of the {@code asType} step, the following argument
-     * conversions are applied as necessary:
-     * <ul>
-     * <li>reference casting
-     * <li>unboxing
-     * <li>widening primitive conversions
-     * </ul>
-     * <p>
-     * 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.spreadInvoker(this.type(), 0);
-     * Object result = invoker.invokeExact(this, arguments);
-     * </pre></blockquote>
-     * <p>
-     * Unlike the signature polymorphic methods {@code invokeExact} and {@code invokeGeneric},
-     * {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI.
-     * It can therefore be used as a bridge between native or reflective code and method handles.
-     *
-     * @param arguments the arguments to pass to the target
-     * @return the result returned by the target
-     * @throws ClassCastException if an argument cannot be converted by reference casting
-     * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
-     * @throws Throwable anything thrown by the target method invocation
-     * @see MethodHandles#spreadInvoker
-     */
-    public Object invokeWithArguments(Object... arguments) throws Throwable {
-        int argc = arguments == null ? 0 : arguments.length;
-        MethodType type = type();
-        if (type.parameterCount() != argc) {
-            // simulate invokeGeneric
-            return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
-        }
-        if (argc <= 10) {
-            MethodHandle invoker = invokers(type).genericInvoker();
-            switch (argc) {
-                case 0:  return invoker.invokeExact(this);
-                case 1:  return invoker.invokeExact(this,
-                                    arguments[0]);
-                case 2:  return invoker.invokeExact(this,
-                                    arguments[0], arguments[1]);
-                case 3:  return invoker.invokeExact(this,
-                                    arguments[0], arguments[1], arguments[2]);
-                case 4:  return invoker.invokeExact(this,
-                                    arguments[0], arguments[1], arguments[2],
-                                    arguments[3]);
-                case 5:  return invoker.invokeExact(this,
-                                    arguments[0], arguments[1], arguments[2],
-                                    arguments[3], arguments[4]);
-                case 6:  return invoker.invokeExact(this,
-                                    arguments[0], arguments[1], arguments[2],
-                                    arguments[3], arguments[4], arguments[5]);
-                case 7:  return invoker.invokeExact(this,
-                                    arguments[0], arguments[1], arguments[2],
-                                    arguments[3], arguments[4], arguments[5],
-                                    arguments[6]);
-                case 8:  return invoker.invokeExact(this,
-                                    arguments[0], arguments[1], arguments[2],
-                                    arguments[3], arguments[4], arguments[5],
-                                    arguments[6], arguments[7]);
-                case 9:  return invoker.invokeExact(this,
-                                    arguments[0], arguments[1], arguments[2],
-                                    arguments[3], arguments[4], arguments[5],
-                                    arguments[6], arguments[7], arguments[8]);
-                case 10:  return invoker.invokeExact(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 = invokers(type).spreadInvoker(0);
-        return invoker.invokeExact(this, arguments);
-    }
-    /** Equivalent to {@code invokeWithArguments(arguments.toArray())}. */
-    public Object invokeWithArguments(java.util.List<?> arguments) throws Throwable {
-        return invokeWithArguments(arguments.toArray());
-    }
-
-    /**
-     * Produce an adapter method handle which adapts the type of the
-     * current method handle to a new type
-     * The resulting method handle is guaranteed to report 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 provides the crucial behavioral difference between
-     * {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}.  The two methods
-     * perform the same steps when the caller's type descriptor is identical
-     * with the callee's, but when the types differ, {@link #invokeGeneric invokeGeneric}
-     * also calls {@code asType} (or some internal equivalent) in order
-     * to match up the caller's and callee's types.
-     * <p>
-     * This method is equivalent to {@link MethodHandles#convertArguments convertArguments},
-     * except for variable arity method handles produced by {@link #asVarargsCollector asVarargsCollector}.
-     *
-     * @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 WrongMethodTypeException if the conversion cannot be made
-     * @see MethodHandles#convertArguments
-     */
-    public MethodHandle asType(MethodType newType) {
-        return MethodHandles.convertArguments(this, newType);
-    }
-
-    /**
-     * Make an adapter which accepts a trailing array argument
-     * and spreads its elements as positional arguments.
-     * The new method handle 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 the final
-     * {@code arrayLength} parameters of the target's type are replaced
-     * by a single array parameter of type {@code arrayType}.
-     * <p>
-     * If the array element type differs from any of the corresponding
-     * argument types on the original target,
-     * the original target is adapted to take the array elements directly,
-     * as if by a call to {@link #asType asType}.
-     * <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
-     * 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 arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments
-     * @param arrayLength the number of arguments to spread from an incoming array argument
-     * @return a new method handle which spreads its final array argument,
-     *         before calling the original method handle
-     * @throws IllegalArgumentException if {@code arrayType} is not an array type
-     * @throws IllegalArgumentException if target does not have at least
-     *         {@code arrayLength} parameter types
-     * @throws WrongMethodTypeException if the implied {@code asType} call fails
-     * @see #asCollector
-     */
-    public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
-        Class<?> arrayElement = arrayType.getComponentType();
-        if (arrayElement == null)  throw newIllegalArgumentException("not an array type");
-        MethodType oldType = type();
-        int nargs = oldType.parameterCount();
-        if (nargs < arrayLength)  throw newIllegalArgumentException("bad spread array length");
-        int keepPosArgs = nargs - arrayLength;
-        MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs);
-        newType = newType.insertParameterTypes(keepPosArgs, arrayType);
-        return MethodHandles.spreadArguments(this, newType);
-    }
-
-    /**
-     * Make an adapter which accepts a given number of trailing
-     * positional arguments and collects them into an array argument.
-     * The new method handle 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
-     * parameter (usually of type {@code arrayType}) is replaced by
-     * {@code arrayLength} parameters whose type is element type of {@code arrayType}.
-     * <p>
-     * If the array type differs from the final argument type on the original target,
-     * the original target is adapted to take the array type directly,
-     * as if by a call to {@link #asType asType}.
-     * <p>
-     * When called, the adapter replaces its trailing {@code arrayLength}
-     * arguments by a single new array of type {@code arrayType}, 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 arrayLength} is zero.)
-     * <p>
-     * (<em>Note:</em> The {@code arrayType} is often identical to the last
-     * parameter type of the original target.
-     * It is an explicit argument for symmetry with {@code asSpreader}, and also
-     * to allow the target to use a simple {@code Object} as its last parameter type.)
-     * <p>
-     * In order to create a collecting adapter which is not restricted to a particular
-     * number of collected arguments, use {@link #asVarargsCollector asVarargsCollector} instead.
-     * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
-     * @param arrayLength the number of arguments to collect into a new array argument
-     * @return a new method handle which collects some trailing argument
-     *         into an array, before calling the original method handle
-     * @throws IllegalArgumentException if {@code arrayType} is not an array type
-     *         or {@code arrayType} is not assignable to this method handle's trailing parameter type,
-     *         or {@code arrayLength} is not a legal array size
-     * @throws WrongMethodTypeException if the implied {@code asType} call fails
-     * @see #asSpreader
-     * @see #asVarargsCollector
-     */
-    public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
-        Class<?> arrayElement = arrayType.getComponentType();
-        if (arrayElement == null)  throw newIllegalArgumentException("not an array type");
-        MethodType oldType = type();
-        int nargs = oldType.parameterCount();
-        if (nargs == 0)  throw newIllegalArgumentException("no trailing argument");
-        MethodType newType = oldType.dropParameterTypes(nargs-1, nargs);
-        newType = newType.insertParameterTypes(nargs-1,
-                    java.util.Collections.<Class<?>>nCopies(arrayLength, arrayElement));
-        return MethodHandles.collectArguments(this, newType);
-    }
-
-    /**
-     * Make a <em>variable arity</em> adapter which is able to accept
-     * any number of trailing positional arguments and collect them
-     * into an array argument.
-     * <p>
-     * The type and behavior of the adapter will be the same as
-     * the type and behavior of the target, except that certain
-     * {@code invokeGeneric} and {@code asType} requests can lead to
-     * trailing positional arguments being collected into target's
-     * trailing parameter.
-     * Also, the last parameter type of the adapter will be
-     * {@code arrayType}, even if the target has a different
-     * last parameter type.
-     * <p>
-     * When called with {@link #invokeExact invokeExact}, the adapter invokes
-     * the target with no argument changes.
-     * (<em>Note:</em> This behavior is different from a
-     * {@linkplain #asCollector fixed arity collector},
-     * since it accepts a whole array of indeterminate length,
-     * rather than a fixed number of arguments.)
-     * <p>
-     * When called with {@link #invokeGeneric invokeGeneric}, if the caller
-     * type is the same as the adapter, the adapter invokes the target as with
-     * {@code invokeExact}.
-     * (This is the normal behavior for {@code invokeGeneric} when types match.)
-     * <p>
-     * Otherwise, if the caller and adapter arity are the same, and the
-     * trailing parameter type of the caller is a reference type identical to
-     * or assignable to the trailing parameter type of the adapter,
-     * the arguments and return values are converted pairwise,
-     * as if by {@link MethodHandles#convertArguments convertArguments}.
-     * (This is also normal behavior for {@code invokeGeneric} in such a case.)
-     * <p>
-     * Otherwise, the arities differ, or the adapter's trailing parameter
-     * type is not assignable from the corresponding caller type.
-     * In this case, the adapter replaces all trailing arguments from
-     * the original trailing argument position onward, by
-     * a new array of type {@code arrayType}, whose elements
-     * comprise (in order) the replaced arguments.
-     * <p>
-     * The caller type must provides as least enough arguments,
-     * and of the correct type, to satisfy the target's requirement for
-     * positional arguments before the trailing array argument.
-     * Thus, the caller must supply, at a minimum, {@code N-1} arguments,
-     * where {@code N} is the arity of the target.
-     * Also, there must exist conversions from the incoming arguments
-     * to the target's arguments.
-     * As with other uses of {@code invokeGeneric}, if these basic
-     * requirements are not fulfilled, a {@code WrongMethodTypeException}
-     * may be thrown.
-     * <p>
-     * In all cases, what the target eventually returns is returned unchanged by the adapter.
-     * <p>
-     * In the final case, it is exactly as if the target method handle were
-     * temporarily adapted with a {@linkplain #asCollector fixed arity collector}
-     * to the arity required by the caller type.
-     * (As with {@code asCollector}, if the array length is zero,
-     * a shared constant may be used instead of a new array.
-     * If the implied call to {@code asCollector} would throw
-     * an {@code IllegalArgumentException} or {@code WrongMethodTypeException},
-     * the call to the variable arity adapter must throw
-     * {@code WrongMethodTypeException}.)
-     * <p>
-     * The behavior of {@link #asType asType} is also specialized for
-     * variable arity adapters, to maintain the invariant that
-     * {@code invokeGeneric} is always equivalent to an {@code asType}
-     * call to adjust the target type, followed by {@code invokeExact}.
-     * Therefore, a variable arity adapter responds
-     * to an {@code asType} request by building a fixed arity collector,
-     * if and only if the adapter and requested type differ either
-     * in arity or trailing argument type.
-     * The resulting fixed arity collector has its type further adjusted
-     * (if necessary) to the requested type by pairwise conversion,
-     * as if by another application of {@code asType}.
-     * <p>
-     * When a method handle is obtained by executing an {@code ldc} instruction
-     * of a {@code CONSTANT_MethodHandle} constant, and the target method is marked
-     * as a variable arity method (with the modifier bit {@code 0x0080}),
-     * the method handle will accept multiple arities, as if the method handle
-     * constant were created by means of a call to {@code asVarargsCollector}.
-     * <p>
-     * In order to create a collecting adapter which collects a predetermined
-     * number of arguments, and whose type reflects this predetermined number,
-     * use {@link #asCollector asCollector} instead.
-     * <p>
-     * No method handle transformations produce new method handles with
-     * variable arity, unless they are documented as doing so.
-     * Therefore, besides {@code asVarargsCollector},
-     * all methods in {@code MethodHandle} and {@code MethodHandles}
-     * will return a method handle with fixed arity,
-     * except in the cases where they are specified to return their original
-     * operand (e.g., {@code asType} of the method handle's own type).
-     * <p>
-     * Calling {@code asVarargsCollector} on a method handle which is already
-     * of variable arity will produce a method handle with the same type and behavior.
-     * It may (or may not) return the original variable arity method handle.
-     * <p>
-     * Here is an example, of a list-making variable arity method handle:
-     * <blockquote><pre>
-MethodHandle asList = publicLookup()
-  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
-  .asVarargsCollector(Object[].class);
-assertEquals("[]", asList.invokeGeneric().toString());
-assertEquals("[1]", asList.invokeGeneric(1).toString());
-assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString());
-Object[] argv = { "three", "thee", "tee" };
-assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString());
-List ls = (List) asList.invokeGeneric((Object)argv);
-assertEquals(1, ls.size());
-assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
-     * </pre></blockquote>
-     * <p style="font-size:smaller;">
-     * <em>Discussion:</em>
-     * These rules are designed as a dynamically-typed variation
-     * of the Java rules for variable arity methods.
-     * In both cases, callers to a variable arity method or method handle
-     * can either pass zero or more positional arguments, or else pass
-     * pre-collected arrays of any length.  Users should be aware of the
-     * special role of the final argument, and of the effect of a
-     * type match on that final argument, which determines whether
-     * or not a single trailing argument is interpreted as a whole
-     * array or a single element of an array to be collected.
-     * Note that the dynamic type of the trailing argument has no
-     * effect on this decision, only a comparison between the static
-     * type descriptor of the call site and the type of the method handle.)
-     * <p style="font-size:smaller;">
-     * As a result of the previously stated rules, the variable arity behavior
-     * of a method handle may be suppressed, by binding it to the exact invoker
-     * of its own type, as follows:
-     * <blockquote><pre>
-MethodHandle vamh = publicLookup()
-  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
-  .asVarargsCollector(Object[].class);
-MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
-assert(vamh.type().equals(mh.type()));
-assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString());
-boolean failed = false;
-try { mh.invokeGeneric(1,2,3); }
-catch (WrongMethodTypeException ex) { failed = true; }
-assert(failed);
-     * </pre></blockquote>
-     * This transformation has no behavioral effect if the method handle is
-     * not of variable arity.
-     *
-     * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
-     * @return a new method handle which can collect any number of trailing arguments
-     *         into an array, before calling the original method handle
-     * @throws IllegalArgumentException if {@code arrayType} is not an array type
-     *         or {@code arrayType} is not assignable to this method handle's trailing parameter type
-     * @see #asCollector
-     * @see #isVarargsCollector
-     */
-    public MethodHandle asVarargsCollector(Class<?> arrayType) {
-        Class<?> arrayElement = arrayType.getComponentType();
-        if (arrayElement == null)  throw newIllegalArgumentException("not an array type");
-        return MethodHandles.asVarargsCollector(this, arrayType);
-    }
-
-    /**
-     * Determine if this method handle
-     * supports {@linkplain #asVarargsCollector variable arity} calls.
-     * Such method handles arise from the following sources:
-     * <ul>
-     * <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
-     * <li>a call to a {@linkplain java.dyn.MethodHandles.Lookup lookup method}
-     *     which resolves to a variable arity Java method or constructor
-     * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
-     *     which resolves to a variable arity Java method or constructor
-     * </ul>
-     * @return true if this method handle accepts more than one arity of {@code invokeGeneric} calls
-     * @see #asVarargsCollector
-     */
-    public boolean isVarargsCollector() {
-        return false;
-    }
-
-    /**
-     * Bind a value {@code x} to the first argument of a method handle, without invoking it.
-     * The new method handle adapts, as its <i>target</i>,
-     * to the current method handle.
-     * 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
-     * @see MethodHandles#insertArguments
-     */
-    public MethodHandle bindTo(Object x) {
-        return MethodHandles.insertArguments(this, 0, x);
-    }
-
-    /**
-     * Returns a string representation of the method handle,
-     * starting with the string {@code "MethodHandle"} and
-     * ending with the string representation of the method handle's type.
-     * In other words, this method returns a string equal to the value of:
-     * <blockquote><pre>
-     * "MethodHandle" + type().toString()
-     * </pre></blockquote>
-     * <p>
-     * Note:  Future releases of this API may add further information
-     * to the string representation.
-     * Therefore, the present syntax should not be parsed by applications.
-     *
-     * @return a string representation of the method handle
-     */
-    @Override
-    public String toString() {
-        return MethodHandleImpl.getNameString(IMPL_TOKEN, this);
-    }
-}
--- a/jdk/src/share/classes/java/dyn/MethodHandles.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2339 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.lang.reflect.*;
-import sun.dyn.Access;
-import sun.dyn.MemberName;
-import sun.dyn.MethodHandleImpl;
-import sun.dyn.WrapperInstance;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.VerifyAccess;
-import sun.dyn.util.Wrapper;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import sun.dyn.Invokers;
-import sun.dyn.MethodTypeImpl;
-import sun.reflect.Reflection;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-import static sun.dyn.MemberName.newNoAccessException;
-
-/**
- * This class consists exclusively of static methods that operate on or return
- * method handles. They fall into several categories:
- * <ul>
- * <li>Lookup methods which help create method handles for methods and fields.
- * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
- * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
- * <li>Wrapper methods which can convert between method handles and other function-like "SAM types".
- * </ul>
- * <p>
- * @author John Rose, JSR 292 EG
- */
-public class MethodHandles {
-
-    private MethodHandles() { }  // do not instantiate
-
-    private static final Access IMPL_TOKEN = Access.getToken();
-    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
-    static { MethodHandleImpl.initStatics(); }
-    // See IMPL_LOOKUP below.
-
-    //// Method handle creation from ordinary methods.
-
-    /**
-     * Return a {@link Lookup lookup object} on the caller,
-     * which has the capability to access any method handle that the caller has access to,
-     * including direct method handles to private fields and methods.
-     * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
-     * Do not store it in place where untrusted code can access it.
-     */
-    public static Lookup lookup() {
-        return new Lookup();
-    }
-
-    /**
-     * Return a {@link Lookup lookup object} which is trusted minimally.
-     * It can only be used to create method handles to
-     * publicly accessible fields and methods.
-     * <p>
-     * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
-     * of this lookup object will be {@link java.lang.Object}.
-     * <p>
-     * The lookup class can be changed to any other class {@code C} using an expression of the form
-     * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
-     * Since all classes have equal access to public names,
-     * such a change would confer no new access rights.
-     */
-    public static Lookup publicLookup() {
-        return Lookup.PUBLIC_LOOKUP;
-    }
-
-    /**
-     * A <em>lookup object</em> is a factory for creating method handles,
-     * when the creation requires access checking.
-     * Method handles do not perform
-     * access checks when they are called, but rather when they are created.
-     * Therefore, method handle access
-     * restrictions must be enforced when a method handle is created.
-     * The caller class against which those restrictions are enforced
-     * is known as the {@linkplain #lookupClass lookup class}.
-     * <p>
-     * A lookup class which needs to create method handles will call
-     * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
-     * When the {@code Lookup} factory object is created, the identity of the lookup class is
-     * determined, and securely stored in the {@code Lookup} object.
-     * The lookup class (or its delegates) may then use factory methods
-     * on the {@code Lookup} object to create method handles for access-checked members.
-     * This includes all methods, constructors, and fields which are allowed to the lookup class,
-     * even private ones.
-     * <p>
-     * The factory methods on a {@code Lookup} object correspond to all major
-     * use cases for methods, constructors, and fields.
-     * Here is a summary of the correspondence between these factory methods and
-     * the behavior the resulting method handles:
-     * <code>
-     * <table border=1 cellpadding=5 summary="lookup method behaviors">
-     * <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
-     *     <td>FT f;</td><td>(T) this.f;</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
-     *     <td>static<br>FT f;</td><td>(T) C.f;</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
-     *     <td>FT f;</td><td>this.f = x;</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
-     *     <td>static<br>FT f;</td><td>C.f = arg;</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
-     *     <td>T m(A*);</td><td>(T) this.m(arg*);</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
-     *     <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
-     *     <td>T m(A*);</td><td>(T) super.m(arg*);</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
-     *     <td>C(A*);</td><td>(T) new C(arg*);</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
-     *     <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
-     *     <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
-     *     <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
-     *     <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td>
-     * </tr>
-     * <tr>
-     *     <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
-     *     <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
-     * </tr>
-     * </table>
-     * </code>
-     * Here, the type {@code C} is the class or interface being searched for a member,
-     * documented as a parameter named {@code refc} in the lookup methods.
-     * The method or constructor type {@code MT} is composed from the return type {@code T}
-     * and the sequence of argument types {@code A*}.
-     * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
-     * The formal parameter {@code this} stands for the self-reference of type {@code C};
-     * if it is present, it is always the leading argument to the method handle invocation.
-     * The name {@code arg} stands for all the other method handle arguments.
-     * In the code examples for the Core Reflection API, the name {@code thisOrNull}
-     * stands for a null reference if the accessed method or field is static,
-     * and {@code this} otherwise.
-     * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
-     * for reflective objects corresponding to the given members.
-     * <p>
-     * The equivalence between looked-up method handles and underlying
-     * class members can break down in a few ways:
-     * <ul>
-     * <li>If {@code C} is not symbolically accessible from the lookup class's loader,
-     * the lookup can still succeed, even when there is no equivalent
-     * Java expression or bytecoded constant.
-     * <li>Likewise, if {@code T} or {@code MT}
-     * is not symbolically accessible from the lookup class's loader,
-     * the lookup can still succeed.
-     * For example, lookups for {@code MethodHandle.invokeExact} and
-     * {@code MethodHandle.invokeGeneric} will always succeed, regardless of requested type.
-     * <li>If there is a security manager installed, it can forbid the lookup
-     * on various grounds (<a href="#secmgr">see below</a>).
-     * By contrast, the {@code ldc} instruction is not subject to
-     * security manager checks.
-     * </ul>
-     *
-     * <h3><a name="access"></a>Access checking</h3>
-     * Access checks are applied in the factory methods of {@code Lookup},
-     * when a method handle is created.
-     * This is a key difference from the Core Reflection API, since
-     * {@link java.lang.reflect.Method#invoke Method.invoke}
-     * performs access checking against every caller, on every call.
-     * <p>
-     * All access checks start from a {@code Lookup} object, which
-     * compares its recorded lookup class against all requests to
-     * create method handles.
-     * A single {@code Lookup} object can be used to create any number
-     * of access-checked method handles, all checked against a single
-     * lookup class.
-     * <p>
-     * A {@code Lookup} object can be shared with other trusted code,
-     * such as a metaobject protocol.
-     * A shared {@code Lookup} object delegates the capability
-     * to create method handles on private members of the lookup class.
-     * Even if privileged code uses the {@code Lookup} object,
-     * the access checking is confined to the privileges of the
-     * original lookup class.
-     * <p>
-     * A lookup can fail, because
-     * the containing class is not accessible to the lookup class, or
-     * because the desired class member is missing, or because the
-     * desired class member is not accessible to the lookup class.
-     * In any of these cases, a {@code ReflectiveOperationException} will be
-     * thrown from the attempted lookup.  The exact class will be one of
-     * the following:
-     * <ul>
-     * <li>NoSuchMethodException &mdash; if a method is requested but does not exist
-     * <li>NoSuchFieldException &mdash; if a field is requested but does not exist
-     * <li>IllegalAccessException &mdash; if the member exists but an access check fails
-     * </ul>
-     * <p>
-     * In general, the conditions under which a method handle may be
-     * looked up for a method {@code M} are exactly equivalent to the conditions
-     * under which the lookup class could have compiled and resolved a call to {@code M}.
-     * And the effect of invoking the method handle resulting from the lookup
-     * is exactly equivalent to executing the compiled and resolved call to {@code M}.
-     * The same point is true of fields and constructors.
-     * <p>
-     * In some cases, access between nested classes is obtained by the Java compiler by creating
-     * an wrapper method to access a private method of another class
-     * in the same top-level declaration.
-     * For example, a nested class {@code C.D}
-     * can access private members within other related classes such as
-     * {@code C}, {@code C.D.E}, or {@code C.B},
-     * but the Java compiler may need to generate wrapper methods in
-     * those related classes.  In such cases, a {@code Lookup} object on
-     * {@code C.E} would be unable to those private members.
-     * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
-     * which can transform a lookup on {@code C.E} into one on any of those other
-     * classes, without special elevation of privilege.
-     * <p>
-     * Although bytecode instructions can only refer to classes in
-     * a related class loader, this API can search for methods in any
-     * class, as long as a reference to its {@code Class} object is
-     * available.  Such cross-loader references are also possible with the
-     * Core Reflection API, and are impossible to bytecode instructions
-     * such as {@code invokestatic} or {@code getfield}.
-     * There is a {@linkplain java.lang.SecurityManager security manager API}
-     * to allow applications to check such cross-loader references.
-     * These checks apply to both the {@code MethodHandles.Lookup} API
-     * and the Core Reflection API
-     * (as found on {@link java.lang.Class Class}).
-     * <p>
-     * Access checks only apply to named and reflected methods,
-     * constructors, and fields.
-     * Other method handle creation methods, such as
-     * {@link #convertArguments MethodHandles.convertArguments},
-     * do not require any access checks, and are done
-     * with static methods of {@link MethodHandles},
-     * independently of any {@code Lookup} object.
-     *
-     * <h3>Security manager interactions</h3>
-     * <a name="secmgr"></a>
-     * If a security manager is present, member lookups are subject to
-     * additional checks.
-     * From one to four calls are made to the security manager.
-     * Any of these calls can refuse access by throwing a
-     * {@link java.lang.SecurityException SecurityException}.
-     * Define {@code smgr} as the security manager,
-     * {@code refc} as the containing class in which the member
-     * is being sought, and {@code defc} as the class in which the
-     * member is actually defined.
-     * The calls are made according to the following rules:
-     * <ul>
-     * <li>In all cases, {@link SecurityManager#checkMemberAccess
-     *     smgr.checkMemberAccess(refc, Member.PUBLIC)} is called.
-     * <li>If the class loader of the lookup class is not
-     *     the same as or an ancestor of the class loader of {@code refc},
-     *     then {@link SecurityManager#checkPackageAccess
-     *     smgr.checkPackageAccess(refcPkg)} is called,
-     *     where {@code refcPkg} is the package of {@code refc}.
-     * <li>If the retrieved member is not public,
-     *     {@link SecurityManager#checkMemberAccess
-     *     smgr.checkMemberAccess(defc, Member.DECLARED)} is called.
-     *     (Note that {@code defc} might be the same as {@code refc}.)
-     * <li>If the retrieved member is not public,
-     *     and if {@code defc} and {@code refc} are in different class loaders,
-     *     and if the class loader of the lookup class is not
-     *     the same as or an ancestor of the class loader of {@code defc},
-     *     then {@link SecurityManager#checkPackageAccess
-     *     smgr.checkPackageAccess(defcPkg)} is called,
-     *     where {@code defcPkg} is the package of {@code defc}.
-     * </ul>
-     * In all cases, the requesting class presented to the security
-     * manager will be the lookup class from the current {@code Lookup} object.
-     */
-    public static final
-    class Lookup {
-        /** The class on behalf of whom the lookup is being performed. */
-        private final Class<?> lookupClass;
-
-        /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
-        private final int allowedModes;
-
-        /** A single-bit mask representing {@code public} access,
-         *  which may contribute to the result of {@link #lookupModes lookupModes}.
-         *  The value, {@code 0x01}, happens to be the same as the value of the
-         *  {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
-         */
-        public static final int PUBLIC = Modifier.PUBLIC;
-
-        /** A single-bit mask representing {@code private} access,
-         *  which may contribute to the result of {@link #lookupModes lookupModes}.
-         *  The value, {@code 0x02}, happens to be the same as the value of the
-         *  {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
-         */
-        public static final int PRIVATE = Modifier.PRIVATE;
-
-        /** A single-bit mask representing {@code protected} access,
-         *  which may contribute to the result of {@link #lookupModes lookupModes}.
-         *  The value, {@code 0x04}, happens to be the same as the value of the
-         *  {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
-         */
-        public static final int PROTECTED = Modifier.PROTECTED;
-
-        /** A single-bit mask representing {@code package} access (default access),
-         *  which may contribute to the result of {@link #lookupModes lookupModes}.
-         *  The value is {@code 0x08}, which does not correspond meaningfully to
-         *  any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
-         */
-        public static final int PACKAGE = Modifier.STATIC;
-
-        private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
-        private static final int TRUSTED   = -1;
-
-        private static int fixmods(int mods) {
-            mods &= (ALL_MODES - PACKAGE);
-            return (mods != 0) ? mods : PACKAGE;
-        }
-
-        /** Tells which class is performing the lookup.  It is this class against
-         *  which checks are performed for visibility and access permissions.
-         *  <p>
-         *  The class implies a maximum level of access permission,
-         *  but the permissions may be additionally limited by the bitmask
-         *  {@link #lookupModes lookupModes}, which controls whether non-public members
-         *  can be accessed.
-         */
-        public Class<?> lookupClass() {
-            return lookupClass;
-        }
-
-        // This is just for calling out to MethodHandleImpl.
-        private Class<?> lookupClassOrNull() {
-            return (allowedModes == TRUSTED) ? null : lookupClass;
-        }
-
-        /** Tells which access-protection classes of members this lookup object can produce.
-         *  The result is a bit-mask of the bits
-         *  {@linkplain #PUBLIC PUBLIC (0x01)},
-         *  {@linkplain #PRIVATE PRIVATE (0x02)},
-         *  {@linkplain #PROTECTED PROTECTED (0x04)},
-         *  and {@linkplain #PACKAGE PACKAGE (0x08)}.
-         *  <p>
-         *  A freshly-created lookup object
-         *  on the {@linkplain java.dyn.MethodHandles#lookup() caller's class}
-         *  has all possible bits set, since the caller class can access all its own members.
-         *  A lookup object on a new lookup class
-         *  {@linkplain java.dyn.MethodHandles.Lookup#in created from a previous lookup object}
-         *  may have some mode bits set to zero.
-         *  The purpose of this is to restrict access via the new lookup object,
-         *  so that it can access only names which can be reached by the original
-         *  lookup object, and also by the new lookup class.
-         */
-        public int lookupModes() {
-            return allowedModes & ALL_MODES;
-        }
-
-        /** Embody the current class (the lookupClass) as a lookup class
-         * for method handle creation.
-         * Must be called by from a method in this package,
-         * which in turn is called by a method not in this package.
-         * <p>
-         * Also, don't make it private, lest javac interpose
-         * an access$N method.
-         */
-        Lookup() {
-            this(getCallerClassAtEntryPoint(), ALL_MODES);
-            // make sure we haven't accidentally picked up a privileged class:
-            checkUnprivilegedlookupClass(lookupClass);
-        }
-
-        Lookup(Access token, Class<?> lookupClass) {
-            this(lookupClass, ALL_MODES);
-            Access.check(token);
-        }
-
-        private Lookup(Class<?> lookupClass, int allowedModes) {
-            this.lookupClass = lookupClass;
-            this.allowedModes = allowedModes;
-        }
-
-        /**
-         * Creates a lookup on the specified new lookup class.
-         * The resulting object will report the specified
-         * class as its own {@link #lookupClass lookupClass}.
-         * <p>
-         * However, the resulting {@code Lookup} object is guaranteed
-         * to have no more access capabilities than the original.
-         * In particular, access capabilities can be lost as follows:<ul>
-         * <li>If the new lookup class differs from the old one,
-         * protected members will not be accessible by virtue of inheritance.
-         * (Protected members may continue to be accessible because of package sharing.)
-         * <li>If the new lookup class is in a different package
-         * than the old one, protected and default (package) members will not be accessible.
-         * <li>If the new lookup class is not within the same package member
-         * as the old one, private members will not be accessible.
-         * <li>If the new lookup class is not accessible to the old lookup class,
-         * then no members, not even public members, will be accessible.
-         * (In all other cases, public members will continue to be accessible.)
-         * </ul>
-         *
-         * @param requestedLookupClass the desired lookup class for the new lookup object
-         * @return a lookup object which reports the desired lookup class
-         * @throws NullPointerException if the argument is null
-         */
-        public Lookup in(Class<?> requestedLookupClass) {
-            requestedLookupClass.getClass();  // null check
-            if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
-                return new Lookup(requestedLookupClass, ALL_MODES);
-            if (requestedLookupClass == this.lookupClass)
-                return this;  // keep same capabilities
-            int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
-            if ((newModes & PACKAGE) != 0
-                && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
-                newModes &= ~(PACKAGE|PRIVATE);
-            }
-            // Allow nestmate lookups to be created without special privilege:
-            if ((newModes & PRIVATE) != 0
-                && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
-                newModes &= ~PRIVATE;
-            }
-            if (newModes == PUBLIC
-                && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass)) {
-                // The requested class it not accessible from the lookup class.
-                // No permissions.
-                newModes = 0;
-            }
-            checkUnprivilegedlookupClass(requestedLookupClass);
-            return new Lookup(requestedLookupClass, newModes);
-        }
-
-        // Make sure outer class is initialized first.
-        static { IMPL_TOKEN.getClass(); }
-
-        /** Version of lookup which is trusted minimally.
-         *  It can only be used to create method handles to
-         *  publicly accessible members.
-         */
-        static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
-
-        /** Package-private version of lookup which is trusted. */
-        static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
-        static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
-
-        private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
-            String name = lookupClass.getName();
-            if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
-                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
-        }
-
-        /**
-         * Displays the name of the class from which lookups are to be made.
-         * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
-         * If there are restrictions on the access permitted to this lookup,
-         * this is indicated by adding a suffix to the class name, consisting
-         * of a slash and a keyword.  The keyword represents the strongest
-         * allowed access, and is chosen as follows:
-         * <ul>
-         * <li>If no access is allowed, the suffix is "/noaccess".
-         * <li>If only public access is allowed, the suffix is "/public".
-         * <li>If only public and package access are allowed, the suffix is "/package".
-         * <li>If only public, package, and private access are allowed, the suffix is "/private".
-         * </ul>
-         * If none of the above cases apply, it is the case that full
-         * access (public, package, private, and protected) is allowed.
-         * In this case, no suffix is added.
-         * This is true only of an object obtained originally from
-         * {@link java.dyn.MethodHandles#lookup MethodHandles.lookup}.
-         * Objects created by {@link java.dyn.MethodHandles.Lookup#in Lookup.in}
-         * always have restricted access, and will display a suffix.
-         * <p>
-         * (It may seem strange that protected access should be
-         * stronger than private access.  Viewed independently from
-         * package access, protected access is the first to be lost,
-         * because it requires a direct subclass relationship between
-         * caller and callee.)
-         * @see #in
-         */
-        @Override
-        public String toString() {
-            String cname = lookupClass.getName();
-            switch (allowedModes) {
-            case 0:  // no privileges
-                return cname + "/noaccess";
-            case PUBLIC:
-                return cname + "/public";
-            case PUBLIC|PACKAGE:
-                return cname + "/package";
-            case ALL_MODES & ~PROTECTED:
-                return cname + "/private";
-            case ALL_MODES:
-                return cname;
-            case TRUSTED:
-                return "/trusted";  // internal only; not exported
-            default:  // Should not happen, but it's a bitfield...
-                cname = cname + "/" + Integer.toHexString(allowedModes);
-                assert(false) : cname;
-                return cname;
-            }
-        }
-
-        // call this from an entry point method in Lookup with extraFrames=0.
-        private static Class<?> getCallerClassAtEntryPoint() {
-            final int CALLER_DEPTH = 4;
-            // 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);
-        }
-
-        /**
-         * Produces 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 {@link #findVirtual findVirtual} or {@link #findSpecial 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.
-         * <p>
-         * The returned method handle will have
-         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
-         * the method's variable arity modifier bit ({@code 0x0080}) is set.
-         * @param refc the class from which the method is accessed
-         * @param name the name of the method
-         * @param type the type of the method
-         * @return the desired method handle
-         * @throws NoSuchMethodException if the method does not exist
-         * @throws IllegalAccessException if access checking fails, or if the method is not {@code static}
-         * @exception SecurityException if a security manager is present and it
-         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-         * @throws NullPointerException if any argument is null
-         */
-        public
-        MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
-            MemberName method = resolveOrFail(refc, name, type, true);
-            checkMethod(refc, method, true);
-            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
-        }
-
-        /**
-         * Produces a method handle for a virtual method.
-         * The type of the method handle will be that of the method,
-         * with the receiver type (usually {@code refc}) prepended.
-         * The method and all its argument types must be accessible to the lookup class.
-         * <p>
-         * When called, the handle will treat the first argument as a receiver
-         * and dispatch on the receiver's type to determine which method
-         * implementation to enter.
-         * (The dispatching action is identical with that performed by an
-         * {@code invokevirtual} or {@code invokeinterface} instruction.)
-         * <p>
-         * The returned method handle will have
-         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
-         * the method's variable arity modifier bit ({@code 0x0080}) is set.
-         * <p>
-         * Because of the general equivalence between {@code invokevirtual}
-         * instructions and method handles produced by {@code findVirtual},
-         * if the class is {@code MethodHandle} and the name string is
-         * {@code invokeExact} or {@code invokeGeneric}, the resulting
-         * method handle is equivalent to one produced by
-         * {@link java.dyn.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
-         * {@link java.dyn.MethodHandles#genericInvoker MethodHandles.genericInvoker}
-         * with the same {@code type} argument.
-         *
-         * @param refc the class or interface 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
-         * @return the desired method handle
-         * @throws NoSuchMethodException if the method does not exist
-         * @throws IllegalAccessException if access checking fails, or if the method is {@code static}
-         * @exception SecurityException if a security manager is present and it
-         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-         * @throws NullPointerException if any argument is null
-         */
-        public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
-            MemberName method = resolveOrFail(refc, name, type, false);
-            checkMethod(refc, method, false);
-            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
-            return restrictProtectedReceiver(method, mh);
-        }
-
-        /**
-         * Produces a method handle which creates an object and initializes it, using
-         * the constructor of the specified type.
-         * The parameter types of the method handle will be those of the constructor,
-         * while the return type will be a reference to the constructor's class.
-         * The constructor and all its argument types must be accessible to the lookup class.
-         * If the constructor's class has not yet been initialized, that is done
-         * immediately, before the method handle is returned.
-         * <p>
-         * Note:  The requested type must have a return type of {@code void}.
-         * This is consistent with the JVM's treatment of constructor type descriptors.
-         * <p>
-         * The returned method handle will have
-         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
-         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
-         * @param refc the class or interface from which the method is accessed
-         * @param type the type of the method, with the receiver argument omitted, and a void return type
-         * @return the desired method handle
-         * @throws NoSuchMethodException if the constructor does not exist
-         * @throws IllegalAccessException if access checking fails
-         * @exception SecurityException if a security manager is present and it
-         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-         * @throws NullPointerException if any argument is null
-         */
-        public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
-            String name = "<init>";
-            MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
-            assert(ctor.isConstructor());
-            checkAccess(refc, ctor);
-            MethodHandle rawMH = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
-            MethodHandle allocMH = MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawMH);
-            return fixVarargs(allocMH, rawMH);
-        }
-
-        /** Return a version of MH which matches matchMH w.r.t. isVarargsCollector. */
-        private static MethodHandle fixVarargs(MethodHandle mh, MethodHandle matchMH) {
-            boolean va1 = mh.isVarargsCollector();
-            boolean va2 = matchMH.isVarargsCollector();
-            if (va1 == va2) {
-                return mh;
-            } else if (va2) {
-                MethodType type = mh.type();
-                int arity = type.parameterCount();
-                return mh.asVarargsCollector(type.parameterType(arity-1));
-            } else {
-                throw new InternalError("already varargs, but template is not: "+mh);
-            }
-        }
-
-        /**
-         * Produces an early-bound method handle for a virtual method,
-         * as if called from an {@code invokespecial}
-         * instruction from {@code caller}.
-         * The type of the method handle will be that of the method,
-         * with a suitably restricted receiver type (such as {@code caller}) prepended.
-         * The method and all its argument types must be accessible
-         * to the caller.
-         * <p>
-         * When called, the handle will treat the first argument as a receiver,
-         * but will not dispatch on the receiver's type.
-         * (This direct invocation action is identical with that performed by an
-         * {@code invokespecial} instruction.)
-         * <p>
-         * If the explicitly specified caller class is not identical with the
-         * lookup class, or if this lookup object does not have private access
-         * privileges, the access fails.
-         * <p>
-         * The returned method handle will have
-         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
-         * the method's variable arity modifier bit ({@code 0x0080}) is set.
-         * @param refc the class or interface from which the method is accessed
-         * @param name the name of the method (which must not be "&lt;init&gt;")
-         * @param type the type of the method, with the receiver argument omitted
-         * @param specialCaller the proposed calling class to perform the {@code invokespecial}
-         * @return the desired method handle
-         * @throws NoSuchMethodException if the method does not exist
-         * @throws IllegalAccessException if access checking fails
-         * @exception SecurityException if a security manager is present and it
-         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-         * @throws NullPointerException if any argument is null
-         */
-        public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
-                                        Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
-            checkSpecialCaller(specialCaller);
-            MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
-            checkMethod(refc, method, false);
-            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
-            return restrictReceiver(method, mh, specialCaller);
-        }
-
-        /**
-         * Produces a method handle giving read access to a non-static field.
-         * The type of the method handle will have a return type of the field's
-         * value type.
-         * The method handle's single argument will be the instance containing
-         * the field.
-         * Access checking is performed immediately on behalf of the lookup class.
-         * @param refc the class or interface from which the method is accessed
-         * @param name the field's name
-         * @param type the field's type
-         * @return a method handle which can load values from the field
-         * @throws NoSuchFieldException if the field does not exist
-         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
-         * @exception SecurityException if a security manager is present and it
-         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-         * @throws NullPointerException if any argument is null
-         */
-        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
-            return makeAccessor(refc, name, type, false, false);
-        }
-
-        /**
-         * Produces a method handle giving write access to a non-static field.
-         * The type of the method handle will have a void return type.
-         * The method handle will take two arguments, the instance containing
-         * the field, and the value to be stored.
-         * The second argument will be of the field's value type.
-         * Access checking is performed immediately on behalf of the lookup class.
-         * @param refc the class or interface from which the method is accessed
-         * @param name the field's name
-         * @param type the field's type
-         * @return a method handle which can store values into the field
-         * @throws NoSuchFieldException if the field does not exist
-         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
-         * @exception SecurityException if a security manager is present and it
-         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-         * @throws NullPointerException if any argument is null
-         */
-        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
-            return makeAccessor(refc, name, type, false, true);
-        }
-
-        /**
-         * Produces a method handle giving read access to a static field.
-         * The type of the method handle will have a return type of the field's
-         * value type.
-         * The method handle will take no arguments.
-         * Access checking is performed immediately on behalf of the lookup class.
-         * @param refc the class or interface from which the method is accessed
-         * @param name the field's name
-         * @param type the field's type
-         * @return a method handle which can load values from the field
-         * @throws NoSuchFieldException if the field does not exist
-         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
-         * @exception SecurityException if a security manager is present and it
-         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-         * @throws NullPointerException if any argument is null
-         */
-        public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
-            return makeAccessor(refc, name, type, true, false);
-        }
-
-        /**
-         * Produces a method handle giving write access to a static field.
-         * The type of the method handle will have a void return type.
-         * The method handle will take a single
-         * argument, of the field's value type, the value to be stored.
-         * Access checking is performed immediately on behalf of the lookup class.
-         * @param refc the class or interface from which the method is accessed
-         * @param name the field's name
-         * @param type the field's type
-         * @return a method handle which can store values into the field
-         * @throws NoSuchFieldException if the field does not exist
-         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
-         * @exception SecurityException if a security manager is present and it
-         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-         * @throws NullPointerException if any argument is null
-         */
-        public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
-            return makeAccessor(refc, name, type, true, true);
-        }
-
-        /**
-         * Produces an early-bound method handle for a non-static method.
-         * 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,
-         * 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>
-         * The returned method handle will have
-         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
-         * the method's variable arity modifier bit ({@code 0x0080}) is set
-         * <em>and</em> the trailing array argument is not the only argument.
-         * (If the trailing array argument is the only argument,
-         * the given receiver value will be bound to it.)
-         * <p>
-         * This is equivalent to the following code:
-         * <blockquote><pre>
-MethodHandle mh0 = {@link #findVirtual findVirtual}(defc, name, type);
-MethodHandle mh1 = mh0.{@link MethodHandle#bindTo bindTo}(receiver);
-MethodType mt1 = mh1.type();
-if (mh0.isVarargsCollector() && mt1.parameterCount() > 0) {
-  mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
-return mh1;
-         * </pre></blockquote>
-         * 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.
-         * (Note that {@code bindTo} does not preserve variable arity.)
-         * @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
-         * @return the desired method handle
-         * @throws NoSuchMethodException if the method does not exist
-         * @throws IllegalAccessException if access checking fails
-         * @exception SecurityException if a security manager is present and it
-         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
-         * @throws NullPointerException if any argument is null
-         */
-        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
-            Class<? extends Object> refc = receiver.getClass(); // may get NPE
-            MemberName method = resolveOrFail(refc, name, type, false);
-            checkMethod(refc, method, false);
-            MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
-            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
-            if (bmh == null)
-                throw newNoAccessException(method, this);
-            if (dmh.type().parameterCount() == 0)
-                return dmh;  // bound the trailing parameter; no varargs possible
-            return fixVarargs(bmh, dmh);
-        }
-
-        /**
-         * 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.
-         * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
-         * The type of the method handle will be that of the method,
-         * with the receiver type prepended (but only if it is non-static).
-         * If the method's {@code accessible} flag is not set,
-         * access checking is performed immediately on behalf of the lookup class.
-         * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
-         * <p>
-         * The returned method handle will have
-         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
-         * the method's variable arity modifier bit ({@code 0x0080}) is set.
-         * @param m the reflected method
-         * @return a method handle which can invoke the reflected method
-         * @throws IllegalAccessException if access checking fails
-         * @throws NullPointerException if the argument is null
-         */
-        public MethodHandle unreflect(Method m) throws IllegalAccessException {
-            MemberName method = new MemberName(m);
-            assert(method.isMethod());
-            if (!m.isAccessible())  checkMethod(method.getDeclaringClass(), method, method.isStatic());
-            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
-            if (!m.isAccessible())  mh = restrictProtectedReceiver(method, mh);
-            return mh;
-        }
-
-        /**
-         * Produces a method handle for a reflected method.
-         * It will bypass checks for overriding methods on the receiver,
-         * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
-         * The type of the method handle will be that of the method,
-         * with the special caller type prepended (and <em>not</em> the receiver of the method).
-         * If the method'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.
-         * <p>
-         * The returned method handle will have
-         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
-         * the method's variable arity modifier bit ({@code 0x0080}) is set.
-         * @param m the reflected method
-         * @param specialCaller the class nominally calling the method
-         * @return a method handle which can invoke the reflected method
-         * @throws IllegalAccessException if access checking fails
-         * @throws NullPointerException if any argument is null
-         */
-        public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
-            checkSpecialCaller(specialCaller);
-            MemberName method = new MemberName(m);
-            assert(method.isMethod());
-            // ignore m.isAccessible:  this is a new kind of access
-            checkMethod(m.getDeclaringClass(), method, false);
-            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
-            return restrictReceiver(method, mh, specialCaller);
-        }
-
-        /**
-         * Produces a method handle for a reflected 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.
-         * <p>
-         * The returned method handle will have
-         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
-         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
-         * @param c the reflected constructor
-         * @return a method handle which can invoke the reflected constructor
-         * @throws IllegalAccessException if access checking fails
-         * @throws NullPointerException if the argument is null
-         */
-        public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException {
-            MemberName ctor = new MemberName(c);
-            assert(ctor.isConstructor());
-            if (!c.isAccessible())  checkAccess(c.getDeclaringClass(), ctor);
-            MethodHandle rawCtor = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
-            MethodHandle allocator = MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawCtor);
-            return fixVarargs(allocator, rawCtor);
-        }
-
-        /**
-         * Produces 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.
-         * 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
-         * @return a method handle which can load values from the reflected field
-         * @throws IllegalAccessException if access checking fails
-         * @throws NullPointerException if the argument is null
-         */
-        public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
-            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
-        }
-
-        /**
-         * Produces a method handle giving write access to a reflected field.
-         * The type of the method handle will have a void return type.
-         * 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
-         * @return a method handle which can store values into the reflected field
-         * @throws IllegalAccessException if access checking fails
-         * @throws NullPointerException if the argument is null
-         */
-        public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
-            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
-        }
-
-        /// Helper methods, all package-private.
-
-        MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoSuchFieldException, IllegalAccessException {
-            checkSymbolicClass(refc);  // do this before attempting to resolve
-            name.getClass(); type.getClass();  // NPE
-            int mods = (isStatic ? Modifier.STATIC : 0);
-            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
-                                            NoSuchFieldException.class);
-        }
-
-        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoSuchMethodException, IllegalAccessException {
-            checkSymbolicClass(refc);  // do this before attempting to resolve
-            name.getClass(); type.getClass();  // NPE
-            int mods = (isStatic ? Modifier.STATIC : 0);
-            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
-                                            NoSuchMethodException.class);
-        }
-
-        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
-                                 boolean searchSupers, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
-            checkSymbolicClass(refc);  // do this before attempting to resolve
-            name.getClass(); type.getClass();  // NPE
-            int mods = (isStatic ? Modifier.STATIC : 0);
-            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller,
-                                            NoSuchMethodException.class);
-        }
-
-        void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
-            Class<?> caller = lookupClassOrNull();
-            if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
-                throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), this);
-        }
-
-        void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws IllegalAccessException {
-            String message;
-            if (m.isConstructor())
-                message = "expected a method, not a constructor";
-            else if (!m.isMethod())
-                message = "expected a method";
-            else if (wantStatic != m.isStatic())
-                message = wantStatic ? "expected a static method" : "expected a non-static method";
-            else
-                { checkAccess(refc, m); return; }
-            throw newNoAccessException(message, m, this);
-        }
-
-        void checkAccess(Class<?> refc, MemberName m) throws IllegalAccessException {
-            int allowedModes = this.allowedModes;
-            if (allowedModes == TRUSTED)  return;
-            int mods = m.getModifiers();
-            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
-                return;  // common case
-            int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
-            if ((requestedModes & allowedModes) != 0
-                && VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
-                                                   mods, lookupClass()))
-                return;
-            if (((requestedModes & ~allowedModes) & PROTECTED) != 0
-                && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
-                // Protected members can also be checked as if they were package-private.
-                return;
-            throw newNoAccessException(accessFailedMessage(refc, m), m, this);
-        }
-
-        String accessFailedMessage(Class<?> refc, MemberName m) {
-            Class<?> defc = m.getDeclaringClass();
-            int mods = m.getModifiers();
-            // check the class first:
-            boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
-                               (defc == refc ||
-                                Modifier.isPublic(refc.getModifiers())));
-            if (!classOK && (allowedModes & PACKAGE) != 0) {
-                classOK = (VerifyAccess.isClassAccessible(defc, lookupClass()) &&
-                           (defc == refc ||
-                            VerifyAccess.isClassAccessible(refc, lookupClass())));
-            }
-            if (!classOK)
-                return "class is not public";
-            if (Modifier.isPublic(mods))
-                return "access to public member failed";  // (how?)
-            if (Modifier.isPrivate(mods))
-                return "member is private";
-            if (Modifier.isProtected(mods))
-                return "member is protected";
-            return "member is private to package";
-        }
-
-        private static final boolean ALLOW_NESTMATE_ACCESS = false;
-
-        void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
-            if (allowedModes == TRUSTED)  return;
-            if ((allowedModes & PRIVATE) == 0
-                || (specialCaller != lookupClass()
-                    && !(ALLOW_NESTMATE_ACCESS &&
-                         VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
-                throw newNoAccessException("no private access for invokespecial",
-                                           new MemberName(specialCaller), this);
-        }
-
-        MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws IllegalAccessException {
-            // The accessing class only has the right to use a protected member
-            // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
-            if (!method.isProtected() || method.isStatic()
-                || allowedModes == TRUSTED
-                || method.getDeclaringClass() == lookupClass()
-                || (ALLOW_NESTMATE_ACCESS &&
-                    VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
-                return mh;
-            else
-                return restrictReceiver(method, mh, lookupClass());
-        }
-        MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException {
-            assert(!method.isStatic());
-            Class<?> defc = method.getDeclaringClass();  // receiver type of mh is too wide
-            if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
-                throw newNoAccessException("caller class must be a subclass below the method", method, caller);
-            }
-            MethodType rawType = mh.type();
-            if (rawType.parameterType(0) == caller)  return mh;
-            MethodType narrowType = rawType.changeParameterType(0, caller);
-            MethodHandle narrowMH = MethodHandleImpl.convertArguments(IMPL_TOKEN, mh, narrowType, rawType, null);
-            return fixVarargs(narrowMH, mh);
-        }
-
-        MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type,
-                                  boolean isStatic, boolean isSetter) throws NoSuchFieldException, IllegalAccessException {
-            MemberName field = resolveOrFail(refc, name, type, isStatic);
-            if (isStatic != field.isStatic())
-                throw newNoAccessException(isStatic
-                                           ? "expected a static field"
-                                           : "expected a non-static field",
-                                           field, this);
-            return makeAccessor(refc, field, false, isSetter);
-        }
-
-        MethodHandle makeAccessor(Class<?> refc, MemberName field,
-                                  boolean trusted, boolean isSetter) throws IllegalAccessException {
-            assert(field.isField());
-            if (trusted)
-                return MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
-            checkAccess(refc, field);
-            MethodHandle mh = MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
-            return restrictProtectedReceiver(field, mh);
-        }
-    }
-
-    /**
-     * Produces a method handle giving read access to elements of an array.
-     * The type of the method handle will have a return type of the array's
-     * element type.  Its first argument will be the array type,
-     * and the second will be {@code int}.
-     * @param arrayClass an array type
-     * @return a method handle which can load values from the given array type
-     * @throws NullPointerException if the argument is null
-     * @throws  IllegalArgumentException if arrayClass is not an array type
-     */
-    public static
-    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
-        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, false);
-    }
-
-    /**
-     * Produces a method handle giving write access to elements of an array.
-     * The type of the method handle will have a void return type.
-     * Its last argument will be the array's element type.
-     * The first and second arguments will be the array type and int.
-     * @return a method handle which can store values into the array type
-     * @throws NullPointerException if the argument is null
-     * @throws IllegalArgumentException if arrayClass is not an array type
-     */
-    public static
-    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
-        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
-    }
-
-    /// method handle invocation (reflective style)
-
-    /**
-     * Produces a method handle which will invoke any method handle of the
-     * given {@code 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>
-     * <p>
-     * The invoker will behave like a call to {@link MethodHandle#invokeGeneric invokeGeneric} with
-     * the indicated {@code type}.
-     * That is, if the target is exactly of the given {@code type}, it will behave
-     * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
-     * is used to convert the target to the required {@code type}.
-     * <p>
-     * The type of the returned invoker will not be the given {@code type}, but rather
-     * will have all parameter and return types replaced by {@code Object}, except for
-     * the last parameter type, which will be the array type {@code Object[]}.
-     * <p>
-     * Before invoking its target, the invoker will spread the varargs array, apply
-     * reference casts as necessary, and unbox and widen 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 method is equivalent to the following code (though it may be more efficient):
-     * <p><blockquote><pre>
-MethodHandle invoker = MethodHandles.genericInvoker(type);
-int spreadArgCount = type.parameterCount - objectArgCount;
-invoker = invoker.asSpreader(Object[].class, spreadArgCount);
-return invoker;
-     * </pre></blockquote>
-     * <p>
-     * This method throws no reflective or security exceptions.
-     * @param type the desired target type
-     * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
-     * @return a method handle suitable for invoking any method handle of the given type
-     */
-    static public
-    MethodHandle spreadInvoker(MethodType type, int objectArgCount) {
-        if (objectArgCount < 0 || objectArgCount > type.parameterCount())
-            throw new IllegalArgumentException("bad argument count "+objectArgCount);
-        return invokers(type).spreadInvoker(objectArgCount);
-    }
-
-    /**
-     * Produces a special <em>invoker method handle</em> which can be used to
-     * invoke any method handle of the given type, as if by {@code invokeExact}.
-     * 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 method is equivalent to the following code (though it may be more efficient):
-     * <p><blockquote><pre>
-publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
-     * </pre></blockquote>
-     *
-     * <p style="font-size:smaller;">
-     * <em>Discussion:</em>
-     * Invoker method handles can be useful when working with variable method handles
-     * of unknown types.
-     * For example, to emulate an {@code invokeExact} call to a variable method
-     * handle {@code M}, extract its type {@code T},
-     * look up the invoker method {@code X} for {@code T},
-     * and call the invoker method, as {@code X.invokeGeneric(T, A...)}.
-     * (It would not work to call {@code X.invokeExact}, since the type {@code T}
-     * is unknown.)
-     * If spreading, collecting, or other argument transformations are required,
-     * they can be applied once to the invoker {@code X} and reused on many {@code M}
-     * method handle values, as long as they are compatible with the type of {@code X}.
-     * <p>
-     * <em>(Note:  The invoker method is not available via the Core Reflection API.
-     * An attempt to call {@linkplain java.lang.reflect.Method#invoke Method.invoke}
-     * on the declared {@code invokeExact} or {@code invokeGeneric} method will raise an
-     * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
-     * <p>
-     * This method throws no reflective or security exceptions.
-     * @param type the desired target type
-     * @return a method handle suitable for invoking any method handle of the given type
-     */
-    static public
-    MethodHandle exactInvoker(MethodType type) {
-        return invokers(type).exactInvoker();
-    }
-
-    /**
-     * Produces a special <em>invoker method handle</em> which can be used to
-     * invoke any method handle of the given type, as if by {@code invokeGeneric}.
-     * 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>
-     * Before invoking its target, the invoker will apply reference casts as
-     * necessary and unbox and widen primitive arguments, as if by {@link #convertArguments 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>
-publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
-     * </pre></blockquote>
-     * <p>
-     * This method throws no reflective or security exceptions.
-     * @param type the desired target type
-     * @return a method handle suitable for invoking any method handle convertible to the given type
-     */
-    static public
-    MethodHandle genericInvoker(MethodType type) {
-        return invokers(type).genericInvoker();
-    }
-
-    static Invokers invokers(MethodType type) {
-        return MethodTypeImpl.invokers(IMPL_TOKEN, type);
-    }
-
-    /**
-     * Perform value checking, exactly as if for an adapted method handle.
-     * It is assumed that the given value is either null, of type T0,
-     * or (if T0 is primitive) of the wrapper type corresponding to T0.
-     * The following checks and conversions are made:
-     * <ul>
-     * <li>If T0 and T1 are references, 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 primitives, then a widening or narrowing
-     *     conversion is applied, if one exists.
-     * <li>If T0 is a primitive and T1 a reference, and
-     *     T0 has a wrapper type TW, a boxing conversion to TW is applied,
-     *     possibly followed by a reference conversion.
-     *     T1 must be TW or a supertype.
-     * <li>If T0 is a reference and T1 a primitive, and
-     *     T1 has a wrapper type TW, an unboxing conversion is applied,
-     *     possibly preceded by a reference conversion.
-     *     T0 must be TW or a supertype.
-     * <li>If T1 is void, the return 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.
-     * </ul>
-     * If the value is discarded, null will be returned.
-     * @param valueType
-     * @param value
-     * @return the value, converted if necessary
-     * @throws java.lang.ClassCastException if a cast fails
-     */
-    static
-    <T0, T1> T1 checkValue(Class<T0> t0, Class<T1> t1, Object value)
-       throws ClassCastException
-    {
-        if (t0 == t1) {
-            // no conversion needed; just reassert the same type
-            if (t0.isPrimitive())
-                return Wrapper.asPrimitiveType(t1).cast(value);
-            else
-                return Wrapper.OBJECT.convert(value, t1);
-        }
-        boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
-        if (!prim0) {
-            // check contract with caller
-            Wrapper.OBJECT.convert(value, t0);
-            if (!prim1) {
-                return Wrapper.OBJECT.convert(value, t1);
-            }
-            // convert reference to primitive by unboxing
-            Wrapper w1 = Wrapper.forPrimitiveType(t1);
-            return w1.convert(value, t1);
-        }
-        // check contract with caller:
-        Wrapper.asWrapperType(t0).cast(value);
-        Wrapper w1 = Wrapper.forPrimitiveType(t1);
-        return w1.convert(value, t1);
-    }
-
-    static
-    Object checkValue(Class<?> T1, Object value)
-       throws ClassCastException
-    {
-        Class<?> T0;
-        if (value == null)
-            T0 = Object.class;
-        else
-            T0 = value.getClass();
-        return checkValue(T0, T1, value);
-    }
-
-    /// method handle modification (creation from other method handles)
-
-    /**
-     * Produces a method handle which adapts the type of the
-     * 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 report a type
-     * which is equal to the desired new type.
-     * <p>
-     * If the original type and new type are equal, returns target.
-     * <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, 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 primitives, then a Java method invocation
-     *     conversion (JLS 5.3) is applied, if one exists.
-     * <li>If T0 is a primitive and T1 a reference, a boxing
-     *     conversion is applied if one exists, possibly followed by
-     *     a reference conversion to a superclass.
-     *     T1 must be a wrapper class or a supertype of one.
-     * <li>If T0 is a reference and T1 a primitive, an unboxing
-     *     conversion will be applied at runtime, possibly followed
-     *     by a Java method invocation conversion (JLS 5.3)
-     *     on the primitive value.  (These are the widening conversions.)
-     *     T0 must be a wrapper class or a supertype of one.
-     *     (In the case where T0 is Object, these are the conversions
-     *     allowed by java.lang.reflect.Method.invoke.)
-     * <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 NullPointerException if either argument is null
-     * @throws WrongMethodTypeException if the conversion cannot be made
-     * @see MethodHandle#asType
-     * @see MethodHandles#explicitCastArguments
-     */
-    public static
-    MethodHandle convertArguments(MethodHandle target, MethodType newType) {
-        MethodType oldType = target.type();
-        if (oldType.equals(newType))
-            return target;
-        MethodHandle res = null;
-        try {
-            res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
-                                                    newType, oldType, null);
-        } catch (IllegalArgumentException ex) {
-        }
-        if (res == null)
-            throw new WrongMethodTypeException("cannot convert to "+newType+": "+target);
-        return res;
-    }
-
-    /**
-     * Produces a method handle which adapts the type of the
-     * 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 report a type
-     * which is equal to the desired new type.
-     * <p>
-     * If the original type and new type are equal, returns target.
-     * <p>
-     * The same conversions are allowed as for {@link #convertArguments convertArguments},
-     * and some additional conversions are also applied if those conversions fail.
-     * Given types T0, T1, one of the following conversions is applied
-     * in addition, if the conversions specified for {@code convertArguments}
-     * would be insufficient:
-     * <ul>
-     * <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 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 a primitive value would be converted by {@code convertArguments}
-     *     using Java method invocation conversion (JLS 5.3),
-     *     Java casting conversion (JLS 5.5) may be used also.
-     *     This allows primitives to be narrowed as well as widened.
-     * </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 NullPointerException if either argument is null
-     * @throws WrongMethodTypeException if the conversion cannot be made
-     * @see MethodHandle#asType
-     * @see MethodHandles#convertArguments
-     */
-    public static
-    MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
-        return convertArguments(target, newType);  // FIXME!
-    }
-
-    /*
-      FIXME: Reconcile javadoc with 10/22/2010 EG notes on conversion:
-
-      Both converters arrange for their method handles to convert arguments
-      and return values.  The conversion rules are the same for arguments
-      and return values, and depend only on source and target types, S and
-      T.  The conversions allowed by castConvertArguments are a strict
-      superset of those performed by convertArguments.
-
-      In all cases, if S and T are references, a simple checkcast is done.
-      If neither S nor T is a primitive, no attempt is made to unbox and
-      box.  A failed conversion throws ClassCastException.
-
-      If T is void, the value is dropped.
-
-      For compatibility with reflection, if S is void and T is a reference,
-      a null value is produced.
-
-      For compatibility with reflection, if S is a reference and T is a
-      primitive, S is first unboxed and then undergoes primitive conversion.
-      In the case of 'convertArguments', only assignment conversion is
-      performed (no narrowing primitive conversion).
-
-      If S is a primitive, S is boxed, and then the above rules are applied.
-      If S and T are both primitives, the boxing will be undetectable; only
-      the primitive conversions will be apparent to the user.  The key point
-      is that if S is a primitive type, the implementation may box it and
-      treat is as Object, without loss of information, or it may use a "fast
-      path" which does not use boxing.
-
-      Notwithstanding the rules above, for compatibility with the verifier,
-      if T is an interface, it is treated as if it were Object.  [KEEP THIS?]
-
-      Also, for compatibility with the verifier, a boolean may be undergo
-      widening or narrowing conversion to any other primitive type.  [KEEP THIS?]
-    */
-
-    /**
-     * Produces a method handle which adapts the calling sequence of the
-     * given method handle to a new type, by reordering the arguments.
-     * The resulting method handle is guaranteed to report a type
-     * which is equal to the desired new type.
-     * <p>
-     * The given array controls the reordering.
-     * Call {@code #I} the number of incoming parameters (the value
-     * {@code newType.parameterCount()}, and call {@code #O} the number
-     * of outgoing parameters (the value {@code target.type().parameterCount()}).
-     * Then the length of the reordering array must be {@code #O},
-     * and each element must be a non-negative number less than {@code #I}.
-     * For every {@code N} less than {@code #O}, the {@code N}-th
-     * outgoing argument will be taken from the {@code I}-th incoming
-     * argument, where {@code I} is {@code reorder[N]}.
-     * <p>
-     * No argument or return value conversions are applied.
-     * The type of each incoming argument, as determined by {@code newType},
-     * must be identical to the type of the corresponding outgoing argument
-     * or arguments in the target method handle.
-     * The return type of {@code newType} must be identical to the return
-     * type of the original target.
-     * <p>
-     * The reordering array need not specify an actual permutation.
-     * An incoming argument will be duplicated if its index appears
-     * more than once in the array, and an incoming argument will be dropped
-     * if its index does not appear in the array.
-     * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
-     * incoming arguments which are not mentioned in the reordering array
-     * are may be any type, as determined only by {@code newType}.
-     * <blockquote><pre>
-MethodType intfn1 = MethodType.methodType(int.class, int.class);
-MethodType intfn2 = MethodType.methodType(int.class, int.class, int.class);
-MethodHandle sub = ... {int x, int y => x-y} ...;
-assert(sub.type().equals(intfn2));
-MethodHandle sub1 = MethodHandles.permuteArguments(sub, intfn2, 0, 1);
-MethodHandle rsub = MethodHandles.permuteArguments(sub, intfn2, 1, 0);
-assert((int)rsub.invokeExact(1, 100) == 99);
-MethodHandle add = ... {int x, int y => x+y} ...;
-assert(add.type().equals(intfn2));
-MethodHandle twice = MethodHandles.permuteArguments(add, intfn1, 0, 0);
-assert(twice.type().equals(intfn1));
-assert((int)twice.invokeExact(21) == 42);
-     * </pre></blockquote>
-     * @param target the method handle to invoke after arguments are reordered
-     * @param newType the expected type of the new method handle
-     * @param reorder a string which controls the reordering
-     * @return a method handle which delegates to {@code target} after it
-     *           drops unused arguments and moves and/or duplicates the other arguments
-     * @throws NullPointerException if any argument is null
-     */
-    public static
-    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
-        MethodType oldType = target.type();
-        checkReorder(reorder, newType, oldType);
-        return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
-                                                 newType, oldType,
-                                                 reorder);
-    }
-
-    private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
-        if (reorder.length == oldType.parameterCount()) {
-            int limit = newType.parameterCount();
-            boolean bad = false;
-            for (int i : reorder) {
-                if (i < 0 || i >= limit) {
-                    bad = true; break;
-                }
-            }
-            if (!bad)  return;
-        }
-        throw newIllegalArgumentException("bad reorder array");
-    }
-
-    /**
-     * Equivalent to the following code:
-     * <p><blockquote><pre>
-     * int spreadPos = newType.parameterCount() - 1;
-     * Class&lt;?&gt; spreadType = newType.parameterType(spreadPos);
-     * int spreadCount = target.type().parameterCount() - spreadPos;
-     * MethodHandle adapter = target.asSpreader(spreadType, spreadCount);
-     * adapter = adapter.asType(newType);
-     * return adapter;
-     * </pre></blockquote>
-     * @param target the method handle to invoke after argument spreading
-     * @param newType the expected type of the new method handle
-     * @return a method handle which spreads its final argument,
-     *         before calling the original method handle
-     */
-    /*non-public*/ static
-    MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
-        MethodType oldType = target.type();
-        int inargs  = newType.parameterCount();
-        int outargs = oldType.parameterCount();
-        int spreadPos = inargs - 1;
-        int numSpread = (outargs - spreadPos);
-        MethodHandle res = null;
-        if (spreadPos >= 0 && numSpread >= 0) {
-            res = MethodHandleImpl.spreadArguments(IMPL_TOKEN, target, newType, spreadPos);
-        }
-        if (res == null) {
-            throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
-        }
-        return res;
-    }
-
-    /**
-     * Equivalent to the following code:
-     * <p><blockquote><pre>
-     * int collectPos = target.type().parameterCount() - 1;
-     * Class&lt;?&gt; collectType = target.type().parameterType(collectPos);
-     * if (!collectType.isArray())  collectType = Object[].class;
-     * int collectCount = newType.parameterCount() - collectPos;
-     * MethodHandle adapter = target.asCollector(collectType, collectCount);
-     * adapter = adapter.asType(newType);
-     * return adapter;
-     * </pre></blockquote>
-     * @param target the method handle to invoke after argument collection
-     * @param newType the expected type of the new method handle
-     * @return a method handle which collects some trailing argument
-     *         into an array, before calling the original method handle
-     */
-    /*non-public*/ static
-    MethodHandle collectArguments(MethodHandle target, MethodType newType) {
-        MethodType oldType = target.type();
-        int inargs  = newType.parameterCount();
-        int outargs = oldType.parameterCount();
-        int collectPos = outargs - 1;
-        int numCollect = (inargs - collectPos);
-        if (collectPos < 0 || numCollect < 0)
-            throw newIllegalArgumentException("wrong number of arguments");
-        MethodHandle res = MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos, null);
-        if (res == null) {
-            throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
-        }
-        return res;
-    }
-
-    /**
-     * Produces a method handle of the requested return type which returns the given
-     * constant value every time it is invoked.
-     * <p>
-     * Before the method handle is returned, the passed-in value is converted to the requested type.
-     * If the requested type is primitive, widening primitive conversions are attempted,
-     * else reference conversions are attempted.
-     * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)},
-     * unless the type is {@code void}, in which case it is {@code identity(type)}.
-     * @param type the return type of the desired method handle
-     * @param value the value to return
-     * @return a method handle of the given return type and no arguments, which always returns the given value
-     * @throws NullPointerException if the {@code type} argument is null
-     * @throws ClassCastException if the value cannot be converted to the required return type
-     * @throws IllegalArgumentException if the given type is {@code void.class}
-     */
-    public static
-    MethodHandle constant(Class<?> type, Object value) {
-        if (type.isPrimitive()) {
-            if (type == void.class)
-                throw newIllegalArgumentException("void type");
-            Wrapper w = Wrapper.forPrimitiveType(type);
-            return identity(type).bindTo(w.convert(value, type));
-        } else {
-            return identity(type).bindTo(type.cast(value));
-        }
-    }
-
-    /**
-     * Produces a method handle which returns its sole argument when invoked.
-     * <p>The identity function for {@code void} takes no arguments and returns no values.
-     * @param type the type of the sole parameter and return value of the desired method handle
-     * @return a unary method handle which accepts and returns the given type
-     * @throws NullPointerException if the argument is null
-     * @throws IllegalArgumentException if the given type is {@code void.class}
-     */
-    public static
-    MethodHandle identity(Class<?> type) {
-        if (type == void.class)
-            throw newIllegalArgumentException("void type");
-        return ValueConversions.identity(type);
-    }
-
-    /**
-     * Produces 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>
-     * 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 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 values the series of arguments to insert
-     * @return a method handle which inserts an additional argument,
-     *         before calling the original method handle
-     * @throws NullPointerException if the {@code target} argument or the {@code values} array is null
-     * @see MethodHandle#bindTo
-     */
-    public static
-    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 - insCount;
-        if (inargs < 0)
-            throw newIllegalArgumentException("too many values to insert");
-        if (pos < 0 || pos > inargs)
-            throw newIllegalArgumentException("no argument type to append");
-        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 result;
-    }
-
-    /**
-     * Produces a method handle which calls the original method handle,
-     * after dropping the given argument(s) at the given position.
-     * 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</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>
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-...
-MethodHandle cat = lookup().findVirtual(String.class,
-  "concat", methodType(String.class, String.class));
-assertEquals("xy", (String) cat.invokeExact("x", "y"));
-MethodHandle d0 = dropArguments(cat, 0, String.class);
-assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
-MethodHandle d1 = dropArguments(cat, 1, String.class);
-assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
-MethodHandle d2 = dropArguments(cat, 2, String.class);
-assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
-MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
-assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
-     * </pre></blockquote>
-     * @param target the method handle to invoke after the arguments are dropped
-     * @param valueTypes the type(s) of the argument(s) to drop
-     * @param pos position of first argument to drop (zero for the leftmost)
-     * @return a method handle which drops arguments of the given types,
-     *         before calling the original method handle
-     * @throws NullPointerException if the {@code target} argument is null,
-     *                              or if the {@code valueTypes} list or any of its elements is null
-     * @throws IllegalArgumentException if any of the {@code valueTypes} is {@code void.class}
-     */
-    public static
-    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.size();
-        if (pos < 0 || pos >= inargs)
-            throw newIllegalArgumentException("no argument type to remove");
-        ArrayList<Class<?>> ptypes =
-                new ArrayList<Class<?>>(oldType.parameterList());
-        ptypes.addAll(pos, valueTypes);
-        MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
-        return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
-    }
-
-    /**
-     * Produces a method handle which calls the original method handle,
-     * after dropping the given argument(s) at the given position.
-     * The type of the new method handle will insert the given argument
-     * type(s), at that position, into the original handle's type.
-     * This method is equivalent to the following code:
-     * <code>
-     * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
-     * </code>
-     * @param target the method handle to invoke after the arguments are dropped
-     * @param valueTypes the type(s) of the argument(s) to drop
-     * @param pos position of first argument to drop (zero for the leftmost)
-     * @return a method handle which drops arguments of the given types,
-     *         before calling the original method handle
-     * @throws NullPointerException if the {@code target} argument is null,
-     *                              or if the {@code valueTypes} array or any of its elements is null
-     * @throws IllegalArgumentException if any of the {@code valueTypes} is {@code void.class}
-     */
-    public static
-    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
-        return dropArguments(target, pos, Arrays.asList(valueTypes));
-    }
-
-    /**
-     * 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 elements of the {@code filters} array.
-     * Null arguments in the array are ignored, and the corresponding arguments left unchanged.
-     * (If there are no non-null elements in the array, the original target is returned.)
-     * Each filter 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 elements of {@code filters}
-     * which do not correspond to argument positions in the target.
-     * <b>Example:</b>
-     * <p><blockquote><pre>
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-...
-MethodHandle cat = lookup().findVirtual(String.class,
-  "concat", methodType(String.class, String.class));
-MethodHandle upcase = lookup().findVirtual(String.class,
-  "toUpperCase", methodType(String.class));
-assertEquals("xy", (String) cat.invokeExact("x", "y"));
-MethodHandle f0 = filterArguments(cat, 0, upcase);
-assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
-MethodHandle f1 = filterArguments(cat, 1, upcase);
-assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
-MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
-assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
-     * </pre></blockquote>
-     *
-     * @param target the method handle to invoke after arguments are filtered
-     * @param pos the position of the first argument to filter
-     * @param filters method handles to call initially on filtered arguments
-     * @return method handle which incorporates the specified argument filtering logic
-     * @throws NullPointerException if the {@code target} argument is null
-     *                              or if the {@code filters} array is null
-     * @throws IllegalArgumentException if a non-null element of {@code filters}
-     *          does not match a corresponding argument type of {@code target} as described above,
-     *          or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()}
-     */
-    public static
-    MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
-        MethodType targetType = target.type();
-        MethodHandle adapter = target;
-        MethodType adapterType = targetType;
-        int maxPos = targetType.parameterCount();
-        if (pos + filters.length > maxPos)
-            throw newIllegalArgumentException("too many filters");
-        int curPos = pos-1;  // pre-incremented
-        for (MethodHandle filter : filters) {
-            curPos += 1;
-            if (filter == null)  continue;  // ignore null elements of filters
-            MethodType filterType = filter.type();
-            if (filterType.parameterCount() != 1
-                || filterType.returnType() != targetType.parameterType(curPos))
-                throw newIllegalArgumentException("target and filter types do not match");
-            adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0));
-            adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, curPos, filter);
-        }
-        MethodType midType = adapter.type();
-        if (midType != adapterType)
-            adapter = MethodHandleImpl.convertArguments(IMPL_TOKEN, adapter, adapterType, midType, null);
-        return adapter;
-    }
-
-    /**
-     * Adapt a target method handle {@code target} by post-processing
-     * its return value with a unary filter function.
-     * <p>
-     * If a filter {@code F} applies to the return value of
-     * the target method handle, then {@code F} must be a method handle which
-     * takes exactly one argument.  The return type of {@code F}
-     * replaces the return type of the target
-     * in the resulting adapted method handle.
-     * The argument type of {@code F} must be identical to the
-     * return type of the target.
-     * <b>Example:</b>
-     * <p><blockquote><pre>
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-...
-MethodHandle cat = lookup().findVirtual(String.class,
-  "concat", methodType(String.class, String.class));
-MethodHandle length = lookup().findVirtual(String.class,
-  "length", methodType(int.class));
-System.out.println((String) cat.invokeExact("x", "y")); // xy
-MethodHandle f0 = filterReturnValue(cat, length);
-System.out.println((int) f0.invokeExact("x", "y")); // 2
-     * </pre></blockquote>
-     * @param target the method handle to invoke before filtering the return value
-     * @param filter method handle to call on the return value
-     * @return method handle which incorporates the specified return value filtering logic
-     * @throws NullPointerException if either argument is null
-     * @throws IllegalArgumentException if {@code filter}
-     *          does not match the return type of {@code target} as described above
-     */
-    public static
-    MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
-        MethodType targetType = target.type();
-        MethodType filterType = filter.type();
-        if (filterType.parameterCount() != 1
-            || filterType.parameterType(0) != targetType.returnType())
-            throw newIllegalArgumentException("target and filter types do not match");
-        // result = fold( lambda(retval, arg...) { filter(retval) },
-        //                lambda(        arg...) { target(arg...) } )
-        // FIXME: Too many nodes here.
-        MethodHandle returner = dropArguments(filter, 1, targetType.parameterList());
-        return foldArguments(returner, target);
-    }
-
-    /**
-     * 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(MethodHandle,int,List) 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 MethodHandle#asCollector asCollector} 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 NullPointerException if either argument is null
-     * @throws IllegalArgumentException if the first argument type of
-     *          {@code target} is not the same as {@code combiner}'s return type,
-     *          or if the following 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 && !combinerType.parameterList().equals(targetType.parameterList().subList(1, foldArgs+1)))
-            ok = false;
-        if (ok && !combinerType.returnType().equals(targetType.parameterType(0)))
-            ok = false;
-        if (!ok)
-            throw misMatchedTypes("target and combiner types", targetType, combinerType);
-        MethodType newType = targetType.dropParameterTypes(0, 1);
-        return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner);
-    }
-
-    /**
-     * Make a method handle which adapts a target method handle,
-     * by guarding it with a test, a boolean-valued method handle.
-     * 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, 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>
-     * boolean test(A...);
-     * T target(A...,B...);
-     * T fallback(A...,B...);
-     * T adapter(A... a,B... b) {
-     *   if (test(a...))
-     *     return target(a..., b...);
-     *   else
-     *     return fallback(a..., b...);
-     * }
-     * </pre></blockquote>
-     * Note that the test arguments ({@code a...} in the pseudocode) cannot
-     * be modified by execution of the test, and so are passed unchanged
-     * from the caller to the target or fallback as appropriate.
-     * @param test method handle used for test, must return boolean
-     * @param target method handle to call if test passes
-     * @param fallback method handle to call if test fails
-     * @return method handle which incorporates the specified if/then/else logic
-     * @throws NullPointerException if any argument is null
-     * @throws IllegalArgumentException if {@code test} does not return boolean,
-     *          or if all three method types do not match (with the return
-     *          type of {@code test} changed to match that of {@code target}).
-     */
-    public static
-    MethodHandle guardWithTest(MethodHandle test,
-                               MethodHandle target,
-                               MethodHandle fallback) {
-        MethodType gtype = test.type();
-        MethodType ttype = target.type();
-        MethodType ftype = fallback.type();
-        if (!ttype.equals(ftype))
-            throw misMatchedTypes("target and fallback types", ttype, ftype);
-        if (gtype.returnType() != boolean.class)
-            throw newIllegalArgumentException("guard type is not a predicate "+gtype);
-        List<Class<?>> targs = ttype.parameterList();
-        List<Class<?>> gargs = gtype.parameterList();
-        if (!targs.equals(gargs)) {
-            int gpc = gargs.size(), tpc = targs.size();
-            if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
-                throw misMatchedTypes("target and test types", ttype, gtype);
-            test = dropArguments(test, gpc, targs.subList(gpc, tpc));
-            gtype = test.type();
-        }
-        return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
-    }
-
-    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
-        return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
-    }
-
-    /**
-     * 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 target and handler must have the same corresponding
-     * argument and return types, except that handler may omit trailing arguments
-     * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
-     * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
-     * <p> Here is pseudocode for the resulting adapter:
-     * <blockquote><pre>
-     * T target(A..., B...);
-     * T handler(ExType, A...);
-     * T adapter(A... a, B... b) {
-     *   try {
-     *     return target(a..., b...);
-     *   } catch (ExType ex) {
-     *     return handler(ex, a...);
-     *   }
-     * }
-     * </pre></blockquote>
-     * Note that the saved arguments ({@code a...} in the pseudocode) cannot
-     * be modified by execution of the target, and so are passed unchanged
-     * from the caller to the handler, if the handler is invoked.
-     * <p>
-     * The target and handler must return the same type, even if the handler
-     * always throws.  (This might happen, for instance, because the handler
-     * is simulating a {@code finally} clause).
-     * To create such a throwing handler, compose the handler creation logic
-     * with {@link #throwException throwException},
-     * in order to create a method handle of the correct return type.
-     * @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 NullPointerException if any argument is null
-     * @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 catchException(MethodHandle target,
-                                Class<? extends Throwable> exType,
-                                MethodHandle handler) {
-        MethodType ttype = target.type();
-        MethodType htype = handler.type();
-        if (htype.parameterCount() < 1 ||
-            !htype.parameterType(0).isAssignableFrom(exType))
-            throw newIllegalArgumentException("handler does not accept exception type "+exType);
-        if (htype.returnType() != ttype.returnType())
-            throw misMatchedTypes("target and handler return types", ttype, htype);
-        List<Class<?>> targs = ttype.parameterList();
-        List<Class<?>> hargs = htype.parameterList();
-        hargs = hargs.subList(1, hargs.size());  // omit leading parameter from handler
-        if (!targs.equals(hargs)) {
-            int hpc = hargs.size(), tpc = targs.size();
-            if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
-                throw misMatchedTypes("target and handler types", ttype, htype);
-            handler = dropArguments(handler, hpc, hargs.subList(hpc, tpc));
-            htype = handler.type();
-        }
-        return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
-    }
-
-    /**
-     * Produces 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.
-     * @return method handle which can throw the given exceptions
-     * @throws NullPointerException if either argument is null
-     */
-    public static
-    MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
-        return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
-    }
-
-    /**
-     * Produces an instance of the given "SAM" interface which redirects
-     * its calls to the given method handle.
-     * <p>
-     * A SAM interface is an interface which declares a single abstract method.
-     * When determining the unique abstract method of a SAM interface,
-     * the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
-     * are disregarded.  For example, {@link java.util.Comparator} is a SAM interface,
-     * even though it re-declares the {@code Object.equals} method.
-     * Also, if the SAM interface has a supertype,
-     * the SAM interface may override an inherited method.
-     * Any such overrides are respected, and the method handle will be accessible
-     * by either the inherited method or the SAM method.
-     * In particular, a {@linkplain java.lang.reflect.Method#isBridge bridge method}
-     * may be created if the methods have different return types.
-     * <p>
-     * The type must be public.  No additional access checks are performed.
-     * <p>
-     * The resulting instance of the required SAM type will respond to
-     * invocation of the SAM type's single abstract method by calling
-     * the given {@code target} on the incoming arguments,
-     * and returning or throwing whatever the {@code target}
-     * returns or throws.  The invocation will be as if by
-     * {@code target.invokeGeneric}.
-     * The target's type will be checked before the SAM
-     * instance is created, as if by a call to {@code asType},
-     * which may result in a {@code WrongMethodTypeException}.
-     * <p>
-     * The wrapper instance will implement the requested SAM interface
-     * and its super-types, but no other SAM types.
-     * This means that the SAM instance will not unexpectedly
-     * pass an {@code instanceof} test for any unrequested type.
-     * <p style="font-size:smaller;">
-     * <em>Implementation Note:</em>
-     * Therefore, each SAM instance must implement a unique SAM type.
-     * Implementations may not bundle together
-     * multiple SAM types onto single implementation classes
-     * in the style of {@link java.awt.AWTEventMulticaster}.
-     * <p>
-     * The method handle may throw an <em>undeclared exception</em>,
-     * which means any checked exception (or other checked throwable)
-     * not declared by the SAM type's single abstract method.
-     * If this happens, the throwable will be wrapped in an instance of
-     * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
-     * and thrown in that wrapped form.
-     * <p>
-     * Like {@link java.lang.Integer#valueOf Integer.valueOf},
-     * {@code asInstance} is a factory method whose results are defined
-     * by their behavior.
-     * It is not guaranteed to return a new instance for every call.
-     * <p>
-     * Future versions of this API may accept additional types,
-     * such as abstract classes with single abstract methods.
-     * Future versions of this API may also equip wrapper instances
-     * with one or more additional public "marker" interfaces.
-     *
-     * @param target the method handle to invoke from the wrapper
-     * @param samType the desired type of the wrapper, a SAM type
-     * @return a correctly-typed wrapper for the given {@code target}
-     * @throws NullPointerException if either argument is null
-     * @throws IllegalArgumentException if the {@code samType} is not a
-     *         valid argument to this method
-     * @throws WrongMethodTypeException if the {@code target} cannot
-     *         be converted to the type required by the SAM type
-     */
-    // Other notes to implementors:
-    // <p>
-    // No stable mapping is promised between the SAM type and
-    // the implementation class C.  Over time, several implementation
-    // classes might be used for the same SAM type.
-    // <p>
-    // If the implementation is able
-    // to prove that a wrapper of the required SAM type
-    // has already been created for a given
-    // method handle, or for another method handle with the
-    // same behavior, the implementation may return that wrapper in place of
-    // a new wrapper.
-    // <p>
-    // This method is designed to apply to common use cases
-    // where a single method handle must interoperate with
-    // an interface that implements a function-like
-    // API.  Additional variations, such as SAM classes with
-    // private constructors, or interfaces with multiple but related
-    // entry points, must be covered by hand-written or automatically
-    // generated adapter classes.
-    //
-    public static
-    <T> T asInstance(final MethodHandle target, final Class<T> samType) {
-        // POC implementation only; violates the above contract several ways
-        final Method sam = getSamMethod(samType);
-        if (sam == null)
-            throw new IllegalArgumentException("not a SAM type: "+samType.getName());
-        MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
-        MethodHandle checkTarget = target.asType(samMT);  // make throw WMT
-        checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
-        final MethodHandle vaTarget = checkTarget.asSpreader(Object[].class, samMT.parameterCount());
-        return samType.cast(Proxy.newProxyInstance(
-                samType.getClassLoader(),
-                new Class[]{ samType, WrapperInstance.class },
-                new InvocationHandler() {
-                    private Object getArg(String name) {
-                        if ((Object)name == "getWrapperInstanceTarget")  return target;
-                        if ((Object)name == "getWrapperInstanceType")    return samType;
-                        throw new AssertionError();
-                    }
-                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-                        if (method.getDeclaringClass() == WrapperInstance.class)
-                            return getArg(method.getName());
-                        if (method.equals(sam))
-                            return vaTarget.invokeExact(args);
-                        if (isObjectMethod(method))
-                            return callObjectMethod(this, method, args);
-                        throw new InternalError();
-                    }
-                }));
-    }
-
-    /**
-     * Determine if the given object was produced by a call to {@link #asInstance asInstance}.
-     * @param x any reference
-     * @return true if the reference is not null and points to an object produced by {@code asInstance}
-     */
-    public static
-    boolean isWrapperInstance(Object x) {
-        return x instanceof WrapperInstance;
-    }
-
-    private static WrapperInstance asWrapperInstance(Object x) {
-        try {
-            if (x != null)
-                return (WrapperInstance) x;
-        } catch (ClassCastException ex) {
-        }
-        throw new IllegalArgumentException("not a wrapper instance");
-    }
-
-    /**
-     * Produces or recovers a target method handle which is behaviorally
-     * equivalent to the SAM method of this wrapper instance.
-     * The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
-     * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
-     * @param x any reference
-     * @return a method handle implementing the SAM method
-     * @throws IllegalArgumentException if the reference x is not to a wrapper instance
-     */
-    public static
-    MethodHandle wrapperInstanceTarget(Object x) {
-        return asWrapperInstance(x).getWrapperInstanceTarget();
-    }
-
-    /**
-     * Recover the SAM type for which this wrapper instance was created.
-     * The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
-     * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
-     * @param x any reference
-     * @return the SAM type for which the wrapper was created
-     * @throws IllegalArgumentException if the reference x is not to a wrapper instance
-     */
-    public static
-    Class<?> wrapperInstanceType(Object x) {
-        return asWrapperInstance(x).getWrapperInstanceType();
-    }
-
-    private static
-    boolean isObjectMethod(Method m) {
-        switch (m.getName()) {
-        case "toString":
-            return (m.getReturnType() == String.class
-                    && m.getParameterTypes().length == 0);
-        case "hashCode":
-            return (m.getReturnType() == int.class
-                    && m.getParameterTypes().length == 0);
-        case "equals":
-            return (m.getReturnType() == boolean.class
-                    && m.getParameterTypes().length == 1
-                    && m.getParameterTypes()[0] == Object.class);
-        }
-        return false;
-    }
-
-    private static
-    Object callObjectMethod(Object self, Method m, Object[] args) {
-        assert(isObjectMethod(m)) : m;
-        switch (m.getName()) {
-        case "toString":
-            return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
-        case "hashCode":
-            return System.identityHashCode(self);
-        case "equals":
-            return (self == args[0]);
-        }
-        return null;
-    }
-
-    private static
-    Method getSamMethod(Class<?> samType) {
-        Method sam = null;
-        for (Method m : samType.getMethods()) {
-            int mod = m.getModifiers();
-            if (Modifier.isAbstract(mod)) {
-                if (sam != null && !isObjectMethod(sam))
-                    return null;  // too many abstract methods
-                sam = m;
-            }
-        }
-        if (!samType.isInterface() && getSamConstructor(samType) == null)
-            return null;  // wrong kind of constructor
-        return sam;
-    }
-
-    private static
-    Constructor getSamConstructor(Class<?> samType) {
-        for (Constructor c : samType.getDeclaredConstructors()) {
-            if (c.getParameterTypes().length == 0) {
-                int mod = c.getModifiers();
-                if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
-                    return c;
-            }
-        }
-        return null;
-    }
-
-    /*non-public*/
-    static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
-        return MethodHandleImpl.asVarargsCollector(IMPL_TOKEN, target, arrayType);
-    }
-}
--- a/jdk/src/share/classes/java/dyn/MethodType.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,865 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import sun.dyn.Access;
-import sun.dyn.Invokers;
-import sun.dyn.MethodHandleImpl;
-import sun.dyn.MethodTypeImpl;
-import sun.dyn.util.BytecodeDescriptor;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-
-/**
- * A method type represents the arguments and return type accepted and
- * returned by a method handle, or the arguments and return type passed
- * and expected  by a method handle caller.  Method types must be properly
- * matched between a method handle and all its callers,
- * and the JVM's operations enforce this matching at, specifically
- * during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact}
- * and {@link MethodHandle#invokeGeneric MethodHandle.invokeGeneric}, and during execution
- * of {@code invokedynamic} instructions.
- * <p>
- * The structure is a return type accompanied by any number of parameter types.
- * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
- * (For ease of exposition, we treat {@code void} as if it were a type.
- * In fact, it denotes the absence of a return type.)
- * <p>
- * All instances of {@code MethodType} are immutable.
- * Two instances are completely interchangeable if they compare equal.
- * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
- * <p>
- * This type can be created only by factory methods.
- * All factory methods may cache values, though caching is not guaranteed.
- * Some factory methods are static, while others are virtual methods which
- * modify precursor method types, e.g., by changing a selected parameter.
- * <p>
- * Factory methods which operate on groups of parameter types
- * are systematically presented in two versions, so that both Java arrays and
- * Java lists can be used to work with groups of parameter types.
- * The query methods {@code parameterArray} and {@code parameterList}
- * also provide a choice between arrays and lists.
- * <p>
- * {@code MethodType} objects are sometimes derived from bytecode instructions
- * such as {@code invokedynamic}, specifically from the type descriptor strings associated
- * with the instructions in a class file's constant pool.
- * <p>
- * Like classes and strings, method types can also be represented directly
- * in a class file's constant pool as constants.
- * A method type may be loaded by an {@code ldc} instruction which refers
- * to a suitable {@code CONSTANT_MethodType} constant pool entry.
- * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
- * For more details, see the <a href="package-summary.html#mtcon">package summary</a>.
- * <p>
- * When the JVM materializes a {@code MethodType} from a descriptor string,
- * all classes named in the descriptor must be accessible, and will be loaded.
- * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
- * This loading may occur at any time before the {@code MethodType} object is first derived.
- * @author John Rose, JSR 292 EG
- */
-public final
-class MethodType implements java.io.Serializable {
-    private static final long serialVersionUID = 292L;  // {rtype, {ptype...}}
-
-    // The rtype and ptypes fields define the structural identity of the method type:
-    private final Class<?>   rtype;
-    private final Class<?>[] ptypes;
-
-    // The remaining fields are caches of various sorts:
-    private MethodTypeForm form; // erased form, plus cached data about primitives
-    private MethodType wrapAlt;  // alternative wrapped/unwrapped version
-    private Invokers invokers;   // cache of handy higher-order adapters
-
-    private static final Access IMPL_TOKEN = Access.getToken();
-
-    // share a cache with a friend in this package
-    Invokers getInvokers() { return invokers; }
-    void setInvokers(Invokers inv) { invokers = inv; }
-
-    static {
-        // This hack allows the implementation package special access to
-        // 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; }
-            public MethodTypeImpl form(MethodType mt)      { return mt.form; }
-            public void setForm(MethodType mt, MethodTypeImpl form) {
-                assert(mt.form == null);
-                mt.form = (MethodTypeForm) form;
-            }
-            public MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
-                return MethodType.makeImpl(rtype, ptypes, trusted);
-            }
-            public MethodTypeImpl newMethodTypeForm(MethodType mt) {
-                return new MethodTypeForm(mt);
-            }
-            public Invokers getInvokers(MethodType mt)    { return mt.invokers; }
-            public void setInvokers(MethodType mt, Invokers inv) { mt.invokers = inv; }
-        });
-    }
-
-    /**
-     * Check the given parameters for validity and store them into the final fields.
-     */
-    private MethodType(Class<?> rtype, Class<?>[] ptypes) {
-        checkRtype(rtype);
-        checkPtypes(ptypes);
-        this.rtype = rtype;
-        this.ptypes = ptypes;
-    }
-
-    private static void checkRtype(Class<?> rtype) {
-        rtype.equals(rtype);  // null check
-    }
-    private static int checkPtype(Class<?> ptype) {
-        ptype.getClass();  //NPE
-        if (ptype == void.class)
-            throw newIllegalArgumentException("parameter type cannot be void");
-        if (ptype == double.class || ptype == long.class)  return 1;
-        return 0;
-    }
-    /** Return number of extra slots (count of long/double args). */
-    private static int checkPtypes(Class<?>[] ptypes) {
-        int slots = 0;
-        for (Class<?> ptype : ptypes) {
-            slots += checkPtype(ptype);
-        }
-        checkSlotCount(ptypes.length + slots);
-        return slots;
-    }
-    private static void checkSlotCount(int count) {
-        if ((count & 0xFF) != count)
-            throw newIllegalArgumentException("bad parameter count "+count);
-    }
-    private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num) {
-        if (num instanceof Integer)  num = "bad index: "+num;
-        return new IndexOutOfBoundsException(num.toString());
-    }
-
-    static final HashMap<MethodType,MethodType> internTable
-            = new HashMap<MethodType, MethodType>();
-
-    static final Class<?>[] NO_PTYPES = {};
-
-    /**
-     * Find or create an instance of the given method type.
-     * @param rtype  the return type
-     * @param ptypes the parameter types
-     * @return a method type with the given components
-     * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
-     * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
-     */
-    public static
-    MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
-        return makeImpl(rtype, ptypes, false);
-    }
-
-    /**
-     * Finds or creates a method type with the given components.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * @return a method type with the given components
-     * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
-     * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
-     */
-    public static
-    MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) {
-        boolean notrust = false;  // random List impl. could return evil ptypes array
-        return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust);
-    }
-
-    /**
-     * Finds or creates a method type with the given components.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * The leading parameter type is prepended to the remaining array.
-     * @return a method type with the given components
-     * @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null
-     * @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class}
-     */
-    public static
-    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);
-    }
-
-    /**
-     * Finds or creates a method type with the given components.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * The resulting method has no parameter types.
-     * @return a method type with the given return value
-     * @throws NullPointerException if {@code rtype} is null
-     */
-    public static
-    MethodType methodType(Class<?> rtype) {
-        return makeImpl(rtype, NO_PTYPES, true);
-    }
-
-    /**
-     * Finds or creates a method type with the given components.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * The resulting method has the single given parameter type.
-     * @return a method type with the given return value and parameter type
-     * @throws NullPointerException if {@code rtype} or {@code ptype0} is null
-     * @throws IllegalArgumentException if {@code ptype0} is {@code void.class}
-     */
-    public static
-    MethodType methodType(Class<?> rtype, Class<?> ptype0) {
-        return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
-    }
-
-    /**
-     * Finds or creates a method type with the given components.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * The resulting method has the same parameter types as {@code ptypes},
-     * and the specified return type.
-     * @throws NullPointerException if {@code rtype} or {@code ptypes} is null
-     */
-    public static
-    MethodType methodType(Class<?> rtype, MethodType ptypes) {
-        return makeImpl(rtype, ptypes.ptypes, true);
-    }
-
-    /**
-     * Sole factory method to find or create an interned method type.
-     * @param rtype desired return type
-     * @param ptypes desired parameter types
-     * @param trusted whether the ptypes can be used without cloning
-     * @return the unique method type of the desired structure
-     */
-    private static
-    MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
-        if (ptypes == null || ptypes.length == 0) {
-            ptypes = NO_PTYPES; trusted = true;
-        }
-        MethodType mt1 = new MethodType(rtype, ptypes);
-        MethodType mt0;
-        synchronized (internTable) {
-            mt0 = internTable.get(mt1);
-            if (mt0 != null)
-                return mt0;
-        }
-        if (!trusted)
-            // defensively copy the array passed in by the user
-            mt1 = new MethodType(rtype, ptypes.clone());
-        // promote the object to the Real Thing, and reprobe
-        MethodTypeImpl.initForm(IMPL_TOKEN, mt1);
-        synchronized (internTable) {
-            mt0 = internTable.get(mt1);
-            if (mt0 != null)
-                return mt0;
-            internTable.put(mt1, mt1);
-        }
-        return mt1;
-    }
-
-    // Entry point from JVM.  TODO: Change the name & signature.
-    private static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes,
-            boolean ignore1, boolean ignore2) {
-        return makeImpl(rtype, ptypes, true);
-    }
-
-    private static final MethodType[] objectOnlyTypes = new MethodType[20];
-
-    /**
-     * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * 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 {@code Object[]}
-     * @return a totally generic method type, given only its count of parameters and varargs
-     * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
-     * @see #genericMethodType(int)
-     */
-    public static
-    MethodType genericMethodType(int objectArgCount, boolean varargs) {
-        MethodType mt;
-        checkSlotCount(objectArgCount);
-        int ivarargs = (!varargs ? 0 : 1);
-        int ootIndex = objectArgCount*2 + ivarargs;
-        if (ootIndex < objectOnlyTypes.length) {
-            mt = objectOnlyTypes[ootIndex];
-            if (mt != null)  return mt;
-        }
-        Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
-        Arrays.fill(ptypes, Object.class);
-        if (ivarargs != 0)  ptypes[objectArgCount] = Object[].class;
-        mt = makeImpl(Object.class, ptypes, true);
-        if (ootIndex < objectOnlyTypes.length) {
-            objectOnlyTypes[ootIndex] = mt;     // cache it here also!
-        }
-        return mt;
-    }
-
-    /**
-     * Finds or creates a method type whose components are all {@code Object}.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * 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
-     * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
-     * @see #genericMethodType(int, boolean)
-     */
-    public static
-    MethodType genericMethodType(int objectArgCount) {
-        return genericMethodType(objectArgCount, false);
-    }
-
-    /**
-     * Finds or creates a method type with a single different parameter type.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * @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
-     * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
-     * @throws IllegalArgumentException if {@code nptype} is {@code void.class}
-     * @throws NullPointerException if {@code nptype} is null
-     */
-    public MethodType changeParameterType(int num, Class<?> nptype) {
-        if (parameterType(num) == nptype)  return this;
-        checkPtype(nptype);
-        Class<?>[] nptypes = ptypes.clone();
-        nptypes[num] = nptype;
-        return makeImpl(rtype, nptypes, true);
-    }
-
-    /**
-     * Finds or creates a method type with additional parameter types.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * @param num    the position (zero-based) of the inserted parameter type(s)
-     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
-     * @return the same type, except with the selected parameter(s) inserted
-     * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
-     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
-     *                                  or if the resulting method type would have more than 255 parameter slots
-     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
-     */
-    public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
-        int len = ptypes.length;
-        if (num < 0 || num > len)
-            throw newIndexOutOfBoundsException(num);
-        int ins = checkPtypes(ptypesToInsert);
-        checkSlotCount(parameterSlotCount() + ptypesToInsert.length + ins);
-        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);
-    }
-
-    /**
-     * Finds or creates a method type with additional parameter types.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
-     * @return the same type, except with the selected parameter(s) appended
-     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
-     *                                  or if the resulting method type would have more than 255 parameter slots
-     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
-     */
-    public MethodType appendParameterTypes(Class<?>... ptypesToInsert) {
-        return insertParameterTypes(parameterCount(), ptypesToInsert);
-    }
-
-    /**
-     * Finds or creates a method type with additional parameter types.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * @param num    the position (zero-based) of the inserted parameter type(s)
-     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
-     * @return the same type, except with the selected parameter(s) inserted
-     * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
-     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
-     *                                  or if the resulting method type would have more than 255 parameter slots
-     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
-     */
-    public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
-        return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES));
-    }
-
-    /**
-     * Finds or creates a method type with additional parameter types.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
-     * @return the same type, except with the selected parameter(s) appended
-     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
-     *                                  or if the resulting method type would have more than 255 parameter slots
-     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
-     */
-    public MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) {
-        return insertParameterTypes(parameterCount(), ptypesToInsert);
-    }
-
-    /**
-     * Finds or creates a method type with some parameter types omitted.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * @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
-     * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
-     *                                  or if {@code end} is negative or greater than {@code parameterCount()}
-     *                                  or if {@code start} is greater than {@code end}
-     */
-    public MethodType dropParameterTypes(int start, int end) {
-        int len = ptypes.length;
-        if (!(0 <= start && start <= end && end <= len))
-            throw newIndexOutOfBoundsException("start="+start+" end="+end);
-        if (start == end)  return this;
-        Class<?>[] nptypes;
-        if (start == 0) {
-            if (end == len) {
-                // drop all parameters
-                nptypes = NO_PTYPES;
-            } else {
-                // drop initial parameter(s)
-                nptypes = Arrays.copyOfRange(ptypes, end, len);
-            }
-        } else {
-            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);
-    }
-
-    /**
-     * Finds or creates a method type with a different return type.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * @param nrtype a return parameter type to replace the old one with
-     * @return the same type, except with the return type change
-     * @throws NullPointerException if {@code nrtype} is null
-     */
-    public MethodType changeReturnType(Class<?> nrtype) {
-        if (returnType() == nrtype)  return this;
-        return makeImpl(nrtype, ptypes, true);
-    }
-
-    /**
-     * Reports 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() {
-        return form.hasPrimitives();
-    }
-
-    /**
-     * Reports 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;
-    }
-
-    /**
-     * Erases all reference types to {@code Object}.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * 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();
-    }
-
-    /**
-     * Converts all types, both reference and primitive, to {@code Object}.
-     * Convenience method for {@link #genericMethodType(int) genericMethodType}.
-     * 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 genericMethodType(parameterCount());
-    }
-
-    /**
-     * Converts all primitive types to their corresponding wrapper types.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * 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;
-    }
-
-    /**
-     * Convert all wrapper types to their corresponding primitive types.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * 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
-     */
-    public MethodType unwrap() {
-        MethodType noprims = !hasPrimitives() ? this : wrapWithPrims(this);
-        return unwrapWithNoPrims(noprims);
-    }
-
-    private static MethodType wrapWithPrims(MethodType pt) {
-        assert(pt.hasPrimitives());
-        MethodType wt = pt.wrapAlt;
-        if (wt == null) {
-            // fill in lazily
-            wt = MethodTypeImpl.canonicalize(pt, MethodTypeImpl.WRAP, MethodTypeImpl.WRAP);
-            assert(wt != null);
-            pt.wrapAlt = wt;
-        }
-        return wt;
-    }
-
-    private static MethodType unwrapWithNoPrims(MethodType wt) {
-        assert(!wt.hasPrimitives());
-        MethodType uwt = wt.wrapAlt;
-        if (uwt == null) {
-            // fill in lazily
-            uwt = MethodTypeImpl.canonicalize(wt, MethodTypeImpl.UNWRAP, MethodTypeImpl.UNWRAP);
-            if (uwt == null)
-                uwt = wt;    // type has no wrappers or prims at all
-            wt.wrapAlt = uwt;
-        }
-        return uwt;
-    }
-
-    /**
-     * Returns the parameter type at the specified index, within this method type.
-     * @param num the index (zero-based) of the desired parameter type
-     * @return the selected parameter type
-     * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
-     */
-    public Class<?> parameterType(int num) {
-        return ptypes[num];
-    }
-    /**
-     * Returns the number of parameter types in this method type.
-     * @return the number of parameter types
-     */
-    public int parameterCount() {
-        return ptypes.length;
-    }
-    /**
-     * Returns the return type of this method type.
-     * @return the return type
-     */
-    public Class<?> returnType() {
-        return rtype;
-    }
-
-    /**
-     * Presents the parameter types as a list (a convenience method).
-     * The list will be immutable.
-     * @return the parameter types (as an immutable list)
-     */
-    public List<Class<?>> parameterList() {
-        return Collections.unmodifiableList(Arrays.asList(ptypes));
-    }
-
-    /**
-     * Presents the parameter types as an array (a convenience method).
-     * 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() {
-        return ptypes.clone();
-    }
-
-    /**
-     * Compares the specified object with this type for equality.
-     * That is, it returns <tt>true</tt> if and only if the specified object
-     * is also a method type with exactly the same parameters and return type.
-     * @param x object to compare
-     * @see Object#equals(Object)
-     */
-    @Override
-    public boolean equals(Object x) {
-        return this == x || x instanceof MethodType && equals((MethodType)x);
-    }
-
-    private boolean equals(MethodType that) {
-        return this.rtype == that.rtype
-            && Arrays.equals(this.ptypes, that.ptypes);
-    }
-
-    /**
-     * Returns the hash code value for this method type.
-     * It is defined to be the same as the hashcode of a List
-     * whose elements are the return type followed by the
-     * parameter types.
-     * @return the hash code value for this method type
-     * @see Object#hashCode()
-     * @see #equals(Object)
-     * @see List#hashCode()
-     */
-    @Override
-    public int hashCode() {
-      int hashCode = 31 + rtype.hashCode();
-      for (Class<?> ptype : ptypes)
-          hashCode = 31*hashCode + ptype.hashCode();
-      return hashCode;
-    }
-
-    /**
-     * Returns a string representation of the method type,
-     * of the form {@code "(PT0,PT1...)RT"}.
-     * The string representation of a method type is a
-     * parenthesis enclosed, comma separated list of type names,
-     * followed immediately by the return type.
-     * <p>
-     * Each type is represented by its
-     * {@link java.lang.Class#getSimpleName simple name}.
-     */
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("(");
-        for (int i = 0; i < ptypes.length; i++) {
-            if (i > 0)  sb.append(",");
-            sb.append(ptypes[i].getSimpleName());
-        }
-        sb.append(")");
-        sb.append(rtype.getSimpleName());
-        return sb.toString();
-    }
-
-    /// Queries which have to do with the bytecode architecture
-
-    /** Reports the number of JVM stack slots required to invoke a method
-     * of this type.  Note that (for historic reasons) the JVM requires
-     * a second stack slot to pass long and double arguments.
-     * So this method returns {@link #parameterCount() parameterCount} plus the
-     * number of long and double parameters (if any).
-     * <p>
-     * This method is included for the benfit of applications that must
-     * generate bytecodes that process method handles and invokedynamic.
-     * @return the number of JVM stack slots for this type's parameters
-     * @deprecated Will be removed for PFD.
-     */
-    public int parameterSlotCount() {
-        return form.parameterSlotCount();
-    }
-
-    /** Reports the 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
-     * according to their trailing edge.  Thus, to obtain the depth
-     * in the outgoing call stack of parameter {@code N}, obtain
-     * the {@code parameterSlotDepth} of its trailing edge
-     * at position {@code N+1}.
-     * <p>
-     * Parameters of type {@code long} and {@code double} occupy
-     * two stack slots (for historical reasons) and all others occupy one.
-     * Therefore, the number returned is the number of arguments
-     * <em>including</em> and <em>after</em> the given parameter,
-     * <em>plus</em> the number of long or double arguments
-     * at or after after the argument for the given parameter.
-     * <p>
-     * This method is included for the benfit of applications that must
-     * generate bytecodes that process method handles and invokedynamic.
-     * @param num an index (zero-based, inclusive) within the parameter types
-     * @return the index of the (shallowest) JVM stack slot transmitting the
-     *         given parameter
-     * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
-     * @deprecated Will be removed for PFD.
-     */
-    public int parameterSlotDepth(int num) {
-        if (num < 0 || num > ptypes.length)
-            parameterType(num);  // force a range check
-        return form.parameterToArgSlot(num-1);
-    }
-
-    /** Reports the number of JVM stack slots required to receive a return value
-     * from a method of this type.
-     * If the {@link #returnType() return type} is void, it will be zero,
-     * else if the return type is long or double, it will be two, else one.
-     * <p>
-     * This method is included for the benfit of applications that must
-     * generate bytecodes that process method handles and invokedynamic.
-     * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
-     * @deprecated Will be removed for PFD.
-     */
-    public int returnSlotCount() {
-        return form.returnSlotCount();
-    }
-
-    /**
-     * Find or create an instance of a method type, given the spelling of its bytecode descriptor.
-     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
-     * Any class or interface name embedded in the descriptor string
-     * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
-     * on the given loader (or if it is null, on the system class loader).
-     * <p>
-     * Note that it is possible to encounter method types which cannot be
-     * constructed by this method, because their component types are
-     * not all reachable from a common class loader.
-     * <p>
-     * This method is included for the benfit of applications that must
-     * generate bytecodes that process method handles and {@code invokedynamic}.
-     * @param descriptor a bytecode-level type descriptor string "(T...)T"
-     * @param loader the class loader in which to look up the types
-     * @return a method type matching the bytecode-level type descriptor
-     * @throws IllegalArgumentException if the string is not well-formed
-     * @throws TypeNotPresentException if a named type cannot be found
-     */
-    public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
-        throws IllegalArgumentException, TypeNotPresentException
-    {
-        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);
-    }
-
-    /**
-     * Produces a bytecode descriptor representation of the method type.
-     * <p>
-     * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
-     * Two distinct classes which share a common name but have different class loaders
-     * will appear identical when viewed within descriptor strings.
-     * <p>
-     * This method is included for the benfit of applications that must
-     * generate bytecodes that process method handles and {@code invokedynamic}.
-     * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
-     * because the latter requires a suitable class loader argument.
-     * @return the bytecode type descriptor representation
-     */
-    public String toMethodDescriptorString() {
-        return BytecodeDescriptor.unparse(this);
-    }
-
-    /// Serialization.
-
-    /**
-     * There are no serializable fields for {@code MethodType}.
-     */
-    private static final java.io.ObjectStreamField[] serialPersistentFields = { };
-
-    /**
-     * Save the {@code MethodType} instance to a stream.
-     *
-     * @serialData
-     * For portability, the serialized format does not refer to named fields.
-     * Instead, the return type and parameter type arrays are written directly
-     * from the {@code writeObject} method, using two calls to {@code s.writeObject}
-     * as follows:
-     * <blockquote><pre>
-s.writeObject(this.returnType());
-s.writeObject(this.parameterArray());
-     * </pre></blockquote>
-     * <p>
-     * The deserialized field values are checked as if they were
-     * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
-     * For example, null values, or {@code void} parameter types,
-     * will lead to exceptions during deserialization.
-     * @param the stream to write the object to
-     */
-    private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-        s.defaultWriteObject();  // requires serialPersistentFields to be an empty array
-        s.writeObject(returnType());
-        s.writeObject(parameterArray());
-    }
-
-    /**
-     * Reconstitute the {@code MethodType} instance from a stream (that is,
-     * deserialize it).
-     * This instance is a scratch object with bogus final fields.
-     * It provides the parameters to the factory method called by
-     * {@link #readResolve readResolve}.
-     * After that call it is discarded.
-     * @param the stream to read the object from
-     * @see #MethodType()
-     * @see #readResolve
-     * @see #writeObject
-     */
-    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-        s.defaultReadObject();  // requires serialPersistentFields to be an empty array
-
-        Class<?>   returnType     = (Class<?>)   s.readObject();
-        Class<?>[] parameterArray = (Class<?>[]) s.readObject();
-
-        // Probably this object will never escape, but let's check
-        // the field values now, just to be sure.
-        checkRtype(returnType);
-        checkPtypes(parameterArray);
-
-        parameterArray = parameterArray.clone();  // make sure it is unshared
-        MethodType_init(returnType, parameterArray);
-    }
-
-    /**
-     * For serialization only.
-     * Sets the final fields to null, pending {@code Unsafe.putObject}.
-     */
-    private MethodType() {
-        this.rtype = null;
-        this.ptypes = null;
-    }
-    private void MethodType_init(Class<?> rtype, Class<?>[] ptypes) {
-        // In order to communicate these values to readResolve, we must
-        // store them into the implementation-specific final fields.
-        checkRtype(rtype);
-        checkPtypes(ptypes);
-        unsafe.putObject(this, rtypeOffset, rtype);
-        unsafe.putObject(this, ptypesOffset, ptypes);
-    }
-
-    // Support for resetting final fields while deserializing
-    private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
-    private static final long rtypeOffset, ptypesOffset;
-    static {
-        try {
-            rtypeOffset = unsafe.objectFieldOffset
-                (MethodType.class.getDeclaredField("rtype"));
-            ptypesOffset = unsafe.objectFieldOffset
-                (MethodType.class.getDeclaredField("ptypes"));
-        } catch (Exception ex) {
-            throw new Error(ex);
-        }
-    }
-
-    /**
-     * Resolves and initializes a {@code MethodType} object
-     * after serialization.
-     * @return the fully initialized {@code MethodType} object
-     */
-    private Object readResolve() {
-        // Do not use a trusted path for deserialization:
-        //return makeImpl(rtype, ptypes, true);
-        // Verify all operands, and make sure ptypes is unshared:
-        return methodType(rtype, ptypes);
-    }
-}
--- a/jdk/src/share/classes/java/dyn/MethodTypeForm.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * TO DO:  Temporary shim; remove after refactoring effects are complete in JVM.
- * @author John Rose
- */
-import sun.dyn.MethodTypeImpl;
-
-class MethodTypeForm extends MethodTypeImpl {
-
-    MethodTypeForm(MethodType erasedType) {
-        super(erasedType);
-    }
-}
--- a/jdk/src/share/classes/java/dyn/MutableCallSite.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,282 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.*;
-import sun.dyn.empty.Empty;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * A {@code MutableCallSite} is a {@link CallSite} whose target variable
- * behaves like an ordinary field.
- * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates
- * all calls to the site's current target.
- * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site
- * also delegates each call to the site's current target.
- * <p>
- * Here is an example of a mutable call site which introduces a
- * state variable into a method handle chain.
- * <blockquote><pre>
-MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
-MethodHandle MH_name = name.dynamicInvoker();
-MethodType MT_str2 = MethodType.methodType(String.class, String.class);
-MethodHandle MH_upcase = MethodHandles.lookup()
-    .findVirtual(String.class, "toUpperCase", MT_str2);
-MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
-name.setTarget(MethodHandles.constant(String.class, "Rocky"));
-assertEquals("ROCKY", (String) worker1.invokeExact());
-name.setTarget(MethodHandles.constant(String.class, "Fred"));
-assertEquals("FRED", (String) worker1.invokeExact());
-// (mutation can be continued indefinitely)
- * </pre></blockquote>
- * <p>
- * The same call site may be used in several places at once.
- * <blockquote><pre>
-MethodHandle MH_dear = MethodHandles.lookup()
-    .findVirtual(String.class, "concat", MT_str2).bindTo(", dear?");
-MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
-assertEquals("Fred, dear?", (String) worker2.invokeExact());
-name.setTarget(MethodHandles.constant(String.class, "Wilma"));
-assertEquals("WILMA", (String) worker1.invokeExact());
-assertEquals("Wilma, dear?", (String) worker2.invokeExact());
- * </pre></blockquote>
- * <p>
- * <em>Non-synchronization of target values:</em>
- * A write to a mutable call site's target does not force other threads
- * to become aware of the updated value.  Threads which do not perform
- * suitable synchronization actions relative to the updated call site
- * may cache the old target value and delay their use of the new target
- * value indefinitely.
- * (This is a normal consequence of the Java Memory Model as applied
- * to object fields.)
- * <p>
- * The {@link #syncAll syncAll} operation provides a way to force threads
- * to accept a new target value, even if there is no other synchronization.
- * <p>
- * For target values which will be frequently updated, consider using
- * a {@linkplain VolatileCallSite volatile call site} instead.
- * @author John Rose, JSR 292 EG
- */
-public class MutableCallSite extends CallSite {
-    /**
-     * Creates a blank call site object with the given method type.
-     * The initial target is set to a method handle of the given type
-     * which will throw an {@link IllegalStateException} if called.
-     * <p>
-     * The type of the call site is permanently set to the given type.
-     * <p>
-     * Before this {@code CallSite} object is returned from a bootstrap method,
-     * or invoked in some other manner,
-     * it is usually provided with a more useful target method,
-     * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
-     * @param type the method type that this call site will have
-     * @throws NullPointerException if the proposed type is null
-     */
-    public MutableCallSite(MethodType type) {
-        super(type);
-    }
-
-    /**
-     * Creates a call site object with an initial target method handle.
-     * The type of the call site is permanently set to the initial target's type.
-     * @param target the method handle that will be the initial target of the call site
-     * @throws NullPointerException if the proposed target is null
-     */
-    public MutableCallSite(MethodHandle target) {
-        super(target);
-    }
-
-    /**
-     * Returns the target method of the call site, which behaves
-     * like a normal field of the {@code MutableCallSite}.
-     * <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
-     * non-volatile, non-final field.
-     * <p>
-     * In particular, the current thread may choose to reuse the result
-     * of a previous read of the target from memory, and may fail to see
-     * a recent update to the target by another thread.
-     *
-     * @return the linkage state of this call site, a method handle which can change over time
-     * @see #setTarget
-     */
-    @Override public final MethodHandle getTarget() {
-        return target;
-    }
-
-    /**
-     * Updates the target method of this call site, as a normal variable.
-     * The type of the new target must agree with the type of the old target.
-     * <p>
-     * The interactions with memory are the same
-     * as of a write to an ordinary variable, such as an array element or a
-     * non-volatile, non-final field.
-     * <p>
-     * In particular, unrelated threads may fail to see the updated target
-     * until they perform a read from memory.
-     * Stronger guarantees can be created by putting appropriate operations
-     * into the bootstrap method and/or the target methods used
-     * at any given call site.
-     *
-     * @param newTarget the new target
-     * @throws NullPointerException if the proposed new target is null
-     * @throws WrongMethodTypeException if the proposed new target
-     *         has a method type that differs from the previous target
-     * @see #getTarget
-     */
-    @Override public void setTarget(MethodHandle newTarget) {
-        checkTargetChange(this.target, newTarget);
-        setTargetNormal(newTarget);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public final MethodHandle dynamicInvoker() {
-        return makeDynamicInvoker();
-    }
-
-    /**
-     * Performs a synchronization operation on each call site in the given array,
-     * forcing all other threads to throw away any cached values previously
-     * loaded from the target of any of the call sites.
-     * <p>
-     * This operation does not reverse any calls that have already started
-     * on an old target value.
-     * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.)
-     * <p>
-     * The overall effect is to force all future readers of each call site's target
-     * to accept the most recently stored value.
-     * ("Most recently" is reckoned relative to the {@code syncAll} itself.)
-     * Conversely, the {@code syncAll} call may block until all readers have
-     * (somehow) decached all previous versions of each call site's target.
-     * <p>
-     * To avoid race conditions, calls to {@code setTarget} and {@code syncAll}
-     * should generally be performed under some sort of mutual exclusion.
-     * Note that reader threads may observe an updated target as early
-     * as the {@code setTarget} call that install the value
-     * (and before the {@code syncAll} that confirms the value).
-     * On the other hand, reader threads may observe previous versions of
-     * the target until the {@code syncAll} call returns
-     * (and after the {@code setTarget} that attempts to convey the updated version).
-     * <p>
-     * This operation is likely to be expensive and should be used sparingly.
-     * If possible, it should be buffered for batch processing on sets of call sites.
-     * <p>
-     * If {@code sites} contains a null element,
-     * a {@code NullPointerException} will be raised.
-     * In this case, some non-null elements in the array may be
-     * processed before the method returns abnormally.
-     * Which elements these are (if any) is implementation-dependent.
-     *
-     * <h3>Java Memory Model details</h3>
-     * In terms of the Java Memory Model, this operation performs a synchronization
-     * action which is comparable in effect to the writing of a volatile variable
-     * by the current thread, and an eventual volatile read by every other thread
-     * that may access one of the affected call sites.
-     * <p>
-     * The following effects are apparent, for each individual call site {@code S}:
-     * <ul>
-     * <li>A new volatile variable {@code V} is created, and written by the current thread.
-     *     As defined by the JMM, this write is a global synchronization event.
-     * <li>As is normal with thread-local ordering of write events,
-     *     every action already performed by the current thread is
-     *     taken to happen before the volatile write to {@code V}.
-     *     (In some implementations, this means that the current thread
-     *     performs a global release operation.)
-     * <li>Specifically, the write to the current target of {@code S} is
-     *     taken to happen before the volatile write to {@code V}.
-     * <li>The volatile write to {@code V} is placed
-     *     (in an implementation specific manner)
-     *     in the global synchronization order.
-     * <li>Consider an arbitrary thread {@code T} (other than the current thread).
-     *     If {@code T} executes a synchronization action {@code A}
-     *     after the volatile write to {@code V} (in the global synchronization order),
-     *     it is therefore required to see either the current target
-     *     of {@code S}, or a later write to that target,
-     *     if it executes a read on the target of {@code S}.
-     *     (This constraint is called "synchronization-order consistency".)
-     * <li>The JMM specifically allows optimizing compilers to elide
-     *     reads or writes of variables that are known to be useless.
-     *     Such elided reads and writes have no effect on the happens-before
-     *     relation.  Regardless of this fact, the volatile {@code V}
-     *     will not be elided, even though its written value is
-     *     indeterminate and its read value is not used.
-     * </ul>
-     * Because of the last point, the implementation behaves as if a
-     * volatile read of {@code V} were performed by {@code T}
-     * immediately after its action {@code A}.  In the local ordering
-     * of actions in {@code T}, this read happens before any future
-     * read of the target of {@code S}.  It is as if the
-     * implementation arbitrarily picked a read of {@code S}'s target
-     * by {@code T}, and forced a read of {@code V} to precede it,
-     * thereby ensuring communication of the new target value.
-     * <p>
-     * As long as the constraints of the Java Memory Model are obeyed,
-     * implementations may delay the completion of a {@code syncAll}
-     * operation while other threads ({@code T} above) continue to
-     * use previous values of {@code S}'s target.
-     * However, implementations are (as always) encouraged to avoid
-     * livelock, and to eventually require all threads to take account
-     * of the updated target.
-     *
-     * <p style="font-size:smaller;">
-     * <em>Discussion:</em>
-     * For performance reasons, {@code syncAll} is not a virtual method
-     * on a single call site, but rather applies to a set of call sites.
-     * Some implementations may incur a large fixed overhead cost
-     * for processing one or more synchronization operations,
-     * but a small incremental cost for each additional call site.
-     * In any case, this operation is likely to be costly, since
-     * other threads may have to be somehow interrupted
-     * in order to make them notice the updated target value.
-     * However, it may be observed that a single call to synchronize
-     * several sites has the same formal effect as many calls,
-     * each on just one of the sites.
-     *
-     * <p style="font-size:smaller;">
-     * <em>Implementation Note:</em>
-     * Simple implementations of {@code MutableCallSite} may use
-     * a volatile variable for the target of a mutable call site.
-     * In such an implementation, the {@code syncAll} method can be a no-op,
-     * and yet it will conform to the JMM behavior documented above.
-     *
-     * @param sites an array of call sites to be synchronized
-     * @throws NullPointerException if the {@code sites} array reference is null
-     *                              or the array contains a null
-     */
-    public static void syncAll(MutableCallSite[] sites) {
-        if (sites.length == 0)  return;
-        STORE_BARRIER.lazySet(0);
-        for (int i = 0; i < sites.length; i++) {
-            sites[i].getClass();  // trigger NPE on first null
-        }
-        // FIXME: NYI
-    }
-    private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
-}
--- a/jdk/src/share/classes/java/dyn/SwitchPoint.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * <p>
- * A {@code SwitchPoint} is an object which can publish state transitions to other threads.
- * A switch point is initially in the <em>valid</em> state, but may at any time be
- * changed to the <em>invalid</em> state.  Invalidation cannot be reversed.
- * A switch point can combine a <em>guarded pair</em> of method handles into a
- * <em>guarded delegator</em>.
- * The guarded delegator is a method handle which delegates to one of the old method handles.
- * The state of the switch point determines which of the two gets the delegation.
- * <p>
- * A single switch point may be used to control any number of method handles.
- * (Indirectly, therefore, it can control any number of call sites.)
- * This is done by using the single switch point as a factory for combining
- * any number of guarded method handle pairs into guarded delegators.
- * <p>
- * When a guarded delegator is created from a guarded pair, the pair
- * is wrapped in a new method handle {@code M},
- * which is permanently associated with the switch point that created it.
- * Each pair consists of a target {@code T} and a fallback {@code F}.
- * While the switch point is valid, invocations to {@code M} are delegated to {@code T}.
- * After it is invalidated, invocations are delegated to {@code F}.
- * <p>
- * Invalidation is global and immediate, as if the switch point contained a
- * volatile boolean variable consulted on every call to {@code M}.
- * The invalidation is also permanent, which means the switch point
- * can change state only once.
- * The switch point will always delegate to {@code F} after being invalidated.
- * At that point {@code guardWithTest} may ignore {@code T} and return {@code F}.
- * <p>
- * Here is an example of a switch point in action:
- * <blockquote><pre>
-MethodType MT_str2 = MethodType.methodType(String.class, String.class);
-MethodHandle MH_strcat = MethodHandles.lookup()
-    .findVirtual(String.class, "concat", MT_str2);
-SwitchPoint spt = new SwitchPoint();
-// the following steps may be repeated to re-use the same switch point:
-MethodHandle worker1 = strcat;
-MethodHandle worker2 = MethodHandles.permuteArguments(strcat, MT_str2, 1, 0);
-MethodHandle worker = spt.guardWithTest(worker1, worker2);
-assertEquals("method", (String) worker.invokeExact("met", "hod"));
-SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
-assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
- * </pre></blockquote>
- * <p style="font-size:smaller;">
- * <em>Discussion:</em>
- * Switch points are useful without subclassing.  They may also be subclassed.
- * This may be useful in order to associate application-specific invalidation logic
- * with the switch point.
- * <p style="font-size:smaller;">
- * <em>Implementation Note:</em>
- * A switch point behaves as if implemented on top of {@link MutableCallSite},
- * approximately as follows:
- * <blockquote><pre>
-public class SwitchPoint {
-  private static final MethodHandle
-    K_true  = MethodHandles.constant(boolean.class, true),
-    K_false = MethodHandles.constant(boolean.class, false);
-  private final MutableCallSite mcs;
-  private final MethodHandle mcsInvoker;
-  public SwitchPoint() {
-    this.mcs = new MutableCallSite(K_true);
-    this.mcsInvoker = mcs.dynamicInvoker();
-  }
-  public MethodHandle guardWithTest(
-                MethodHandle target, MethodHandle fallback) {
-    // Note:  mcsInvoker is of type ()boolean.
-    // Target and fallback may take any arguments, but must have the same type.
-    return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
-  }
-  public static void invalidateAll(SwitchPoint[] spts) {
-    List&lt;MutableCallSite&gt; mcss = new ArrayList&lt;&gt;();
-    for (SwitchPoint spt : spts)  mcss.add(spt.mcs);
-    for (MutableCallSite mcs : mcss)  mcs.setTarget(K_false);
-    MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
-  }
-}
- * </pre></blockquote>
- * @author Remi Forax, JSR 292 EG
- */
-public class SwitchPoint {
-    private static final MethodHandle
-        K_true  = MethodHandles.constant(boolean.class, true),
-        K_false = MethodHandles.constant(boolean.class, false);
-
-    private final MutableCallSite mcs;
-    private final MethodHandle mcsInvoker;
-
-    /**
-     * Creates a new switch point.
-     */
-    public SwitchPoint() {
-        this.mcs = new MutableCallSite(K_true);
-        this.mcsInvoker = mcs.dynamicInvoker();
-    }
-
-    /**
-     * Returns a method handle which always delegates either to the target or the fallback.
-     * The method handle will delegate to the target exactly as long as the switch point is valid.
-     * After that, it will permanently delegate to the fallback.
-     * <p>
-     * The target and fallback must be of exactly the same method type,
-     * and the resulting combined method handle will also be of this type.
-     *
-     * @param target the method handle selected by the switch point as long as it is valid
-     * @param fallback the method handle selected by the switch point after it is invalidated
-     * @return a combined method handle which always calls either the target or fallback
-     * @throws NullPointerException if either argument is null
-     * @see MethodHandles#guardWithTest
-     */
-    public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) {
-        if (mcs.getTarget() == K_false)
-            return fallback;  // already invalid
-        return MethodHandles.guardWithTest(mcsInvoker, target, fallback);
-    }
-
-    /**
-     * Sets all of the given switch points into the invalid state.
-     * After this call executes, no thread will observe any of the
-     * switch points to be in a valid state.
-     * <p>
-     * This operation is likely to be expensive and should be used sparingly.
-     * If possible, it should be buffered for batch processing on sets of switch points.
-     * <p>
-     * If {@code switchPoints} contains a null element,
-     * a {@code NullPointerException} will be raised.
-     * In this case, some non-null elements in the array may be
-     * processed before the method returns abnormally.
-     * Which elements these are (if any) is implementation-dependent.
-     *
-     * <p style="font-size:smaller;">
-     * <em>Discussion:</em>
-     * For performance reasons, {@code invalidateAll} is not a virtual method
-     * on a single switch point, but rather applies to a set of switch points.
-     * Some implementations may incur a large fixed overhead cost
-     * for processing one or more invalidation operations,
-     * but a small incremental cost for each additional invalidation.
-     * In any case, this operation is likely to be costly, since
-     * other threads may have to be somehow interrupted
-     * in order to make them notice the updated switch point state.
-     * However, it may be observed that a single call to invalidate
-     * several switch points has the same formal effect as many calls,
-     * each on just one of the switch points.
-     *
-     * <p style="font-size:smaller;">
-     * <em>Implementation Note:</em>
-     * Simple implementations of {@code SwitchPoint} may use
-     * a private {@link MutableCallSite} to publish the state of a switch point.
-     * In such an implementation, the {@code invalidateAll} method can
-     * simply change the call site's target, and issue one call to
-     * {@linkplain MutableCallSite#syncAll synchronize} all the
-     * private call sites.
-     *
-     * @param switchPoints an array of call sites to be synchronized
-     * @throws NullPointerException if the {@code switchPoints} array reference is null
-     *                              or the array contains a null
-     */
-    public static void invalidateAll(SwitchPoint[] switchPoints) {
-        if (switchPoints.length == 0)  return;
-        MutableCallSite[] sites = new MutableCallSite[switchPoints.length];
-        for (int i = 0; i < switchPoints.length; i++) {
-            SwitchPoint spt = switchPoints[i];
-            if (spt == null)  break;  // MSC.syncAll will trigger a NPE
-            sites[i] = spt.mcs;
-            spt.mcs.setTarget(K_false);
-        }
-        MutableCallSite.syncAll(sites);
-    }
-}
--- a/jdk/src/share/classes/java/dyn/VolatileCallSite.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.util.List;
-
-/**
- * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
- * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates
- * to its call site target immediately, even if the update occurs in another thread.
- * There may be a performance penalty for such tight coupling between threads.
- * <p>
- * Unlike {@code MutableCallSite}, there is no
- * {@linkplain MutableCallSite#syncAll syncAll operation} on volatile
- * call sites, since every write to a volatile variable is implicitly
- * synchronized with reader threads.
- * <p>
- * In other respects, a {@code VolatileCallSite} is interchangeable
- * with {@code MutableCallSite}.
- * @see MutableCallSite
- * @author John Rose, JSR 292 EG
- */
-public class VolatileCallSite extends CallSite {
-    /**
-     * Creates a call site with a volatile binding to its target.
-     * The initial target is set to a method handle
-     * of the given type which will throw an {@code IllegalStateException} if called.
-     * @param type the method type that this call site will have
-     * @throws NullPointerException if the proposed type is null
-     */
-    public VolatileCallSite(MethodType type) {
-        super(type);
-    }
-
-    /**
-     * Creates a call site with a volatile binding to its target.
-     * The target is set to the given value.
-     * @param target the method handle that will be the initial target of the call site
-     * @throws NullPointerException if the proposed target is null
-     */
-    public VolatileCallSite(MethodHandle target) {
-        super(target);
-    }
-
-    /**
-     * Returns the target method of the call site, which behaves
-     * like a {@code volatile} field of the {@code VolatileCallSite}.
-     * <p>
-     * The interactions of {@code getTarget} with memory are the same
-     * as of a read from a {@code volatile} field.
-     * <p>
-     * In particular, the current thread is required to issue a fresh
-     * read of the target from memory, and must not fail to see
-     * a recent update to the target by another thread.
-     *
-     * @return the linkage state of this call site, a method handle which can change over time
-     * @see #setTarget
-     */
-    @Override public final MethodHandle getTarget() {
-        return getTargetVolatile();
-    }
-
-    /**
-     * Updates the target method of this call site, as a volatile variable.
-     * The type of the new target must agree with the type of the old target.
-     * <p>
-     * The interactions with memory are the same as of a write to a volatile field.
-     * In particular, any threads is guaranteed to see the updated target
-     * the next time it calls {@code getTarget}.
-     * @param newTarget the new target
-     * @throws NullPointerException if the proposed new target is null
-     * @throws WrongMethodTypeException if the proposed new target
-     *         has a method type that differs from the previous target
-     * @see #getTarget
-     */
-    @Override public void setTarget(MethodHandle newTarget) {
-        checkTargetChange(getTargetVolatile(), newTarget);
-        setTargetVolatile(newTarget);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public final MethodHandle dynamicInvoker() {
-        return makeDynamicInvoker();
-    }
-}
--- a/jdk/src/share/classes/java/dyn/WrongMethodTypeException.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * Thrown to indicate that code has attempted to call a method handle
- * via the wrong method type.  As with the bytecode representation of
- * normal Java method calls, method handle calls are strongly typed
- * to a specific type descriptor associated with a call site.
- * <p>
- * This exception may also be thrown when two method handles are
- * composed, and the system detects that their types cannot be
- * matched up correctly.  This amounts to an early evaluation
- * of the type mismatch, at method handle construction time,
- * instead of when the mismatched method handle is called.
- *
- * @author John Rose, JSR 292 EG
- * @since 1.7
- */
-public class WrongMethodTypeException extends RuntimeException {
-    private static final long serialVersionUID = 292L;
-
-    /**
-     * Constructs a {@code WrongMethodTypeException} with no detail message.
-     */
-    public WrongMethodTypeException() {
-        super();
-    }
-
-    /**
-     * Constructs a {@code WrongMethodTypeException} with the specified
-     * detail message.
-     *
-     * @param s the detail message.
-     */
-    public WrongMethodTypeException(String s) {
-        super(s);
-    }
-}
--- a/jdk/src/share/classes/java/dyn/package-info.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,478 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * The {@code java.lang.invoke} package contains dynamic language support provided directly by
- * the Java core class libraries and virtual machine.
- *
- * <p style="font-size:smaller;">
- * <em>Historic Note:</em> In some early versions of Java SE 7,
- * the name of this package is {@code java.dyn}.
- * <p>
- * Certain types in this package have special relations to dynamic
- * language support in the virtual machine:
- * <ul>
- * <li>The class {@link java.dyn.MethodHandle MethodHandle} contains
- * <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
- * which can be linked regardless of their type descriptor.
- * Normally, method linkage requires exact matching of type descriptors.
- * </li>
- *
- * <li>The JVM bytecode format supports immediate constants of
- * the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}.
- * </li>
- * </ul>
- *
- * <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2>
- * <em>The following low-level information is presented here as a preview of
- * changes being made to the Java Virtual Machine specification for JSR 292.
- * This information will be incorporated in a future version of the JVM specification.</em>
- *
- * <h3><a name="indyinsn"></a>{@code invokedynamic} instruction format</h3>
- * In bytecode, an {@code invokedynamic} instruction is formatted as five bytes.
- * The first byte is the opcode 186 (hexadecimal {@code BA}).
- * The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
- * The final two bytes are reserved for future use and required to be zero.
- * The constant pool reference of an {@code invokedynamic} instruction is to a entry
- * with tag {@code CONSTANT_InvokeDynamic} (decimal 18).  See below for its format.
- * The entry specifies the following information:
- * <ul>
- * <li>a bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant)</li>
- * <li>the dynamic invocation name (a UTF8 string)</li>
- * <li>the argument and return types of the call (encoded as a type descriptor in a UTF8 string)</li>
- * <li>optionally, a sequence of additional <em>static arguments</em> to the bootstrap method ({@code ldc}-type constants)</li>
- * </ul>
- * <p>
- * Each instance of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
- * Multiple instances of an {@code invokedynamic} instruction can share a single
- * {@code CONSTANT_InvokeDynamic} entry.
- * In any case, distinct call sites always have distinct linkage state.
- * <p>
- * A dynamic call site is originally in an unlinked state.  In this state, there is
- * no target method for the call site to invoke.
- * A dynamic call site is linked by means of a bootstrap method,
- * as <a href="#bsm">described below</a>.
- *
- * <p style="font-size:smaller;">
- * <em>Historic Note:</em> Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
- * instead of a {@code CONSTANT_InvokeDynamic}.  In earlier, obsolete versions of this API, the
- * bootstrap method was specified dynamically, in a per-class basis, during class initialization.
- *
- * <h3><a name="indycon"></a>constant pool entries for {@code invokedynamic} instructions</h3>
- * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
- * it must contain exactly four more bytes after the tag.
- * These bytes are interpreted as two 16-bit indexes, in the usual {@code u2} format.
- * The first pair of bytes after the tag must be an index into a side table called the
- * <em>bootstrap method table</em>, which is stored in the {@code BootstrapMethods}
- * attribute as <a href="#bsmattr">described below</a>.
- * The second pair of bytes must be an index to a {@code CONSTANT_NameAndType}.
- * <p>
- * The first index specifies a bootstrap method used by the associated dynamic call sites.
- * The second index specifies the method name, argument types, and return type of the dynamic call site.
- * The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
- * except that the bootstrap method specifier reference replaces
- * the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
- *
- * <h3><a name="mtcon"></a>constant pool entries for {@linkplain java.dyn.MethodType method types}</h3>
- * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
- * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
- * entry which represents a method type descriptor.
- * <p>
- * The JVM will ensure that on first
- * execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType MethodType}
- * will be created which represents the type descriptor.
- * Any classes mentioned in the {@code MethodType} will be loaded if necessary,
- * but not initialized.
- * Access checking and error reporting is performed exactly as it is for
- * references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
- *
- * <h3><a name="mhcon"></a>constant pool entries for {@linkplain java.dyn.MethodHandle method handles}</h3>
- * If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
- * it must contain exactly three more bytes.  The first byte after the tag is a subtag
- * value which must be in the range 1 through 9, and the last two must be an index to a
- * {@code CONSTANT_Fieldref}, {@code CONSTANT_Methodref}, or
- * {@code CONSTANT_InterfaceMethodref} entry which represents a field or method
- * for which a method handle is to be created.
- * Furthermore, the subtag value and the type of the constant index value
- * must agree according to the table below.
- * <p>
- * The JVM will ensure that on first execution of an {@code ldc} instruction
- * for this entry, a {@link java.dyn.MethodHandle MethodHandle} will be created which represents
- * the field or method reference, according to the specific mode implied by the subtag.
- * <p>
- * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
- * the {@code Class} or {@code MethodType} object which reifies the field or method's
- * type is created.  Any classes mentioned in this reification will be loaded if necessary,
- * but not initialized, and access checking and error reporting performed as usual.
- * <p>
- * Unlike the reflective {@code Lookup} API, there are no security manager calls made
- * when these constants are resolved.
- * <p>
- * The method handle itself will have a type and behavior determined by the subtag as follows:
- * <code>
- * <table border=1 cellpadding=5 summary="CONSTANT_MethodHandle subtypes">
- * <tr><th>N</th><th>subtag name</th><th>member</th><th>MH type</th><th>bytecode behavior</th><th>lookup expression</th></tr>
- * <tr><td>1</td><td>REF_getField</td><td>C.f:T</td><td>(C)T</td><td>getfield C.f:T</td>
- *               <td>{@linkplain java.dyn.MethodHandles.Lookup#findGetter findGetter(C.class,"f",T.class)}</td></tr>
- * <tr><td>2</td><td>REF_getStatic</td><td>C.f:T</td><td>(&nbsp;)T</td><td>getstatic C.f:T</td>
- *               <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticGetter findStaticGetter(C.class,"f",T.class)}</td></tr>
- * <tr><td>3</td><td>REF_putField</td><td>C.f:T</td><td>(C,T)void</td><td>putfield C.f:T</td>
- *               <td>{@linkplain java.dyn.MethodHandles.Lookup#findSetter findSetter(C.class,"f",T.class)}</td></tr>
- * <tr><td>4</td><td>REF_putStatic</td><td>C.f:T</td><td>(T)void</td><td>putstatic C.f:T</td>
- *               <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticSetter findStaticSetter(C.class,"f",T.class)}</td></tr>
- * <tr><td>5</td><td>REF_invokeVirtual</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokevirtual C.m(A*)T</td>
- *               <td>{@linkplain java.dyn.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
- * <tr><td>6</td><td>REF_invokeStatic</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokestatic C.m(A*)T</td>
- *               <td>{@linkplain java.dyn.MethodHandles.Lookup#findStatic findStatic(C.class,"m",MT)}</td></tr>
- * <tr><td>7</td><td>REF_invokeSpecial</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokespecial C.m(A*)T</td>
- *               <td>{@linkplain java.dyn.MethodHandles.Lookup#findSpecial findSpecial(C.class,"m",MT,this.class)}</td></tr>
- * <tr><td>8</td><td>REF_newInvokeSpecial</td><td>C.&lt;init&gt;(A*)void</td><td>(A*)C</td><td>new C; dup; invokespecial C.&lt;init&gt;(A*)void</td>
- *               <td>{@linkplain java.dyn.MethodHandles.Lookup#findConstructor findConstructor(C.class,MT)}</td></tr>
- * <tr><td>9</td><td>REF_invokeInterface</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokeinterface C.m(A*)T</td>
- *               <td>{@linkplain java.dyn.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
- * </table>
- * </code>
- * Here, the type {@code C} is taken from the {@code CONSTANT_Class} reference associated
- * with the {@code CONSTANT_NameAndType} descriptor.
- * The field name {@code f} or method name {@code m} is taken from the {@code CONSTANT_NameAndType}
- * as is the result type {@code T} and (in the case of a method or constructor) the argument type sequence
- * {@code A*}.
- * <p>
- * Each method handle constant has an equivalent instruction sequence called its <em>bytecode behavior</em>.
- * In general, creating a method handle constant can be done in exactly the same circumstances that
- * the JVM would successfully resolve the symbolic references in the bytecode behavior.
- * Also, the type of a method handle constant is such that a valid {@code invokeExact} call
- * on the method handle has exactly the same JVM stack effects as the <em>bytecode behavior</em>.
- * Finally, calling a method handle constant on a valid set of arguments has exactly the same effect
- * and returns the same result (if any) as the corresponding <em>bytecode behavior</em>.
- * <p>
- * Each method handle constant also has an equivalent reflective <em>lookup expression</em>,
- * which is a query to a method in {@link java.dyn.MethodHandles.Lookup}.
- * In the example lookup method expression given in the table above, the name {@code MT}
- * stands for a {@code MethodType} built from {@code T} and the sequence of argument types {@code A*}.
- * (Note that the type {@code C} is not prepended to the query type {@code MT} even if the member is non-static.)
- * In the case of {@code findSpecial}, the name {@code this.class} refers to the class containing
- * the bytecodes.
- * <p>
- * The special name {@code <clinit>} is not allowed.
- * The special name {@code <init>} is not allowed except for subtag 8 as shown.
- * <p>
- * The JVM verifier and linker apply the same access checks and restrictions for these references as for the hypothetical
- * bytecode instructions specified in the last column of the table.
- * A method handle constant will successfully resolve to a method handle if the symbolic references
- * of the corresponding bytecode instruction(s) would also resolve successfully.
- * Otherwise, an attempt to resolve the constant will throw equivalent linkage errors.
- * In particular, method handles to
- * private and protected members can be created in exactly those classes for which the corresponding
- * normal accesses are legal.
- * <p>
- * A constant may refer to a method or constructor with the {@code varargs}
- * bit (hexadecimal {@code 0x0080}) set in its modifier bitmask.
- * The method handle constant produced for such a method behaves as if
- * it were created by {@link java.dyn.MethodHandle#asVarargsCollector asVarargsCollector}.
- * In other words, the constant method handle will exhibit variable arity,
- * when invoked via {@code invokeGeneric}.
- * On the other hand, its behavior with respect to {@code invokeExact} will be the same
- * as if the {@code varargs} bit were not set.
- * <p>
- * Although the {@code CONSTANT_MethodHandle} and {@code CONSTANT_MethodType} constant types
- * resolve class names, they do not force class initialization.
- * Method handle constants for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
- * may force class initialization on their first invocation, just like the corresponding bytecodes.
- * <p>
- * The rules of section 5.4.3 of the
- * <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#73492">JVM Specification</a>
- * apply to the resolution of {@code CONSTANT_MethodType}, {@code CONSTANT_MethodHandle},
- * and {@code CONSTANT_InvokeDynamic} constants,
- * by the execution of {@code invokedynamic} and {@code ldc} instructions.
- * (Roughly speaking, this means that every use of a constant pool entry
- * must lead to the same outcome.
- * If the resolution succeeds, the same object reference is produced
- * by every subsequent execution of the same instruction.
- * If the resolution of the constant causes an error to occur,
- * the same error will be re-thrown on every subsequent attempt
- * to use this particular constant.)
- * <p>
- * Constants created by the resolution of these constant pool types are not necessarily
- * interned.  Except for {@code CONSTANT_Class} and {@code CONSTANT_String} entries,
- * two distinct constant pool entries might not resolve to the same reference
- * even if they contain the same symbolic reference.
- *
- * <h2><a name="bsm"></a>Bootstrap Methods</h2>
- * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
- * the call site must first be <em>linked</em>.
- * Linking is accomplished by calling a <em>bootstrap method</em>
- * which is given the static information content of the call site,
- * and which must produce a {@link java.dyn.MethodHandle method handle}
- * that gives the behavior of the call site.
- * <p>
- * Each {@code invokedynamic} instruction statically specifies its own
- * bootstrap method as a constant pool reference.
- * The constant pool reference also specifies the call site's name and type descriptor,
- * just like {@code invokevirtual} and the other invoke instructions.
- * <p>
- * Linking starts with resolving the constant pool entry for the
- * bootstrap method, and resolving a {@link java.dyn.MethodType MethodType} object for
- * the type descriptor of the dynamic call site.
- * This resolution process may trigger class loading.
- * It may therefore throw an error if a class fails to load.
- * This error becomes the abnormal termination of the dynamic
- * call site execution.
- * Linkage does not trigger class initialization.
- * <p>
- * Next, the bootstrap method call is started, with at least four values being stacked:
- * <ul>
- * <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
- * <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em> in which dynamic call site occurs </li>
- * <li>a {@code String}, the method name mentioned in the call site </li>
- * <li>a {@code MethodType}, the resolved type descriptor of the call </li>
- * <li>optionally, one or more <a href="#args">additional static arguments</a> </li>
- * </ul>
- * The method handle is then applied to the other values as if by
- * {@link java.dyn.MethodHandle#invokeGeneric invokeGeneric}.
- * The returned result must be a {@link java.dyn.CallSite CallSite} (or a subclass).
- * The type of the call site's target must be exactly equal to the type
- * derived from the dynamic call site's type descriptor and passed to
- * the bootstrap method.
- * The call site then becomes permanently linked to the dynamic call site.
- * <p>
- * As long as each bootstrap method can be correctly invoked
- * by <code>invokeGeneric</code>, its detailed type is arbitrary.
- * For example, the first argument could be {@code Object}
- * instead of {@code MethodHandles.Lookup}, and the return type
- * could also be {@code Object} instead of {@code CallSite}.
- * <p>
- * As with any method handle constant, a {@code varargs} modifier bit
- * on the bootstrap method is ignored.
- * <p>
- * Note that the first argument of the bootstrap method cannot be
- * a simple {@code Class} reference.  (This is a change from earlier
- * versions of this specification.  If the caller class is needed,
- * it is easy to {@linkplain java.dyn.MethodHandles.Lookup#lookupClass() extract it}
- * from the {@code Lookup} object.)
- * <p>
- * After resolution, the linkage process may fail in a variety of ways.
- * All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError},
- * which is thrown as the abnormal termination of the dynamic call
- * site execution.
- * The following circumstances will cause this:
- * <ul>
- * <li>the index to the bootstrap method specifier is out of range </li>
- * <li>the bootstrap method cannot be resolved </li>
- * <li>the {@code MethodType} to pass to the bootstrap method cannot be resolved </li>
- * <li>a static argument to the bootstrap method cannot be resolved
- *     (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType},
- *     or {@code CONSTANT_MethodHandle} argument cannot be linked) </li>
- * <li>the bootstrap method has the wrong arity,
- *     causing {@code invokeGeneric} to throw {@code WrongMethodTypeException} </li>
- * <li>the bootstrap method has a wrong argument or return type </li>
- * <li>the bootstrap method invocation completes abnormally </li>
- * <li>the result from the bootstrap invocation is not a reference to
- *     an object of type {@link java.dyn.CallSite CallSite} </li>
- * <li>the target of the {@code CallSite} does not have a target of
- *     the expected {@code MethodType} </li>
- * </ul>
- *
- * <h3><a name="linktime"></a>timing of linkage</h3>
- * A dynamic call site is linked just before its first execution.
- * The bootstrap method call implementing the linkage occurs within
- * a thread that is attempting a first execution.
- * <p>
- * If there are several such threads, the bootstrap method may be
- * invoked in several threads concurrently.
- * Therefore, bootstrap methods which access global application
- * data must take the usual precautions against race conditions.
- * In any case, every {@code invokedynamic} instruction is either
- * unlinked or linked to a unique {@code CallSite} object.
- * <p>
- * In an application which requires dynamic call sites with individually
- * mutable behaviors, their bootstrap methods should produce distinct
- * {@link java.dyn.CallSite CallSite} objects, one for each linkage request.
- * Alternatively, an application can link a single {@code CallSite} object
- * to several {@code invokedynamic} instructions, in which case
- * a change to the target method will become visible at each of
- * the instructions.
- * <p>
- * If several threads simultaneously execute a bootstrap method for a single dynamic
- * call site, the JVM must choose one {@code CallSite} object and install it visibly to
- * all threads.  Any other bootstrap method calls are allowed to complete, but their
- * results are ignored, and their dynamic call site invocations proceed with the originally
- * chosen target object.
- *
- * <p style="font-size:smaller;">
- * <em>Historic Note:</em> Unlike some previous versions of this specification,
- * these rules do not enable the JVM to duplicate dynamic call sites,
- * or to issue &ldquo;causeless&rdquo; bootstrap method calls.
- * Every dynamic call site transitions at most once from unlinked to linked,
- * just before its first invocation.
- *
- * <h3><a name="bsmattr">the {@code BootstrapMethods} attribute </h3>
- * Each {@code CONSTANT_InvokeDynamic} entry contains an index which references
- * a bootstrap method specifier; all such specifiers are contained in a separate array.
- * This array is defined by a class attribute named {@code BootstrapMethods}.
- * The body of this attribute consists of a sequence of byte pairs, all interpreted as
- * as 16-bit counts or constant pool indexes, in the {@code u2} format.
- * The attribute body starts with a count of bootstrap method specifiers,
- * which is immediately followed by the sequence of specifiers.
- * <p>
- * Each bootstrap method specifier contains an index to a
- * {@code CONSTANT_MethodHandle} constant, which is the bootstrap
- * method itself.
- * This is followed by a count, and then a sequence (perhaps empty) of
- * indexes to <a href="#args">additional static arguments</a>
- * for the bootstrap method.
- * <p>
- * During class loading, the verifier must check the structure of the
- * {@code BootstrapMethods} attribute.  In particular, each constant
- * pool index must be of the correct type.  A bootstrap method index
- * must refer to a {@code CONSTANT_MethodHandle} (tag 15).
- * Every other index must refer to a valid operand of an
- * {@code ldc_w} or {@code ldc2_w} instruction (tag 3..8 or 15..16).
- *
- * <h3><a name="args">static arguments to the bootstrap method</h3>
- * An {@code invokedynamic} instruction specifies at least three arguments
- * to pass to its bootstrap method:
- * The caller class (expressed as a {@link java.dyn.MethodHandles.Lookup Lookup object},
- * the name (extracted from the {@code CONSTANT_NameAndType} entry),
- * and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
- * The {@code invokedynamic} instruction may specify additional metadata values
- * to pass to its bootstrap method.
- * Collectively, these values are called <em>static arguments</em> to the
- * {@code invokedynamic} instruction, because they are used once at link
- * time to determine the instruction's behavior on subsequent sets of
- * <em>dynamic arguments</em>.
- * <p>
- * Static arguments are used to communicate application-specific meta-data
- * to the bootstrap method.
- * Drawn from the constant pool, they may include references to classes, method handles,
- * strings, or numeric data that may be relevant to the task of linking that particular call site.
- * <p>
- * Static arguments are specified constant pool indexes stored in the {@code BootstrapMethods} attribute.
- * Before the bootstrap method is invoked, each index is used to compute an {@code Object}
- * reference to the indexed value in the constant pool.
- * The valid constant pool entries are listed in this table:
- * <code>
- * <table border=1 cellpadding=5 summary="Static argument types">
- * <tr><th>entry type</th><th>argument type</th><th>argument value</th></tr>
- * <tr><td>CONSTANT_String</td><td><code>java.lang.String</code></td><td>the indexed string literal</td></tr>
- * <tr><td>CONSTANT_Class</td><td><code>java.lang.Class</code></td><td>the indexed class, resolved</td></tr>
- * <tr><td>CONSTANT_Integer</td><td><code>java.lang.Integer</code></td><td>the indexed int value</td></tr>
- * <tr><td>CONSTANT_Long</td><td><code>java.lang.Long</code></td><td>the indexed long value</td></tr>
- * <tr><td>CONSTANT_Float</td><td><code>java.lang.Float</code></td><td>the indexed float value</td></tr>
- * <tr><td>CONSTANT_Double</td><td><code>java.lang.Double</code></td><td>the indexed double value</td></tr>
- * <tr><td>CONSTANT_MethodHandle</td><td><code>java.dyn.MethodHandle</code></td><td>the indexed method handle constant</td></tr>
- * <tr><td>CONSTANT_MethodType</td><td><code>java.dyn.MethodType</code></td><td>the indexed method type constant</td></tr>
- * </table>
- * </code>
- * <p>
- * If a given {@code invokedynamic} instruction specifies no static arguments,
- * the instruction's bootstrap method will be invoked on three arguments,
- * conveying the instruction's caller class, name, and method type.
- * If the {@code invokedynamic} instruction specifies one or more static arguments,
- * those values will be passed as additional arguments to the method handle.
- * (Note that because there is a limit of 255 arguments to any method,
- * at most 252 extra arguments can be supplied.)
- * The bootstrap method will be invoked as if by either {@code invokeGeneric}
- * or {@code invokeWithArguments}.  (There is no way to tell the difference.)
- * <p>
- * The normal argument conversion rules for {@code invokeGeneric} apply to all stacked arguments.
- * For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion.
- * If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set),
- * then some or all of the arguments specified here may be collected into a trailing array parameter.
- * (This is not a special rule, but rather a useful consequence of the interaction
- * between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
- * and the {@code java.dyn.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
- * <p>
- * Given these rules, here are examples of legal bootstrap method declarations,
- * given various numbers {@code N} of extra arguments.
- * The first rows (marked {@code *}) will work for any number of extra arguments.
- * <code>
- * <table border=1 cellpadding=5 summary="Static argument types">
- * <tr><th>N</th><th>sample bootstrap method</th></tr>
- * <tr><td>*</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
- * <tr><td>*</td><td><code>CallSite bootstrap(Object... args)</code></td></tr>
- * <tr><td>*</td><td><code>CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)</code></td></tr>
- * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type)</code></td></tr>
- * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, Object... nameAndType)</code></td></tr>
- * <tr><td>1</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)</code></td></tr>
- * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
- * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)</code></td></tr>
- * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)</code></td></tr>
- * </table>
- * </code>
- * The last example assumes that the extra arguments are of type
- * {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively.
- * The second-to-last example assumes that all extra arguments are of type
- * {@code CONSTANT_String}.
- * The other examples work with all types of extra arguments.
- * <p>
- * As noted above, the actual method type of the bootstrap method can vary.
- * For example, the fourth argument could be {@code MethodHandle},
- * if that is the type of the corresponding constant in
- * the {@code CONSTANT_InvokeDynamic} entry.
- * In that case, the {@code invokeGeneric} call will pass the extra method handle
- * constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric}
- * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
- * (If a string constant were passed instead, by badly generated code, that cast would then fail,
- * resulting in an {@code InvokeDynamicBootstrapError}.)
- * <p>
- * Extra bootstrap method arguments are intended to allow language implementors
- * to safely and compactly encode metadata.
- * In principle, the name and extra arguments are redundant,
- * since each call site could be given its own unique bootstrap method.
- * Such a practice is likely to produce large class files and constant pools.
- *
- * <h2><a name="structs"></a>Structure Summary</h2>
- * <blockquote><pre>// summary of constant and attribute structures
-struct CONSTANT_MethodHandle_info {
-  u1 tag = 15;
-  u1 reference_kind;       // 1..8 (one of REF_invokeVirtual, etc.)
-  u2 reference_index;      // index to CONSTANT_Fieldref or *Methodref
-}
-struct CONSTANT_MethodType_info {
-  u1 tag = 16;
-  u2 descriptor_index;    // index to CONSTANT_Utf8, as in NameAndType
-}
-struct CONSTANT_InvokeDynamic_info {
-  u1 tag = 18;
-  u2 bootstrap_method_attr_index;  // index into BootstrapMethods_attr
-  u2 name_and_type_index;          // index to CONSTANT_NameAndType, as in Methodref
-}
-struct BootstrapMethods_attr {
- u2 name;  // CONSTANT_Utf8 = "BootstrapMethods"
- u4 size;
- u2 bootstrap_method_count;
- struct bootstrap_method_specifier {
-   u2 bootstrap_method_ref;  // index to CONSTANT_MethodHandle
-   u2 bootstrap_argument_count;
-   u2 bootstrap_arguments[bootstrap_argument_count];  // constant pool indexes
- } bootstrap_methods[bootstrap_method_count];
-}
- * </pre></blockquote>
- *
- * @author John Rose, JSR 292 EG
- */
-
-package java.dyn;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/BootstrapMethodError.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * Thrown to indicate that an {@code invokedynamic} instruction has
+ * failed to find its bootstrap method,
+ * or the bootstrap method has failed to provide a
+ * {@linkplain java.lang.invoke.CallSite call site} with a {@linkplain java.lang.invoke.CallSite#getTarget target}
+ * of the correct {@linkplain java.lang.invoke.MethodHandle#type method type}.
+ *
+ * @author John Rose, JSR 292 EG
+ * @since 1.7
+ */
+public class BootstrapMethodError extends LinkageError {
+    private static final long serialVersionUID = 292L;
+
+    /**
+     * Constructs an {@code BootstrapMethodError} with no detail message.
+     */
+    public BootstrapMethodError() {
+        super();
+    }
+
+    /**
+     * Constructs an {@code BootstrapMethodError} with the specified
+     * detail message.
+     *
+     * @param s the detail message.
+     */
+    public BootstrapMethodError(String s) {
+        super(s);
+    }
+
+    /**
+     * Constructs a {@code BootstrapMethodError} with the specified
+     * detail message and cause.
+     *
+     * @param s the detail message.
+     * @param cause the cause, may be {@code null}.
+     */
+    public BootstrapMethodError(String s, Throwable cause) {
+        super(s, cause);
+    }
+
+    /**
+     * Constructs a {@code BootstrapMethodError} with the specified
+     * cause.
+     *
+     * @param cause the cause, may be {@code null}.
+     */
+    public BootstrapMethodError(Throwable cause) {
+        // cf. Throwable(Throwable cause) constructor.
+        super(cause == null ? null : cause.toString());
+        initCause(cause);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/ClassValue.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Lazily associate a computed value with (potentially) every type.
+ * For example, if a dynamic language needs to construct a message dispatch
+ * table for each class encountered at a message send call site,
+ * it can use a {@code ClassValue} to cache information needed to
+ * perform the message send quickly, for each class encountered.
+ * @author John Rose, JSR 292 EG
+ * @since 1.7
+ */
+public abstract class ClassValue<T> {
+    /**
+     * Computes the given class's derived value for this {@code ClassValue}.
+     * <p>
+     * This method will be invoked within the first thread that accesses
+     * the value with the {@link #get get} method.
+     * <p>
+     * Normally, this method is invoked at most once per class,
+     * but it may be invoked again if there has been a call to
+     * {@link #remove remove}.
+     * <p>
+     * If this method throws an exception, the corresponding call to {@code get}
+     * will terminate abnormally with that exception, and no class value will be recorded.
+     *
+     * @param type the type whose class value must be computed
+     * @return the newly computed value associated with this {@code ClassValue}, for the given class or interface
+     * @see #get
+     * @see #remove
+     */
+    protected abstract T computeValue(Class<?> type);
+
+    /**
+     * Returns the value for the given class.
+     * If no value has yet been computed, it is obtained by
+     * an invocation of the {@link #computeValue computeValue} method.
+     * <p>
+     * The actual installation of the value on the class
+     * is performed atomically.
+     * At that point, if several racing threads have
+     * computed values, one is chosen, and returned to
+     * all the racing threads.
+     * <p>
+     * The {@code type} parameter is typically a class, but it may be any type,
+     * such as an interface, a primitive type (like {@code int.class}), or {@code void.class}.
+     * <p>
+     * In the absence of {@code remove} calls, a class value has a simple
+     * state diagram:  uninitialized and initialized.
+     * When {@code remove} calls are made,
+     * the rules for value observation are more complex.
+     * See the documentation for {@link #remove remove} for more information.
+     *
+     * @param type the type whose class value must be computed or retrieved
+     * @return the current value associated with this {@code ClassValue}, for the given class or interface
+     * @throws NullPointerException if the argument is null
+     * @see #remove
+     * @see #computeValue
+     */
+    public T get(Class<?> type) {
+        ClassValueMap map = getMap(type);
+        if (map != null) {
+            Object x = map.get(this);
+            if (x != null) {
+                return (T) map.unmaskNull(x);
+            }
+        }
+        return setComputedValue(type);
+    }
+
+    /**
+     * Removes the associated value for the given class.
+     * If this value is subsequently {@linkplain #get read} for the same class,
+     * its value will be reinitialized by invoking its {@link #computeValue computeValue} method.
+     * This may result in an additional invocation of the
+     * {@code computeValue computeValue} method for the given class.
+     * <p>
+     * In order to explain the interaction between {@code get} and {@code remove} calls,
+     * we must model the state transitions of a class value to take into account
+     * the alternation between uninitialized and initialized states.
+     * To do this, number these states sequentially from zero, and note that
+     * uninitialized (or removed) states are numbered with even numbers,
+     * while initialized (or re-initialized) states have odd numbers.
+     * <p>
+     * When a thread {@code T} removes a class value in state {@code 2N},
+     * nothing happens, since the class value is already uninitialized.
+     * Otherwise, the state is advanced atomically to {@code 2N+1}.
+     * <p>
+     * When a thread {@code T} queries a class value in state {@code 2N},
+     * the thread first attempts to initialize the class value to state {@code 2N+1}
+     * by invoking {@code computeValue} and installing the resulting value.
+     * <p>
+     * When {@code T} attempts to install the newly computed value,
+     * if the state is still at {@code 2N}, the class value will be initialized
+     * with the computed value, advancing it to state {@code 2N+1}.
+     * <p>
+     * Otherwise, whether the new state is even or odd,
+     * {@code T} will discard the newly computed value
+     * and retry the {@code get} operation.
+     * <p>
+     * Discarding and retrying is an important proviso,
+     * since otherwise {@code T} could potentially install
+     * a disastrously stale value.  For example:
+     * <ul>
+     * <li>{@code T} calls {@code CV.get(C)} and sees state {@code 2N}
+     * <li>{@code T} quickly computes a time-dependent value {@code V0} and gets ready to install it
+     * <li>{@code T} is hit by an unlucky paging or scheduling event, and goes to sleep for a long time
+     * <li>...meanwhile, {@code T2} also calls {@code CV.get(C)} and sees state {@code 2N}
+     * <li>{@code T2} quickly computes a similar time-dependent value {@code V1} and installs it on {@code CV.get(C)}
+     * <li>{@code T2} (or a third thread) then calls {@code CV.remove(C)}, undoing {@code T2}'s work
+     * <li> the previous actions of {@code T2} are repeated several times
+     * <li> also, the relevant computed values change over time: {@code V1}, {@code V2}, ...
+     * <li>...meanwhile, {@code T} wakes up and attempts to install {@code V0}; <em>this must fail</em>
+     * </ul>
+     * We can assume in the above scenario that {@code CV.computeValue} uses locks to properly
+     * observe the time-dependent states as it computes {@code V1}, etc.
+     * This does not remove the threat of a stale value, since there is a window of time
+     * between the return of {@code computeValue} in {@code T} and the installation
+     * of the the new value.  No user synchronization is possible during this time.
+     *
+     * @param type the type whose class value must be removed
+     * @throws NullPointerException if the argument is null
+     */
+    public void remove(Class<?> type) {
+        ClassValueMap map = getMap(type);
+        if (map != null) {
+            synchronized (map) {
+                map.remove(this);
+            }
+        }
+    }
+
+    /// Implementation...
+    // FIXME: Use a data structure here similar that of ThreadLocal (7030453).
+
+    private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
+
+    /** Slow path for {@link #get}. */
+    private T setComputedValue(Class<?> type) {
+        ClassValueMap map = getMap(type);
+        if (map == null) {
+            map = initializeMap(type);
+        }
+        T value = computeValue(type);
+        STORE_BARRIER.lazySet(0);
+        // All stores pending from computeValue are completed.
+        synchronized (map) {
+            // Warm up the table with a null entry.
+            map.preInitializeEntry(this);
+        }
+        STORE_BARRIER.lazySet(0);
+        // All stores pending from table expansion are completed.
+        synchronized (map) {
+            value = (T) map.initializeEntry(this, value);
+            // One might fear a possible race condition here
+            // if the code for map.put has flushed the write
+            // to map.table[*] before the writes to the Map.Entry
+            // are done.  This is not possible, since we have
+            // warmed up the table with an empty entry.
+        }
+        return value;
+    }
+
+    // Replace this map by a per-class slot.
+    private static final WeakHashMap<Class<?>, ClassValueMap> ROOT
+        = new WeakHashMap<Class<?>, ClassValueMap>();
+
+    private static ClassValueMap getMap(Class<?> type) {
+        return ROOT.get(type);
+    }
+
+    private static ClassValueMap initializeMap(Class<?> type) {
+        synchronized (ClassValue.class) {
+            ClassValueMap map = ROOT.get(type);
+            if (map == null)
+                ROOT.put(type, map = new ClassValueMap());
+            return map;
+        }
+    }
+
+    static class ClassValueMap extends WeakHashMap<ClassValue, Object> {
+        /** Make sure this table contains an Entry for the given key, even if it is empty. */
+        void preInitializeEntry(ClassValue key) {
+            if (!this.containsKey(key))
+                this.put(key, null);
+        }
+        /** Make sure this table contains a non-empty Entry for the given key. */
+        Object initializeEntry(ClassValue key, Object value) {
+            Object prior = this.get(key);
+            if (prior != null) {
+                return unmaskNull(prior);
+            }
+            this.put(key, maskNull(value));
+            return value;
+        }
+
+        Object maskNull(Object x) {
+            return x == null ? this : x;
+        }
+        Object unmaskNull(Object x) {
+            return x == this ? null : x;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,943 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.VerifyType;
+import sun.invoke.util.Wrapper;
+import java.util.Arrays;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * This method handle performs simple conversion or checking of a single argument.
+ * @author jrose
+ */
+class AdapterMethodHandle extends BoundMethodHandle {
+
+    //MethodHandle vmtarget;   // next AMH or BMH in chain or final DMH
+    //Object       argument;   // parameter to the conversion if needed
+    //int          vmargslot;  // which argument slot is affected
+    private final int conversion;  // the type of conversion: RETYPE_ONLY, etc.
+
+    // Constructors in this class *must* be package scoped or private.
+    private AdapterMethodHandle(MethodHandle target, MethodType newType,
+                long conv, Object convArg) {
+        super(newType, convArg, newType.parameterSlotDepth(1+convArgPos(conv)));
+        this.conversion = convCode(conv);
+        // JVM might update VM-specific bits of conversion (ignore)
+        MethodHandleNatives.init(this, target, convArgPos(conv));
+    }
+    private AdapterMethodHandle(MethodHandle target, MethodType newType,
+                long conv) {
+        this(target, newType, conv, null);
+    }
+
+    // TO DO:  When adapting another MH with a null conversion, clone
+    // the target and change its type, instead of adding another layer.
+
+    /** Can a JVM-level adapter directly implement the proposed
+     *  argument conversions, as if by MethodHandles.convertArguments?
+     */
+    static boolean canPairwiseConvert(MethodType newType, MethodType oldType) {
+        // same number of args, of course
+        int len = newType.parameterCount();
+        if (len != oldType.parameterCount())
+            return false;
+
+        // Check return type.  (Not much can be done with it.)
+        Class<?> exp = newType.returnType();
+        Class<?> ret = oldType.returnType();
+        if (!VerifyType.isNullConversion(ret, exp))
+            return false;
+
+        // Check args pairwise.
+        for (int i = 0; i < len; i++) {
+            Class<?> src = newType.parameterType(i); // source type
+            Class<?> dst = oldType.parameterType(i); // destination type
+            if (!canConvertArgument(src, dst))
+                return false;
+        }
+
+        return true;
+    }
+
+    /** Can a JVM-level adapter directly implement the proposed
+     *  argument conversion, as if by MethodHandles.convertArguments?
+     */
+    static boolean canConvertArgument(Class<?> src, Class<?> dst) {
+        // ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
+        // so we don't need to repeat so much decision making.
+        if (VerifyType.isNullConversion(src, dst)) {
+            return true;
+        } else if (src.isPrimitive()) {
+            if (dst.isPrimitive())
+                return canPrimCast(src, dst);
+            else
+                return canBoxArgument(src, dst);
+        } else {
+            if (dst.isPrimitive())
+                return canUnboxArgument(src, dst);
+            else
+                return true;  // any two refs can be interconverted
+        }
+    }
+
+    /**
+     * Create a JVM-level adapter method handle to conform the given method
+     * handle to the similar newType, using only pairwise argument conversions.
+     * For each argument, convert incoming argument to the exact type needed.
+     * Only null conversions are allowed on the return value (until
+     * the JVM supports ricochet adapters).
+     * The argument conversions allowed are casting, unboxing,
+     * integral widening or narrowing, and floating point widening or narrowing.
+     * @param newType required call type
+     * @param target original method handle
+     * @return an adapter to the original handle with the desired new type,
+     *          or the original target if the types are already identical
+     *          or null if the adaptation cannot be made
+     */
+    static MethodHandle makePairwiseConvert(MethodType newType, MethodHandle target) {
+        MethodType oldType = target.type();
+        if (newType == oldType)  return target;
+
+        if (!canPairwiseConvert(newType, oldType))
+            return null;
+        // (after this point, it is an assertion error to fail to convert)
+
+        // Find last non-trivial conversion (if any).
+        int lastConv = newType.parameterCount()-1;
+        while (lastConv >= 0) {
+            Class<?> src = newType.parameterType(lastConv); // source type
+            Class<?> dst = oldType.parameterType(lastConv); // destination type
+            if (VerifyType.isNullConversion(src, dst)) {
+                --lastConv;
+            } else {
+                break;
+            }
+        }
+        // Now build a chain of one or more adapters.
+        MethodHandle adapter = target;
+        MethodType midType = oldType.changeReturnType(newType.returnType());
+        for (int i = 0; i <= lastConv; i++) {
+            Class<?> src = newType.parameterType(i); // source type
+            Class<?> dst = midType.parameterType(i); // destination type
+            if (VerifyType.isNullConversion(src, dst)) {
+                // do nothing: difference is trivial
+                continue;
+            }
+            // Work the current type backward toward the desired caller type:
+            if (i != lastConv) {
+                midType = midType.changeParameterType(i, src);
+            } else {
+                // When doing the last (or only) real conversion,
+                // force all remaining null conversions to happen also.
+                assert(VerifyType.isNullConversion(newType, midType.changeParameterType(i, src)));
+                midType = newType;
+            }
+
+            // Tricky case analysis follows.
+            // It parallels canConvertArgument() above.
+            if (src.isPrimitive()) {
+                if (dst.isPrimitive()) {
+                    adapter = makePrimCast(midType, adapter, i, dst);
+                } else {
+                    adapter = makeBoxArgument(midType, adapter, i, dst);
+                }
+            } else {
+                if (dst.isPrimitive()) {
+                    // Caller has boxed a primitive.  Unbox it for the target.
+                    // The box type must correspond exactly to the primitive type.
+                    // This is simpler than the powerful set of widening
+                    // conversions supported by reflect.Method.invoke.
+                    // Those conversions require a big nest of if/then/else logic,
+                    // which we prefer to make a user responsibility.
+                    adapter = makeUnboxArgument(midType, adapter, i, dst);
+                } else {
+                    // Simple reference conversion.
+                    // Note:  Do not check for a class hierarchy relation
+                    // between src and dst.  In all cases a 'null' argument
+                    // will pass the cast conversion.
+                    adapter = makeCheckCast(midType, adapter, i, dst);
+                }
+            }
+            assert(adapter != null);
+            assert(adapter.type() == midType);
+        }
+        if (adapter.type() != newType) {
+            // Only trivial conversions remain.
+            adapter = makeRetypeOnly(newType, adapter);
+            assert(adapter != null);
+            // Actually, that's because there were no non-trivial ones:
+            assert(lastConv == -1);
+        }
+        assert(adapter.type() == newType);
+        return adapter;
+    }
+
+    /**
+     * Create a JVM-level adapter method handle to permute the arguments
+     * of the given method.
+     * @param newType required call type
+     * @param target original method handle
+     * @param argumentMap for each target argument, position of its source in newType
+     * @return an adapter to the original handle with the desired new type,
+     *          or the original target if the types are already identical
+     *          and the permutation is null
+     * @throws IllegalArgumentException if the adaptation cannot be made
+     *          directly by a JVM-level adapter, without help from Java code
+     */
+    static MethodHandle makePermutation(MethodType newType, MethodHandle target,
+                int[] argumentMap) {
+        MethodType oldType = target.type();
+        boolean nullPermutation = true;
+        for (int i = 0; i < argumentMap.length; i++) {
+            int pos = argumentMap[i];
+            if (pos != i)
+                nullPermutation = false;
+            if (pos < 0 || pos >= newType.parameterCount()) {
+                argumentMap = new int[0]; break;
+            }
+        }
+        if (argumentMap.length != oldType.parameterCount())
+            throw newIllegalArgumentException("bad permutation: "+Arrays.toString(argumentMap));
+        if (nullPermutation) {
+            MethodHandle res = makePairwiseConvert(newType, target);
+            // well, that was easy
+            if (res == null)
+                throw newIllegalArgumentException("cannot convert pairwise: "+newType);
+            return res;
+        }
+
+        // Check return type.  (Not much can be done with it.)
+        Class<?> exp = newType.returnType();
+        Class<?> ret = oldType.returnType();
+        if (!VerifyType.isNullConversion(ret, exp))
+            throw newIllegalArgumentException("bad return conversion for "+newType);
+
+        // See if the argument types match up.
+        for (int i = 0; i < argumentMap.length; i++) {
+            int j = argumentMap[i];
+            Class<?> src = newType.parameterType(j);
+            Class<?> dst = oldType.parameterType(i);
+            if (!VerifyType.isNullConversion(src, dst))
+                throw newIllegalArgumentException("bad argument #"+j+" conversion for "+newType);
+        }
+
+        // Now figure out a nice mix of SWAP, ROT, DUP, and DROP adapters.
+        // A workable greedy algorithm is as follows:
+        // Drop unused outgoing arguments (right to left: shallowest first).
+        // Duplicate doubly-used outgoing arguments (left to right: deepest first).
+        // Then the remaining problem is a true argument permutation.
+        // Marshal the outgoing arguments as required from left to right.
+        // That is, find the deepest outgoing stack position that does not yet
+        // have the correct argument value, and correct at least that position
+        // by swapping or rotating in the misplaced value (from a shallower place).
+        // If the misplaced value is followed by one or more consecutive values
+        // (also misplaced)  issue a rotation which brings as many as possible
+        // into position.  Otherwise make progress with either a swap or a
+        // rotation.  Prefer the swap as cheaper, but do not use it if it
+        // breaks a slot pair.  Prefer the rotation over the swap if it would
+        // preserve more consecutive values shallower than the target position.
+        // When more than one rotation will work (because the required value
+        // is already adjacent to the target position), then use a rotation
+        // which moves the old value in the target position adjacent to
+        // one of its consecutive values.  Also, prefer shorter rotation
+        // spans, since they use fewer memory cycles for shuffling.
+
+        throw new UnsupportedOperationException("NYI");
+    }
+
+    private static byte basicType(Class<?> type) {
+        if (type == null)  return T_VOID;
+        switch (Wrapper.forBasicType(type)) {
+            case BOOLEAN:  return T_BOOLEAN;
+            case CHAR:     return T_CHAR;
+            case FLOAT:    return T_FLOAT;
+            case DOUBLE:   return T_DOUBLE;
+            case BYTE:     return T_BYTE;
+            case SHORT:    return T_SHORT;
+            case INT:      return T_INT;
+            case LONG:     return T_LONG;
+            case OBJECT:   return T_OBJECT;
+            case VOID:     return T_VOID;
+        }
+        return 99; // T_ILLEGAL or some such
+    }
+
+    /** Number of stack slots for the given type.
+     *  Two for T_DOUBLE and T_FLOAT, one for the rest.
+     */
+    private static int type2size(int type) {
+        assert(type >= T_BOOLEAN && type <= T_OBJECT);
+        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. */
+    private static long makeConv(int convOp, int argnum, int src, int dest) {
+        assert(src  == (src  & 0xF));
+        assert(dest == (dest & 0xF));
+        assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF);
+        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 |
+                insertStackMove(stackMove)
+                );
+    }
+    private static long makeConv(int convOp, int argnum, int stackMove) {
+        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;
+        return ((long) argnum << 32 |
+                (long) convOp << CONV_OP_SHIFT |
+                (int)  src    << CONV_SRC_TYPE_SHIFT |
+                (int)  dest   << CONV_DEST_TYPE_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 || 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;
+    }
+    private static int convArgPos(long conv) {
+        return (int)(conv >>> 32);
+    }
+    private static boolean convOpSupported(int convOp) {
+        assert(convOp >= 0 && convOp <= CONV_OP_LIMIT);
+        return ((1<<convOp) & MethodHandleNatives.CONV_OP_IMPLEMENTED_MASK) != 0;
+    }
+
+    /** One of OP_RETYPE_ONLY, etc. */
+    int conversionOp() { return (conversion & CONV_OP_MASK) >> CONV_OP_SHIFT; }
+
+    /* 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.
+     * Trivial differences are those which could be ignored by the JVM
+     * without subverting the verifier.  Otherwise, adaptable differences
+     * are ones for which we could create an adapter to make the type change.
+     * Return zero if there are no differences (other than trivial ones).
+     * Return 1+N if N is the only adaptable argument difference.
+     * Return the -2-N where N is the first of several adaptable
+     * argument differences.
+     * Return -1 if there there are differences which are not adaptable.
+     */
+    private static int diffTypes(MethodType adapterType,
+                                 MethodType targetType,
+                                 boolean raw) {
+        int diff;
+        diff = diffReturnTypes(adapterType, targetType, raw);
+        if (diff != 0)  return diff;
+        int nargs = adapterType.parameterCount();
+        if (nargs != targetType.parameterCount())
+            return -1;
+        diff = diffParamTypes(adapterType, 0, targetType, 0, nargs, raw);
+        //System.out.println("diff "+adapterType);
+        //System.out.println("  "+diff+" "+targetType);
+        return diff;
+    }
+    private static int diffReturnTypes(MethodType adapterType,
+                                       MethodType targetType,
+                                       boolean raw) {
+        Class<?> src = targetType.returnType();
+        Class<?> dst = adapterType.returnType();
+        if ((!raw
+             ? VerifyType.canPassUnchecked(src, dst)
+             : VerifyType.canPassRaw(src, dst)
+             ) > 0)
+            return 0;  // no significant difference
+        if (raw && !src.isPrimitive() && !dst.isPrimitive())
+            return 0;  // can force a reference return (very carefully!)
+        //if (false)  return 1;  // never adaptable!
+        return -1;  // some significant difference
+    }
+    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(astart+i);
+            Class<?> dest = targetType.parameterType(tstart+i);
+            if ((!raw
+                 ? VerifyType.canPassUnchecked(src, dest)
+                 : VerifyType.canPassRaw(src, dest)
+                ) <= 0) {
+                // found a difference; is it the only one so far?
+                if (res != 0)
+                    return -1-res; // return -2-i for prev. i
+                res = 1+i;
+            }
+        }
+        return res;
+    }
+
+    /** Can a retyping adapter (alone) validly convert the target to newType? */
+    static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
+        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
+     *  conversions between float/int and double/long, and to perform unchecked
+     *  reference conversions on return.  This last feature requires that the
+     *  caller be trusted, and perform explicit cast conversions on return values.
+     */
+    static boolean canRetypeRaw(MethodType newType, MethodType targetType) {
+        return canRetype(newType, targetType, true);
+    }
+    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(raw || (diff == 0) == VerifyType.isNullConversion(newType, targetType));
+        return diff == 0;
+    }
+
+    /** Factory method:  Performs no conversions; simply retypes the adapter.
+     *  Allows unchecked argument conversions pairwise, if they are safe.
+     *  Returns null if not possible.
+     */
+    static MethodHandle makeRetypeOnly(MethodType newType, MethodHandle target) {
+        return makeRetype(newType, target, false);
+    }
+    static MethodHandle makeRetypeRaw(MethodType newType, MethodHandle target) {
+        return makeRetype(newType, target, true);
+    }
+    static MethodHandle makeRetype(MethodType newType, MethodHandle target, boolean 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(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY));
+    }
+
+    static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
+        return new AsVarargsCollector(target, arrayType);
+    }
+
+    static class AsVarargsCollector extends AdapterMethodHandle {
+        final MethodHandle target;
+        final Class<?> arrayType;
+        MethodHandle cache;
+
+        AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
+            super(target, target.type(), makeConv(OP_RETYPE_ONLY));
+            this.target = target;
+            this.arrayType = arrayType;
+            this.cache = target.asCollector(arrayType, 0);
+        }
+
+        @Override
+        public boolean isVarargsCollector() {
+            return true;
+        }
+
+        @Override
+        public MethodHandle asType(MethodType newType) {
+            MethodType type = this.type();
+            int collectArg = type.parameterCount() - 1;
+            int newArity = newType.parameterCount();
+            if (newArity == collectArg+1 &&
+                type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
+                // if arity and trailing parameter are compatible, do normal thing
+                return super.asType(newType);
+            }
+            // check cache
+            if (cache.type().parameterCount() == newArity)
+                return cache.asType(newType);
+            // build and cache a collector
+            int arrayLength = newArity - collectArg;
+            MethodHandle collector;
+            try {
+                collector = target.asCollector(arrayType, arrayLength);
+            } catch (IllegalArgumentException ex) {
+                throw new WrongMethodTypeException("cannot build collector");
+            }
+            cache = collector;
+            return collector.asType(newType);
+        }
+
+        @Override
+        public MethodHandle asVarargsCollector(Class<?> arrayType) {
+            MethodType type = this.type();
+            if (type.parameterType(type.parameterCount()-1) == arrayType)
+                return this;
+            return super.asVarargsCollector(arrayType);
+        }
+    }
+
+    /** Can a checkcast adapter validly convert the target to newType?
+     *  The JVM supports all kind of reference casts, even silly ones.
+     */
+    static boolean canCheckCast(MethodType newType, MethodType targetType,
+                int arg, Class<?> castType) {
+        if (!convOpSupported(OP_CHECK_CAST))  return false;
+        Class<?> src = newType.parameterType(arg);
+        Class<?> dst = targetType.parameterType(arg);
+        if (!canCheckCast(src, castType)
+                || !VerifyType.isNullConversion(castType, dst))
+            return false;
+        int diff = diffTypes(newType, targetType, false);
+        return (diff == arg+1);  // arg is sole non-trivial diff
+    }
+    /** Can an primitive conversion adapter validly convert src to dst? */
+    static boolean canCheckCast(Class<?> src, Class<?> dst) {
+        return (!src.isPrimitive() && !dst.isPrimitive());
+    }
+
+    /** Factory method:  Forces a cast at the given argument.
+     *  The castType is the target of the cast, and can be any type
+     *  with a null conversion to the corresponding target parameter.
+     *  Return null if this cannot be done.
+     */
+    static MethodHandle makeCheckCast(MethodType newType, MethodHandle target,
+                int arg, Class<?> castType) {
+        if (!canCheckCast(newType, target.type(), arg, castType))
+            return null;
+        long conv = makeConv(OP_CHECK_CAST, arg, T_OBJECT, T_OBJECT);
+        return new AdapterMethodHandle(target, newType, conv, castType);
+    }
+
+    /** Can an primitive conversion adapter validly convert the target to newType?
+     *  The JVM currently supports all conversions except those between
+     *  floating and integral types.
+     */
+    static boolean canPrimCast(MethodType newType, MethodType targetType,
+                int arg, Class<?> convType) {
+        if (!convOpSupported(OP_PRIM_TO_PRIM))  return false;
+        Class<?> src = newType.parameterType(arg);
+        Class<?> dst = targetType.parameterType(arg);
+        if (!canPrimCast(src, convType)
+                || !VerifyType.isNullConversion(convType, dst))
+            return false;
+        int diff = diffTypes(newType, targetType, false);
+        return (diff == arg+1);  // arg is sole non-trivial diff
+    }
+    /** Can an primitive conversion adapter validly convert src to dst? */
+    static boolean canPrimCast(Class<?> src, Class<?> dst) {
+        if (src == dst || !src.isPrimitive() || !dst.isPrimitive()) {
+            return false;
+        } else if (Wrapper.forPrimitiveType(dst).isFloating()) {
+            // both must be floating types
+            return Wrapper.forPrimitiveType(src).isFloating();
+        } else {
+            // both are integral, and all combinations work fine
+            assert(Wrapper.forPrimitiveType(src).isIntegral() &&
+                   Wrapper.forPrimitiveType(dst).isIntegral());
+            return true;
+        }
+    }
+
+    /** Factory method:  Truncate the given argument with zero or sign extension,
+     *  and/or convert between single and doubleword versions of integer or float.
+     *  The convType is the target of the conversion, and can be any type
+     *  with a null conversion to the corresponding target parameter.
+     *  Return null if this cannot be done.
+     */
+    static MethodHandle makePrimCast(MethodType newType, MethodHandle target,
+                int arg, Class<?> convType) {
+        MethodType oldType = target.type();
+        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);
+    }
+
+    /** Can an unboxing conversion validly convert src to dst?
+     *  The JVM currently supports all kinds of casting and unboxing.
+     *  The convType is the unboxed type; it can be either a primitive or wrapper.
+     */
+    static boolean canUnboxArgument(MethodType newType, MethodType targetType,
+                int arg, Class<?> convType) {
+        if (!convOpSupported(OP_REF_TO_PRIM))  return false;
+        Class<?> src = newType.parameterType(arg);
+        Class<?> dst = targetType.parameterType(arg);
+        Class<?> boxType = Wrapper.asWrapperType(convType);
+        convType = Wrapper.asPrimitiveType(convType);
+        if (!canCheckCast(src, boxType)
+                || boxType == convType
+                || !VerifyType.isNullConversion(convType, dst))
+            return false;
+        int diff = diffTypes(newType, targetType, false);
+        return (diff == arg+1);  // arg is sole non-trivial diff
+    }
+    /** Can an primitive unboxing adapter validly convert src to dst? */
+    static boolean canUnboxArgument(Class<?> src, Class<?> dst) {
+        return (!src.isPrimitive() && Wrapper.asPrimitiveType(dst).isPrimitive());
+    }
+
+    /** Factory method:  Unbox the given argument.
+     *  Return null if this cannot be done.
+     */
+    static MethodHandle makeUnboxArgument(MethodType newType, MethodHandle target,
+                int arg, Class<?> convType) {
+        MethodType oldType = target.type();
+        Class<?> src = newType.parameterType(arg);
+        Class<?> dst = oldType.parameterType(arg);
+        Class<?> boxType = Wrapper.asWrapperType(convType);
+        Class<?> primType = Wrapper.asPrimitiveType(convType);
+        if (!canUnboxArgument(newType, oldType, arg, convType))
+            return null;
+        MethodType castDone = newType;
+        if (!VerifyType.isNullConversion(src, boxType))
+            castDone = newType.changeParameterType(arg, boxType);
+        long conv = makeConv(OP_REF_TO_PRIM, arg, T_OBJECT, basicType(primType));
+        MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType);
+        if (castDone == newType)
+            return adapter;
+        return makeCheckCast(newType, adapter, arg, boxType);
+    }
+
+    /** Can an primitive boxing adapter validly convert src to dst? */
+    static boolean canBoxArgument(Class<?> src, Class<?> dst) {
+        if (!convOpSupported(OP_PRIM_TO_REF))  return false;
+        throw new UnsupportedOperationException("NYI");
+    }
+
+    /** Factory method:  Unbox the given argument.
+     *  Return null if this cannot be done.
+     */
+    static MethodHandle makeBoxArgument(MethodType newType, MethodHandle target,
+                int arg, Class<?> convType) {
+        // this is difficult to do in the JVM because it must GC
+        return null;
+    }
+
+    /** Can an adapter simply drop arguments to convert the target to newType? */
+    static boolean canDropArguments(MethodType newType, MethodType targetType,
+                int dropArgPos, int dropArgCount) {
+        if (dropArgCount == 0)
+            return canRetypeOnly(newType, targetType);
+        if (!convOpSupported(OP_DROP_ARGS))  return false;
+        if (diffReturnTypes(newType, targetType, false) != 0)
+            return false;
+        int nptypes = newType.parameterCount();
+        // parameter types must be the same up to the drop point
+        if (dropArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, dropArgPos, false) != 0)
+            return false;
+        int afterPos = dropArgPos + dropArgCount;
+        int afterCount = nptypes - afterPos;
+        if (dropArgPos < 0 || dropArgPos >= nptypes ||
+            dropArgCount < 1 || afterPos > nptypes ||
+            targetType.parameterCount() != nptypes - dropArgCount)
+            return false;
+        // parameter types after the drop point must also be the same
+        if (afterCount != 0 && diffParamTypes(newType, afterPos, targetType, dropArgPos, afterCount, false) != 0)
+            return false;
+        return true;
+    }
+
+    /** Factory method:  Drop selected arguments.
+     *  Allow unchecked retyping of remaining arguments, pairwise.
+     *  Return null if this is not possible.
+     */
+    static MethodHandle makeDropArguments(MethodType newType, MethodHandle target,
+                int dropArgPos, int dropArgCount) {
+        if (dropArgCount == 0)
+            return makeRetypeOnly(newType, target);
+        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? */
+    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.
+     */
+    static MethodHandle makeDupArguments(MethodType newType, MethodHandle target,
+                int dupArgPos, int dupArgCount) {
+        if (!canDupArguments(newType, target.type(), dupArgPos, dupArgCount))
+            return null;
+        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? */
+    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.
+     */
+    static MethodHandle makeSwapArguments(MethodType newType, MethodHandle target,
+                int swapArg1, int swapArg2) {
+        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 {
+            return (-1-((-1-rotateBy) % argCount)) + argCount;
+        }
+    }
+
+    final static int MAX_ARG_ROTATION = 1;
+
+    /** Can an adapter rotate arguments to convert the target to newType? */
+    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.
+     */
+    static MethodHandle makeRotateArguments(MethodType newType, MethodHandle target,
+                int firstArg, int argCount, int rotateBy) {
+        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? */
+    static boolean canSpreadArguments(MethodType newType, MethodType targetType,
+                Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
+        if (!convOpSupported(OP_SPREAD_ARGS))  return false;
+        if (diffReturnTypes(newType, targetType, false) != 0)
+            return false;
+        int nptypes = newType.parameterCount();
+        // parameter types must be the same up to the spread point
+        if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0)
+            return false;
+        int afterPos = spreadArgPos + spreadArgCount;
+        int afterCount = nptypes - (spreadArgPos + 1);
+        if (spreadArgPos < 0 || spreadArgPos >= nptypes ||
+            spreadArgCount < 0 ||
+            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)
+            return false;
+        // match the array element type to the spread arg types
+        Class<?> rawSpreadArgType = newType.parameterType(spreadArgPos);
+        if (rawSpreadArgType != spreadArgType && !canCheckCast(rawSpreadArgType, spreadArgType))
+            return false;
+        for (int i = 0; i < spreadArgCount; i++) {
+            Class<?> src = VerifyType.spreadArgElementType(spreadArgType, i);
+            Class<?> dst = targetType.parameterType(spreadArgPos + i);
+            if (src == null || !VerifyType.isNullConversion(src, dst))
+                return false;
+        }
+        return true;
+    }
+
+
+    /** Factory method:  Spread selected argument. */
+    static MethodHandle makeSpreadArguments(MethodType newType, MethodHandle target,
+                Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
+        MethodType targetType = target.type();
+        if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
+            return null;
+        // 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 getNameString(nonAdapter((MethodHandle)vmtarget), this);
+    }
+
+    private static MethodHandle nonAdapter(MethodHandle mh) {
+        while (mh instanceof AdapterMethodHandle) {
+            mh = (MethodHandle) mh.vmtarget;
+        }
+        return mh;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.VerifyType;
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * The flavor of method handle which emulates an invoke instruction
+ * on a predetermined argument.  The JVM dispatches to the correct method
+ * when the handle is created, not when it is invoked.
+ * @author jrose
+ */
+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
+
+    // Constructors in this class *must* be package scoped or private.
+
+    /** Bind a direct MH to its receiver (or first ref. argument).
+     *  The JVM will pre-dispatch the MH if it is not already static.
+     */
+    /*non-public*/ BoundMethodHandle(DirectMethodHandle mh, Object argument) {
+        super(mh.type().dropParameterTypes(0, 1));
+        // check the type now, once for all:
+        this.argument = checkReferenceArgument(argument, mh, 0);
+        this.vmargslot = this.type().parameterSlotCount();
+        initTarget(mh, 0);
+    }
+
+    /** Insert an argument into an arbitrary method handle.
+     *  If argnum is zero, inserts the first argument, etc.
+     *  The argument type must be a reference.
+     */
+    /*non-public*/ BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
+        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.
+     */
+    /*non-public*/ BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) {
+        super(type);
+        if (mh.type().parameterType(argnum).isPrimitive())
+            this.argument = bindPrimitiveArgument(argument, mh, argnum);
+        else {
+            this.argument = checkReferenceArgument(argument, mh, argnum);
+        }
+        this.vmargslot = type.parameterSlotDepth(argnum);
+        initTarget(mh, argnum);
+    }
+
+    private void initTarget(MethodHandle mh, int argnum) {
+        //this.vmtarget = mh;  // maybe updated by JVM
+        MethodHandleNatives.init(this, mh, argnum);
+    }
+
+    /** For the AdapterMethodHandle subclass.
+     */
+    /*non-public*/ BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
+        super(type);
+        this.argument = argument;
+        this.vmargslot = vmargslot;
+        assert(this instanceof AdapterMethodHandle);
+    }
+
+    /** Initialize the current object as a self-bound 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.
+     */
+    /*non-public*/ BoundMethodHandle(MethodHandle entryPoint) {
+        super(entryPoint.type().dropParameterTypes(0, 1));
+        this.argument = this; // kludge; get rid of
+        this.vmargslot = this.type().parameterSlotDepth(0);
+        initTarget(entryPoint, 0);
+    }
+
+    /** Make sure the given {@code argument} can be used as {@code argnum}-th
+     *  parameter of the given method handle {@code mh}, which must be a reference.
+     *  <p>
+     *  If this fails, throw a suitable {@code WrongMethodTypeException},
+     *  which will prevent the creation of an illegally typed bound
+     *  method handle.
+     */
+    final static Object checkReferenceArgument(Object argument, MethodHandle mh, int argnum) {
+        Class<?> ptype = mh.type().parameterType(argnum);
+        if (ptype.isPrimitive()) {
+            // fail
+        } else if (argument == null) {
+            return null;
+        } else if (VerifyType.isNullReferenceConversion(argument.getClass(), ptype)) {
+            return argument;
+        }
+        throw badBoundArgumentException(argument, mh, argnum);
+    }
+
+    /** Make sure the given {@code argument} can be used as {@code argnum}-th
+     *  parameter of the given method handle {@code mh}, which must be a primitive.
+     *  <p>
+     *  If this fails, throw a suitable {@code WrongMethodTypeException},
+     *  which will prevent the creation of an illegally typed bound
+     *  method handle.
+     */
+    final static Object bindPrimitiveArgument(Object argument, MethodHandle mh, int argnum) {
+        Class<?> ptype = mh.type().parameterType(argnum);
+        Wrapper  wrap = Wrapper.forPrimitiveType(ptype);
+        Object   zero  = wrap.zero();
+        if (zero == null) {
+            // fail
+        } else if (argument == null) {
+            if (ptype != int.class && wrap.isSubwordOrInt())
+                return Integer.valueOf(0);
+            else
+                return zero;
+        } else if (VerifyType.isNullReferenceConversion(argument.getClass(), zero.getClass())) {
+            if (ptype != int.class && wrap.isSubwordOrInt())
+                return Wrapper.INT.wrap(argument);
+            else
+                return argument;
+        }
+        throw badBoundArgumentException(argument, mh, argnum);
+    }
+
+    final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) {
+        String atype = (argument == null) ? "null" : argument.getClass().toString();
+        return new WrongMethodTypeException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type());
+    }
+
+    @Override
+    public String toString() {
+        return addTypeString(baseName(), this);
+    }
+
+    /** Component of toString() before the type string. */
+    protected String baseName() {
+        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 noParens(super.toString()); // "invoke", probably
+            }
+            assert(mh != this);
+        }
+        return noParens(mh.toString());
+    }
+
+    private static String noParens(String str) {
+        int paren = str.indexOf('(');
+        if (paren >= 0) str = str.substring(0, paren);
+        return str;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/CallSite.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.empty.Empty;
+import sun.misc.Unsafe;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * A {@code CallSite} is a holder for a variable {@link MethodHandle},
+ * which is called its {@code target}.
+ * An {@code invokedynamic} instruction linked to a {@code CallSite} delegates
+ * all calls to the site's current target.
+ * A {@code CallSite} may be associated with several {@code invokedynamic}
+ * instructions, or it may be "free floating", associated with none.
+ * In any case, it may be invoked through an associated method handle
+ * called its {@linkplain #dynamicInvoker dynamic invoker}.
+ * <p>
+ * {@code CallSite} is an abstract class which does not allow
+ * direct subclassing by users.  It has three immediate,
+ * concrete subclasses that may be either instantiated or subclassed.
+ * <ul>
+ * <li>If a mutable target is not required, an {@code invokedynamic} instruction
+ * may be permanently bound by means of a {@linkplain ConstantCallSite constant call site}.
+ * <li>If a mutable target is required which has volatile variable semantics,
+ * because updates to the target must be immediately and reliably witnessed by other threads,
+ * a {@linkplain VolatileCallSite volatile call site} may be used.
+ * <li>Otherwise, if a mutable target is required,
+ * a {@linkplain MutableCallSite mutable call site} may be used.
+ * </ul>
+ * <p>
+ * A non-constant call site may be <em>relinked</em> by changing its target.
+ * The new target must have the same {@linkplain MethodHandle#type() type}
+ * as the previous target.
+ * Thus, though a call site can be relinked to a series of
+ * successive targets, it cannot change its type.
+ * <p>
+ * Here is a sample use of call sites and bootstrap methods which links every
+ * dynamic call site to print its arguments:
+<blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
+static void test() throws Throwable {
+    // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
+    InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
+}
+private static void printArgs(Object... args) {
+  System.out.println(java.util.Arrays.deepToString(args));
+}
+private static final MethodHandle printArgs;
+static {
+  MethodHandles.Lookup lookup = MethodHandles.lookup();
+  Class thisClass = lookup.lookupClass();  // (who am I?)
+  printArgs = lookup.findStatic(thisClass,
+      "printArgs", MethodType.methodType(void.class, Object[].class));
+}
+private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
+  // ignore caller and name, but match the type:
+  return new ConstantCallSite(printArgs.asType(type));
+}
+</pre></blockquote>
+ * @author John Rose, JSR 292 EG
+ */
+abstract
+public class CallSite {
+    static { MethodHandleImpl.initStatics(); }
+
+    // Fields used only by the JVM.  Do not use or change.
+    private MemberName vmmethod; // supplied by the JVM (ref. to calling method)
+    private int        vmindex;  // supplied by the JVM (BCI within calling method)
+
+    // The actual payload of this call site:
+    /*package-private*/
+    MethodHandle target;
+
+    /**
+     * Make a blank call site object with the given method type.
+     * An initial target method is supplied which will throw
+     * an {@link IllegalStateException} if called.
+     * <p>
+     * Before this {@code CallSite} object is returned from a bootstrap method,
+     * it is usually provided with a more useful target method,
+     * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
+     * @throws NullPointerException if the proposed type is null
+     */
+    /*package-private*/
+    CallSite(MethodType type) {
+        target = type.invokers().uninitializedCallSite();
+    }
+
+    /**
+     * Make a blank call site object, possibly equipped with an initial target method handle.
+     * @param target the method handle which will be the initial target of the call site
+     * @throws NullPointerException if the proposed target is null
+     */
+    /*package-private*/
+    CallSite(MethodHandle target) {
+        target.type();  // null check
+        this.target = target;
+    }
+
+    /**
+     * Returns the type of this call site's target.
+     * Although targets may change, any call site's type is permanent, and can never change to an unequal type.
+     * The {@code setTarget} method enforces this invariant by refusing any new target that does
+     * not have the previous target's type.
+     * @return the type of the current target, which is also the type of any future target
+     */
+    public MethodType type() {
+        return target.type();
+    }
+
+    /** Called from JVM (or low-level Java code) after the BSM returns the newly created CallSite.
+     *  The parameters are JVM-specific.
+     */
+    void initializeFromJVM(String name,
+                           MethodType type,
+                           MemberName callerMethod,
+                           int        callerBCI) {
+        if (this.vmmethod != null) {
+            // FIXME
+            throw new BootstrapMethodError("call site has already been linked to an invokedynamic instruction");
+        }
+        if (!this.type().equals(type)) {
+            throw wrongTargetType(target, type);
+        }
+        this.vmindex  = callerBCI;
+        this.vmmethod = callerMethod;
+    }
+
+    /**
+     * Returns the target method of the call site, according to the
+     * behavior defined by this call site's specific class.
+     * The immediate subclasses of {@code CallSite} document the
+     * class-specific behaviors of this method.
+     *
+     * @return the current linkage state of the call site, its target method handle
+     * @see ConstantCallSite
+     * @see VolatileCallSite
+     * @see #setTarget
+     * @see ConstantCallSite#getTarget
+     * @see MutableCallSite#getTarget
+     * @see VolatileCallSite#getTarget
+     */
+    public abstract MethodHandle getTarget();
+
+    /**
+     * Updates the target method of this call site, according to the
+     * behavior defined by this call site's specific class.
+     * The immediate subclasses of {@code CallSite} document the
+     * class-specific behaviors of this method.
+     * <p>
+     * The type of the new target must be {@linkplain MethodType#equals equal to}
+     * the type of the old target.
+     *
+     * @param newTarget the new target
+     * @throws NullPointerException if the proposed new target is null
+     * @throws WrongMethodTypeException if the proposed new target
+     *         has a method type that differs from the previous target
+     * @see CallSite#getTarget
+     * @see ConstantCallSite#setTarget
+     * @see MutableCallSite#setTarget
+     * @see VolatileCallSite#setTarget
+     */
+    public abstract void setTarget(MethodHandle newTarget);
+
+    void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
+        MethodType oldType = oldTarget.type();
+        MethodType newType = newTarget.type();  // null check!
+        if (!newType.equals(oldType))
+            throw wrongTargetType(newTarget, oldType);
+    }
+
+    private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
+        return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type);
+    }
+
+    /**
+     * Produces a method handle equivalent to an invokedynamic instruction
+     * which has been linked to this call site.
+     * <p>
+     * This method is equivalent to the following code:
+     * <blockquote><pre>
+     * MethodHandle getTarget, invoker, result;
+     * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
+     * invoker = MethodHandles.exactInvoker(this.type());
+     * result = MethodHandles.foldArguments(invoker, getTarget)
+     * </pre></blockquote>
+     *
+     * @return a method handle which always invokes this call site's current target
+     */
+    public abstract MethodHandle dynamicInvoker();
+
+    /*non-public*/ MethodHandle makeDynamicInvoker() {
+        MethodHandle getTarget = MethodHandleImpl.bindReceiver(GET_TARGET, this);
+        MethodHandle invoker = MethodHandles.exactInvoker(this.type());
+        return MethodHandles.foldArguments(invoker, getTarget);
+    }
+
+    private static final MethodHandle GET_TARGET;
+    static {
+        try {
+            GET_TARGET = IMPL_LOOKUP.
+                findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
+        } catch (ReflectiveOperationException ignore) {
+            throw new InternalError();
+        }
+    }
+
+    /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
+    /*package-private*/
+    static Empty uninitializedCallSite() {
+        throw new IllegalStateException("uninitialized call site");
+    }
+
+    // unsafe stuff:
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final long TARGET_OFFSET;
+
+    static {
+        try {
+            TARGET_OFFSET = unsafe.objectFieldOffset(CallSite.class.getDeclaredField("target"));
+        } catch (Exception ex) { throw new Error(ex); }
+    }
+
+    /*package-private*/
+    void setTargetNormal(MethodHandle newTarget) {
+        target = newTarget;
+    }
+    /*package-private*/
+    MethodHandle getTargetVolatile() {
+        return (MethodHandle) unsafe.getObjectVolatile(this, TARGET_OFFSET);
+    }
+    /*package-private*/
+    void setTargetVolatile(MethodHandle newTarget) {
+        unsafe.putObjectVolatile(this, TARGET_OFFSET, newTarget);
+    }
+
+    // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
+    static CallSite makeSite(MethodHandle bootstrapMethod,
+                             // Callee information:
+                             String name, MethodType type,
+                             // Extra arguments for BSM, if any:
+                             Object info,
+                             // Caller information:
+                             MemberName callerMethod, int callerBCI) {
+        Class<?> callerClass = callerMethod.getDeclaringClass();
+        Object caller = IMPL_LOOKUP.in(callerClass);
+        CallSite site;
+        try {
+            Object binding;
+            info = maybeReBox(info);
+            if (info == null) {
+                binding = bootstrapMethod.invokeGeneric(caller, name, type);
+            } else if (!info.getClass().isArray()) {
+                binding = bootstrapMethod.invokeGeneric(caller, name, type, info);
+            } else {
+                Object[] argv = (Object[]) info;
+                maybeReBoxElements(argv);
+                if (3 + argv.length > 255)
+                    throw new BootstrapMethodError("too many bootstrap method arguments");
+                MethodType bsmType = bootstrapMethod.type();
+                if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class)
+                    binding = bootstrapMethod.invokeGeneric(caller, name, type, argv);
+                else
+                    binding = MethodHandles.spreadInvoker(bsmType, 3)
+                        .invokeGeneric(bootstrapMethod, caller, name, type, argv);
+            }
+            //System.out.println("BSM for "+name+type+" => "+binding);
+            if (binding instanceof CallSite) {
+                site = (CallSite) binding;
+            }  else {
+                throw new ClassCastException("bootstrap method failed to produce a CallSite");
+            }
+            assert(site.getTarget() != null);
+            assert(site.getTarget().type().equals(type));
+        } catch (Throwable ex) {
+            BootstrapMethodError bex;
+            if (ex instanceof BootstrapMethodError)
+                bex = (BootstrapMethodError) ex;
+            else
+                bex = new BootstrapMethodError("call site initialization exception", ex);
+            throw bex;
+        }
+        return site;
+    }
+
+    private static Object maybeReBox(Object x) {
+        if (x instanceof Integer) {
+            int xi = (int) x;
+            if (xi == (byte) xi)
+                x = xi;  // must rebox; see JLS 5.1.7
+        }
+        return x;
+    }
+    private static void maybeReBoxElements(Object[] xa) {
+        for (int i = 0; i < xa.length; i++) {
+            xa[i] = maybeReBox(xa[i]);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/ConstantCallSite.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
+ * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
+ * bound to the call site's target.
+ * @author John Rose, JSR 292 EG
+ */
+public class ConstantCallSite extends CallSite {
+    /**
+     * Creates a call site with a permanent target.
+     * @param target the target to be permanently associated with this call site
+     * @throws NullPointerException if the proposed target is null
+     */
+    public ConstantCallSite(MethodHandle target) {
+        super(target);
+    }
+
+    /**
+     * Returns the target method of the call site, which behaves
+     * like a {@code final} field of the {@code ConstantCallSite}.
+     * That is, the the target is always the original value passed
+     * to the constructor call which created this instance.
+     *
+     * @return the immutable linkage state of this call site, a constant method handle
+     * @throws UnsupportedOperationException because this kind of call site cannot change its target
+     */
+    @Override public final MethodHandle getTarget() {
+        return target;
+    }
+
+    /**
+     * Always throws an {@link UnsupportedOperationException}.
+     * This kind of call site cannot change its target.
+     * @param ignore a new target proposed for the call site, which is ignored
+     * @throws UnsupportedOperationException because this kind of call site cannot change its target
+     */
+    @Override public final void setTarget(MethodHandle ignore) {
+        throw new UnsupportedOperationException("ConstantCallSite");
+    }
+
+    /**
+     * Returns this call site's permanent target.
+     * Since that target will never change, this is a correct implementation
+     * of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}.
+     * @return the immutable linkage state of this call site, a constant method handle
+     */
+    @Override
+    public final MethodHandle dynamicInvoker() {
+        return getTarget();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+
+/**
+ * The flavor of method handle which emulates invokespecial or invokestatic.
+ * @author jrose
+ */
+class DirectMethodHandle extends MethodHandle {
+    //inherited oop    vmtarget;    // methodOop or virtual class/interface oop
+    private final int  vmindex;     // method index within class or interface
+    { vmindex = VM_INDEX_UNINITIALIZED; }  // JVM may change this
+
+    // Constructors in this class *must* be package scoped or private.
+    DirectMethodHandle(MethodType mtype, MemberName m, boolean doDispatch, Class<?> lookupClass) {
+        super(mtype);
+
+        assert(m.isMethod() || !doDispatch && m.isConstructor());
+        if (!m.isResolved())
+            throw new InternalError();
+
+        MethodHandleNatives.init(this, (Object) m, doDispatch, lookupClass);
+    }
+
+    boolean isValid() {
+        return (vmindex != VM_INDEX_UNINITIALIZED);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/FilterGeneric.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,4496 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.lang.reflect.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * 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 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 filtering adapters
+     *  with the given generic type
+     */
+    FilterGeneric(MethodType entryType) {
+        this.entryType = entryType;
+        int tableSize = Kind.LIMIT.invokerIndex(1 + entryType.parameterCount());
+        this.adapters = new Adapter[tableSize];
+    }
+
+    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 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 makeArgumentFolder(MethodHandle combiner, MethodHandle target) {
+        int num = combiner.type().parameterCount();
+        return make(Kind.fold, num, combiner, target);
+    }
+
+    /** 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);
+    }
+
+    /** 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);
+    }
+
+    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);
+        MethodTypeForm form = entryType.form();
+        FilterGeneric filterGen = form.filterGeneric;
+        if (filterGen == null)
+            form.filterGeneric = filterGen = new FilterGeneric(entryType);
+        return filterGen;
+    }
+
+    public String toString() {
+        return "FilterGeneric/"+entryType;
+    }
+
+    static MethodType targetType(MethodType entryType, Kind kind, int pos, MethodType filterType) {
+        MethodType type = entryType;
+        switch (kind) {
+            case value:
+            case flyby:
+                break;  // no change
+            case fold:
+                type = type.insertParameterTypes(0, filterType.returnType());
+                break;
+            case collect:
+                type = type.dropParameterTypes(pos, type.parameterCount());
+                type = type.insertParameterTypes(pos, filterType.returnType());
+                break;
+            default:
+                throw new InternalError();
+        }
+        return type;
+    }
+
+    static MethodType entryType(Kind kind, int pos, MethodType filterType, MethodType targetType) {
+        MethodType type = targetType;
+        switch (kind) {
+            case value:
+            case flyby:
+                break;  // no change
+            case fold:
+                type = type.dropParameterTypes(0, 1);
+                break;
+            case collect:
+                type = type.dropParameterTypes(pos, pos+1);
+                type = type.insertParameterTypes(pos, filterType.parameterList());
+                break;
+            default:
+                throw new InternalError();
+        }
+        return type;
+    }
+
+    /* Create an adapter that handles spreading calls for the given type. */
+    static Adapter findAdapter(MethodType entryType, Kind kind, int pos) {
+        int argc = entryType.parameterCount();
+        String cname0 = "F"+argc;
+        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;
+            // see if it has the required invoke method
+            MethodHandle entryPoint = null;
+            try {
+                entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+            } catch (ReflectiveOperationException ex) {
+            }
+            if (entryPoint == null)  continue;
+            Constructor<? extends Adapter> ctor = null;
+            try {
+                ctor = acls.getDeclaredConstructor(MethodHandle.class);
+            } catch (NoSuchMethodException ex) {
+            } catch (SecurityException ex) {
+            }
+            if (ctor == null)  continue;
+            try {
+                // Produce an instance configured as a prototype.
+                return ctor.newInstance(entryPoint);
+            } 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 entryType, Kind kind, int pos) {
+        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 BoundMethodHandle {
+        protected final MethodHandle filter; // transforms one or more arguments
+        protected final MethodHandle target; // ultimate target
+
+        @Override
+        public String toString() {
+            return addTypeString(target, this);
+        }
+
+        protected boolean isPrototype() { return target == null; }
+        protected Adapter(MethodHandle entryPoint) {
+            this(entryPoint, entryPoint, null);
+            assert(isPrototype());
+        }
+        protected MethodHandle prototypeEntryPoint() {
+            if (!isPrototype())  throw new InternalError();
+            return filter;
+        }
+
+        protected Adapter(MethodHandle entryPoint,
+                          MethodHandle filter, MethodHandle target) {
+            super(entryPoint);
+            this.filter = filter;
+            this.target = target;
+        }
+
+        /** Make a copy of self, with new fields. */
+        protected abstract Adapter makeInstance(MethodHandle entryPoint,
+                MethodHandle filter, MethodHandle target);
+        // { return new ThisType(entryPoint, filter, target); }
+
+        static private final String CLASS_PREFIX; // "java.lang.invoke.FilterGeneric$"
+        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;
+            }
+        }
+    }
+
+    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(); }
+    }
+
+    /* 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 F1X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
+                        { return new F1X(e, f, t); }
+        protected Object invoke_V0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); }
+        protected Object invoke_F0(Object a0) { return target.invokeExact(filter.invokeExact(), a0); }
+        protected Object invoke_F1(Object a0) { return target.invokeExact(filter.invokeExact(a0), a0); }
+        protected Object invoke_C0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); }
+        protected Object invoke_C1(Object a0) { return target.invokeExact(a0, filter.invokeExact()); }
+        protected Object invoke_Y0(Object a0) { Object[] av = { a0 };
+                       filter.invokeExact(av); return target.invokeExact(av[0]); }
+    }
+    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 F2X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
+                        { return new F2X(e, f, t); }
+        protected Object invoke_V0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0), a1); }
+        protected Object invoke_V1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); }
+        protected Object invoke_F0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(), a0, a1); }
+        protected Object invoke_F1(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0), a0, a1); }
+        protected Object invoke_F2(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0, a1), a0, a1); }
+        protected Object invoke_C0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0, a1)); }
+        protected Object invoke_C1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); }
+        protected Object invoke_C2(Object a0, Object a1) { return target.invokeExact(a0, a1, filter.invokeExact()); }
+        protected Object invoke_Y0(Object a0, Object a1) { Object[] av = { a0, a1 };
+                       filter.invokeExact(av); return target.invokeExact(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.invokeExact(filter.invokeExact()); }
+        protected Object invoke_C0() throws Throwable {
+            return target.invokeExact(filter.invokeExact()); }
+        static final Object[] NO_ARGS = { };
+        protected Object invoke_Y0() throws Throwable {
+            filter.invokeExact(NO_ARGS); // make the flyby
+            return target.invokeExact(); }
+    }
+
+/*
+  : 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.invokeExact(@a0_@@Psp@filter.invokeExact(a@P@)@_aN@); }",
+        "        //@end-P@",
+        "        //@each-P@",
+        "        protected Object invoke_F@P@(@Tvav@) throws Throwable {",
+        "            return target.invokeExact(filter.invokeExact(@a0@),",
+        "                                 @av@); }",
+        "        //@end-P@",
+        "        protected Object invoke_F@N@(@Tvav@) throws Throwable {",
+        "            return target.invokeExact(filter.invokeExact(@av@),",
+        "                                 @av@); }",
+        "        //@each-P@",
+        "        protected Object invoke_C@P@(@Tvav@) throws Throwable {",
+        "            return target.invokeExact(@a0_@filter.invokeExact(a@P@@_aN@)); }",
+        "        //@end-P@",
+        "        protected Object invoke_C@N@(@Tvav@) throws Throwable {",
+        "            return target.invokeExact(@av@, filter.invokeExact()); }",
+        "        protected Object invoke_Y0(@Tvav@) throws Throwable {",
+        "            Object[] av = { @av@ };",
+        "            filter.invokeExact(av); // make the flyby",
+        "            return target.invokeExact(@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.invokeExact(filter.invokeExact(a0)); }
+        protected Object invoke_F0(Object a0) throws Throwable {
+            return target.invokeExact(filter.invokeExact(),
+                                 a0); }
+        protected Object invoke_F1(Object a0) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0),
+                                 a0); }
+        protected Object invoke_C0(Object a0) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0)); }
+        protected Object invoke_C1(Object a0) throws Throwable {
+            return target.invokeExact(a0, filter.invokeExact()); }
+        protected Object invoke_Y0(Object a0) throws Throwable {
+            Object[] av = { a0 };
+            filter.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(a0), a1); }
+        protected Object invoke_V1(Object a0, Object a1) throws Throwable {
+            return target.invokeExact(a0, filter.invokeExact(a1)); }
+        protected Object invoke_F0(Object a0, Object a1) throws Throwable {
+            return target.invokeExact(filter.invokeExact(),
+                                 a0, a1); }
+        protected Object invoke_F1(Object a0, Object a1) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0),
+                                 a0, a1); }
+        protected Object invoke_F2(Object a0, Object a1) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0, a1),
+                                 a0, a1); }
+        protected Object invoke_C0(Object a0, Object a1) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0, a1)); }
+        protected Object invoke_C1(Object a0, Object a1) throws Throwable {
+            return target.invokeExact(a0, filter.invokeExact(a1)); }
+        protected Object invoke_C2(Object a0, Object a1) throws Throwable {
+            return target.invokeExact(a0, a1, filter.invokeExact()); }
+        protected Object invoke_Y0(Object a0, Object a1) throws Throwable {
+            Object[] av = { a0, a1 };
+            filter.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(a0), a1, a2); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(a0, filter.invokeExact(a1), a2); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(a0, a1, filter.invokeExact(a2)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(filter.invokeExact(),
+                                 a0, a1, a2); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0),
+                                 a0, a1, a2); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0, a1),
+                                 a0, a1, a2); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0, a1, a2),
+                                 a0, a1, a2); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0, a1, a2)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(a0, filter.invokeExact(a1, a2)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(a0, a1, filter.invokeExact(a2)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2) throws Throwable {
+            return target.invokeExact(a0, a1, a2, filter.invokeExact()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2) throws Throwable {
+            Object[] av = { a0, a1, a2 };
+            filter.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(a0), a1, a2, a3); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(a0, filter.invokeExact(a1), a2, a3); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(a0, a1, filter.invokeExact(a2), a3); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(filter.invokeExact(),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0, a1),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0, a1, a2),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+                                 a0, a1, a2, a3); }
+        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0, a1, a2, a3)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(a0, filter.invokeExact(a1, a2, a3)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(a0, a1, filter.invokeExact(a2, a3)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            Object[] av = { a0, a1, a2, a3 };
+            filter.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4); }
+        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4); }
+        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(filter.invokeExact(),
+                                 a0, a1, a2, a3, a4); }
+        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(filter.invokeExact(a0),
+                                 a0, a1, a2, a3, a4); }
+        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4)); }
+        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4)); }
+        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact()); }
+        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4) throws Throwable {
+            Object[] av = { a0, a1, a2, a3, a4 };
+            filter.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5); }
+        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5); }
+        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5); }
+        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5)); }
+        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5)); }
+        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5)); }
+        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6); }
+        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6)); }
+        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6)); }
+        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6)); }
+        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+                                   Object a4, Object a5, Object a6) throws Throwable {
+            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact(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.invokeExact(filter.invokeExact(),
+                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, filter.invokeExact()); }
+        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.invokeExact(av); // make the flyby
+            return target.invokeExact(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]); }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/FilterOneArgument.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Unary function composition, useful for many small plumbing jobs.
+ * The invoke method takes a single reference argument, and returns a reference
+ * Internally, it first calls the {@code filter} method on the argument,
+ * Making up the difference between the raw method type and the
+ * final method type is the responsibility of a JVM-level adapter.
+ * @author jrose
+ */
+class FilterOneArgument extends BoundMethodHandle {
+    protected final MethodHandle filter;  // Object -> Object
+    protected final MethodHandle target;  // Object -> Object
+
+    @Override
+    public String toString() {
+        return target.toString();
+    }
+
+    protected Object invoke(Object argument) throws Throwable {
+        Object filteredArgument = filter.invokeExact(argument);
+        return target.invokeExact(filteredArgument);
+    }
+
+    private static final MethodHandle INVOKE;
+    static {
+        try {
+            INVOKE =
+                IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
+                                        MethodType.genericMethodType(1));
+        } catch (ReflectiveOperationException ex) {
+            throw uncaughtException(ex);
+        }
+    }
+
+    protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
+        super(INVOKE);
+        this.filter = filter;
+        this.target = target;
+    }
+
+    public static MethodHandle make(MethodHandle filter, MethodHandle target) {
+        if (filter == null)  return target;
+        if (target == null)  return filter;
+        return new FilterOneArgument(filter, target);
+    }
+
+//    MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) {
+//        MethodHandle filter = make(filter1, filter2);
+//        return make(filter, target);
+//    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/FromGeneric.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
+import java.lang.reflect.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * 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
+ * only Object arguments.  A non-generic call therefore features
+ * primitives and/or reference types other than Object.
+ * An adapter has types for its incoming and outgoing calls.
+ * The incoming call type is simply determined by the adapter's type
+ * (the MethodType it presents to callers).  The outgoing call type
+ * is determined by the adapter's target (a MethodHandle that the adapter
+ * 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.)
+ * @author jrose
+ */
+class FromGeneric {
+    // type for the outgoing call (may have primitives, etc.)
+    private final MethodType targetType;
+    // type of the outgoing call internal to the adapter
+    private final MethodType internalType;
+    // prototype adapter (clone and customize for each new target!)
+    private final Adapter adapter;
+    // entry point for adapter (Adapter mh, a...) => ...
+    private final MethodHandle entryPoint;
+    // unboxing invoker of type (MH, Object**N) => raw return value
+    // it makes up the difference of internalType => targetType
+    private final MethodHandle unboxingInvoker;
+    // conversion which boxes a the target's raw return value
+    private final MethodHandle returnConversion;
+
+    /** Compute and cache information common to all unboxing adapters
+     *  that can call out to targets of the erasure-family of the given erased type.
+     */
+    private FromGeneric(MethodType targetType) {
+        this.targetType = targetType;
+        MethodType internalType0;
+        // the target invoker will generally need casts on reference arguments
+        Adapter ad = findAdapter(internalType0 = targetType.erase());
+        if (ad != null) {
+            // Immediate hit to exactly the adapter we want,
+            // with no monkeying around with primitive types.
+            this.internalType = internalType0;
+            this.adapter = ad;
+            this.entryPoint = ad.prototypeEntryPoint();
+            this.returnConversion = computeReturnConversion(targetType, internalType0);
+            this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
+            return;
+        }
+
+        // outgoing primitive arguments will be wrapped; unwrap them
+        MethodType primsAsObj = targetType.form().primArgsAsBoxes();
+        MethodType objArgsRawRet = primsAsObj.form().primsAsInts();
+        if (objArgsRawRet != targetType)
+            ad = findAdapter(internalType0 = objArgsRawRet);
+        if (ad == null) {
+            ad = buildAdapterFromBytecodes(internalType0 = targetType);
+        }
+        this.internalType = internalType0;
+        this.adapter = ad;
+        MethodType tepType = targetType.insertParameterTypes(0, adapter.getClass());
+        this.entryPoint = ad.prototypeEntryPoint();
+        this.returnConversion = computeReturnConversion(targetType, internalType0);
+        this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
+    }
+
+    /**
+     * The typed target will be called according to targetType.
+     * The adapter code will in fact see the raw result from internalType,
+     * and must box it into an object.  Produce a converter for this.
+     */
+    private static MethodHandle computeReturnConversion(
+            MethodType targetType, MethodType internalType) {
+        Class<?> tret = targetType.returnType();
+        Class<?> iret = internalType.returnType();
+        Wrapper wrap = Wrapper.forBasicType(tret);
+        if (!iret.isPrimitive()) {
+            assert(iret == Object.class);
+            return ValueConversions.identity();
+        } else if (wrap.primitiveType() == iret) {
+            return ValueConversions.box(wrap, false);
+        } else {
+            assert(tret == double.class ? iret == long.class : iret == int.class);
+            return ValueConversions.boxRaw(wrap, false);
+        }
+    }
+
+    /**
+     * The typed target will need an exact invocation point; provide it here.
+     * The adapter will possibly need to make a slightly different call,
+     * so adapt the invoker.  This way, the logic for making up the
+     * difference between what the adapter can call and what the target
+     * needs can be cached once per type.
+     */
+    private static MethodHandle computeUnboxingInvoker(
+            MethodType targetType, MethodType internalType) {
+        // All the adapters we have here have reference-untyped internal calls.
+        assert(internalType == internalType.erase());
+        MethodHandle invoker = targetType.invokers().exactInvoker();
+        // cast all narrow reference types, unbox all primitive arguments:
+        MethodType fixArgsType = internalType.changeReturnType(targetType.returnType());
+        MethodHandle fixArgs = MethodHandleImpl.convertArguments(
+                                 invoker, Invokers.invokerType(fixArgsType),
+                                 invoker.type(), null);
+        if (fixArgs == null)
+            throw new InternalError("bad fixArgs");
+        // reinterpret the calling sequence as raw:
+        MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(
+                                        Invokers.invokerType(internalType), fixArgs);
+        if (retyper == null)
+            throw new InternalError("bad retyper");
+        return retyper;
+    }
+
+    Adapter makeInstance(MethodHandle typedTarget) {
+        MethodType type = typedTarget.type();
+        if (type == targetType) {
+            return adapter.makeInstance(entryPoint, unboxingInvoker, returnConversion, typedTarget);
+        }
+        // my erased-type is not exactly the same as the desired type
+        assert(type.erase() == targetType);  // else we are busted
+        MethodHandle invoker = computeUnboxingInvoker(type, internalType);
+        return adapter.makeInstance(entryPoint, invoker, returnConversion, typedTarget);
+    }
+
+    /** 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 typedTarget) {
+        MethodType type = typedTarget.type();
+        if (type == type.generic())  return typedTarget;
+        return FromGeneric.of(type).makeInstance(typedTarget);
+    }
+
+    /** Return the adapter information for this type's erasure. */
+    static FromGeneric of(MethodType type) {
+        MethodTypeForm form = type.form();
+        FromGeneric fromGen = form.fromGeneric;
+        if (fromGen == null)
+            form.fromGeneric = fromGen = new FromGeneric(form.erasedType());
+        return fromGen;
+    }
+
+    public String toString() {
+        return "FromGeneric"+targetType;
+    }
+
+    /* Create an adapter that handles spreading calls for the given type. */
+    static Adapter findAdapter(MethodType internalType) {
+        MethodType entryType = internalType.generic();
+        MethodTypeForm form = internalType.form();
+        Class<?> rtype = internalType.returnType();
+        int argc = form.parameterCount();
+        int lac = form.longPrimitiveParameterCount();
+        int iac = form.primitiveParameterCount() - lac;
+        String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
+        String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
+        String cname0 = rawReturn + argc;
+        String cname1 = "A"       + argc;
+        String[] cnames = { cname0+intsAndLongs, cname0, cname1+intsAndLongs, cname1 };
+        String iname = "invoke_"+cname0+intsAndLongs;
+        // 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 = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+            } catch (ReflectiveOperationException ex) {
+            }
+            if (entryPoint == null)  continue;
+            Constructor<? extends Adapter> ctor = null;
+            try {
+                ctor = acls.getDeclaredConstructor(MethodHandle.class);
+            } catch (NoSuchMethodException ex) {
+            } catch (SecurityException ex) {
+            }
+            if (ctor == null)  continue;
+            try {
+                // Produce an instance configured as a prototype.
+                return ctor.newInstance(entryPoint);
+            } 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 internalType) {
+        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 BoundMethodHandle {
+        /*
+         * class X<<R,int N>> extends Adapter {
+         *   (MH, Object**N)=>raw(R) invoker;
+         *   (any**N)=>R target;
+         *   raw(R)=>Object convert;
+         *   Object invoke(Object**N a) = convert(invoker(target, a...))
+         * }
+         */
+        protected final MethodHandle invoker;  // (MH, Object**N) => raw(R)
+        protected final MethodHandle convert;  // raw(R) => Object
+        protected final MethodHandle target;   // (any**N) => R
+
+        @Override
+        public String toString() {
+            return addTypeString(target, this);
+        }
+
+        protected boolean isPrototype() { return target == null; }
+        protected Adapter(MethodHandle entryPoint) {
+            this(entryPoint, null, entryPoint, null);
+            assert(isPrototype());
+        }
+        protected MethodHandle prototypeEntryPoint() {
+            if (!isPrototype())  throw new InternalError();
+            return convert;
+        }
+
+        protected Adapter(MethodHandle entryPoint,
+                          MethodHandle invoker, MethodHandle convert, MethodHandle target) {
+            super(entryPoint);
+            this.invoker = invoker;
+            this.convert = convert;
+            this.target  = target;
+        }
+
+        /** Make a copy of self, with new fields. */
+        protected abstract Adapter makeInstance(MethodHandle entryPoint,
+                MethodHandle invoker, MethodHandle convert, MethodHandle target);
+        // { return new ThisType(entryPoint, convert, target); }
+
+        /// Conversions on the value returned from the target.
+        protected Object convert_L(Object result) throws Throwable { return convert.invokeExact(result); }
+        protected Object convert_I(int    result) throws Throwable { return convert.invokeExact(result); }
+        protected Object convert_J(long   result) throws Throwable { return convert.invokeExact(result); }
+        protected Object convert_F(float  result) throws Throwable { return convert.invokeExact(result); }
+        protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); }
+
+        static private final String CLASS_PREFIX; // "java.lang.invoke.FromGeneric$"
+        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 xA2 extends Adapter {
+        protected xA2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
+        protected xA2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+                        { 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) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
+        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1)); }
+        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1)); }
+        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
+        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
+    }
+    // */
+
+/*
+: SHELL; n=FromGeneric; 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[] TYPES = { "Object",    "int   ",    "long  ",    "float ",    "double" };
+    static String[] WRAPS = { "         ", "(Integer)", "(Long)   ", "(Float)  ", "(Double) " };
+    static String[] TCHARS = { "L",     "I",      "J",      "F",      "D",     "A" };
+    static String[][] TEMPLATES = { {
+        "@for@ arity=0..10  rcat<=4 nrefs<=99 nints=0   nlongs=0",
+        "    //@each-cat@",
+        "    static class @cat@ extends Adapter {",
+        "        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); }",
+        "        //@each-R@",
+        "        protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@((@R@)@W@invoker.invokeExact(target@av@)); }",
+        "        //@end-R@",
+        "    }",
+    } };
+    static final String NEWLINE_INDENT = "\n                ";
+    enum VAR {
+        cat, catN, R, Rc, W, av, Tvav, Ovav;
+        public final String pattern = "@"+toString().replace('_','.')+"@";
+        public String binding;
+        static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
+            int nargs = nrefs + nints + nlongs;
+            if (topLevel)
+                VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
+            VAR.catN.binding = catstr(rcat, nrefs, nints, nlongs);
+            VAR.R.binding = TYPES[rcat];
+            VAR.Rc.binding = TCHARS[rcat];
+            VAR.W.binding = WRAPS[rcat];
+            String[] Tv = new String[nargs];
+            String[] av = new String[nargs];
+            String[] Tvav = new String[nargs];
+            String[] Ovav = new String[nargs];
+            for (int i = 0; i < nargs; i++) {
+                int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
+                Tv[i] = TYPES[tcat];
+                av[i] = arg(i);
+                Tvav[i] = param(Tv[i], av[i]);
+                Ovav[i] = param("Object", av[i]);
+            }
+            VAR.av.binding = comma(", ", av);
+            VAR.Tvav.binding = comma(Tvav);
+            VAR.Ovav.binding = comma(Ovav);
+        }
+        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 sep, String[] v) {
+            if (v.length == 0)  return "";
+            String res = sep+v[0];
+            for (int i = 1; i < v.length; i++)  res += ", "+v[i];
+            return res;
+        }
+        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, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
+    static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
+    static HashSet<String> done = new HashSet<String>();
+    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++]);
+        MAX_RCAT  = Integer.valueOf(params[pcur++]);
+        MAX_REFS  = Integer.valueOf(params[pcur++]);
+        MAX_INTS  = Integer.valueOf(params[pcur++]);
+        MAX_LONGS = Integer.valueOf(params[pcur++]);
+        if (pcur != params.length)  throw new RuntimeException("bad extra param: "+forLine);
+        if (MAX_RCAT >= TYPES.length)  MAX_RCAT = TYPES.length - 1;
+        ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
+        ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
+        for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
+            for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
+                expandTemplate(template, true, rcat, nargs, 0, 0);
+                if (ALL_ARG_TYPES)  break;
+                expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
+                if (ALL_RETURN_TYPES)  break;
+            }
+        }
+    }
+    static String catstr(int rcat, int nrefs, int nints, int nlongs) {
+        int nargs = nrefs + nints + nlongs;
+        String cat = TCHARS[rcat] + nargs;
+        if (!ALL_ARG_TYPES)  cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
+        return cat;
+    }
+    static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
+        for (int isLong = 0; isLong <= 1; isLong++) {
+            for (int nprims = 1; nprims <= nargs; nprims++) {
+                int nrefs = nargs - nprims;
+                int nints = ((1-isLong) * nprims);
+                int nlongs = (isLong * nprims);
+                expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
+            }
+        }
+    }
+    static void expandTemplate(String[] template, boolean topLevel,
+                               int rcat, int nrefs, int nints, int nlongs) {
+        int nargs = nrefs + nints + nlongs;
+        if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS)  return;
+        VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+        if (topLevel && !done.add(VAR.cat.binding)) {
+            System.out.println("    //repeat "+VAR.cat.binding);
+            return;
+        }
+        for (int i = 0; i < template.length; i++) {
+            String line = template[i];
+            if (line.endsWith("@each-cat@")) {
+                // ignore
+            } else if (line.endsWith("@each-R@")) {
+                int blockEnd = indexAfter(template, i, "@end-R@");
+                String[] block = stringsIn(template, i+1, blockEnd-1);
+                for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
+                    expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
+                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+                i = blockEnd-1; continue;
+            } else if (line.endsWith("@each-Tv@")) {
+                int blockEnd = indexAfter(template, i, "@end-Tv@");
+                String[] block = stringsIn(template, i+1, blockEnd-1);
+                expandTemplate(block, false, rcat, nrefs, nints, nlongs);
+                expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
+                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+                i = blockEnd-1; continue;
+            } else {
+                System.out.println(VAR.transform(line));
+            }
+        }
+    }
+}
+//}}} */
+//params=[0, 10, 4, 99, 0, 0]
+    static class A0 extends Adapter {
+        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 invoke_L0() throws Throwable { return convert_L((Object)invoker.invokeExact(target)); }
+        protected Object invoke_I0() throws Throwable { return convert_I((int)   invoker.invokeExact(target)); }
+        protected Object invoke_J0() throws Throwable { return convert_J((long)  invoker.invokeExact(target)); }
+        protected Object invoke_F0() throws Throwable { return convert_F((float) invoker.invokeExact(target)); }
+        protected Object invoke_D0() throws Throwable { return convert_D((double)invoker.invokeExact(target)); }
+    }
+    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 invoke_L1(Object a0) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0)); }
+        protected Object invoke_I1(Object a0) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0)); }
+        protected Object invoke_J1(Object a0) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0)); }
+        protected Object invoke_F1(Object a0) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0)); }
+        protected Object invoke_D1(Object a0) throws Throwable { return convert_D((double)invoker.invokeExact(target, 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 invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
+        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1)); }
+        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1)); }
+        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
+        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, 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 invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2)); }
+        protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2)); }
+        protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2)); }
+        protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2)); }
+        protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2)); }
+    }
+    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 invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3)); }
+        protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3)); }
+        protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3)); }
+        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3)); }
+        protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D((double)invoker.invokeExact(target, 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 invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
+    }
+    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 invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, 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 invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, 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 invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, 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 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((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, 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 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((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/InvokeDynamic.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * This is a place-holder class.  Some HotSpot implementations need to see it.
+ */
+final class InvokeDynamic {
+    private InvokeDynamic() { throw new InternalError(); }  // do not instantiate
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/InvokeGeneric.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Adapters which manage MethodHandle.invokeGeneric calls.
+ * The JVM calls one of these when the exact type match fails.
+ * @author jrose
+ */
+class InvokeGeneric {
+    // erased type for the call, which originates from an invokeGeneric site
+    private final MethodType erasedCallerType;
+    // an invoker of type (MT, MH; A...) -> R
+    private final MethodHandle initialInvoker;
+
+    /** Compute and cache information for this adapter, so that it can
+     *  call out to targets of the erasure-family of the given erased type.
+     */
+    /*non-public*/ InvokeGeneric(MethodType erasedCallerType) throws ReflectiveOperationException {
+        assert(erasedCallerType.equals(erasedCallerType.erase()));
+        this.erasedCallerType = erasedCallerType;
+        this.initialInvoker = makeInitialInvoker();
+        assert initialInvoker.type().equals(erasedCallerType
+                                            .insertParameterTypes(0, MethodType.class, MethodHandle.class))
+            : initialInvoker.type();
+    }
+
+    private static MethodHandles.Lookup lookup() {
+        return IMPL_LOOKUP;
+    }
+
+    /** Return the adapter information for this type's erasure. */
+    /*non-public*/ static MethodHandle genericInvokerOf(MethodType erasedCallerType) throws ReflectiveOperationException {
+        InvokeGeneric gen = new InvokeGeneric(erasedCallerType);
+        return gen.initialInvoker;
+    }
+
+    private MethodHandle makeInitialInvoker() throws ReflectiveOperationException {
+        // postDispatch = #(MH'; MT, MH; A...){MH'(MT, MH; A)}
+        MethodHandle postDispatch = makePostDispatchInvoker();
+        MethodHandle invoker;
+        if (returnConversionPossible()) {
+            invoker = MethodHandles.foldArguments(postDispatch,
+                                                  dispatcher("dispatchWithConversion"));
+        } else {
+            invoker = MethodHandles.foldArguments(postDispatch, dispatcher("dispatch"));
+        }
+        return invoker;
+    }
+
+    private static final Class<?>[] EXTRA_ARGS = { MethodType.class, MethodHandle.class };
+    private MethodHandle makePostDispatchInvoker() {
+        // Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...).
+        MethodType invokerType = erasedCallerType.insertParameterTypes(0, EXTRA_ARGS);
+        return invokerType.invokers().exactInvoker();
+    }
+    private MethodHandle dropDispatchArguments(MethodHandle targetInvoker) {
+        assert(targetInvoker.type().parameterType(0) == MethodHandle.class);
+        return MethodHandles.dropArguments(targetInvoker, 1, EXTRA_ARGS);
+    }
+
+    private MethodHandle dispatcher(String dispatchName) throws ReflectiveOperationException {
+        return lookup().bind(this, dispatchName,
+                             MethodType.methodType(MethodHandle.class,
+                                                   MethodType.class, MethodHandle.class));
+    }
+
+    static final boolean USE_AS_TYPE_PATH = true;
+
+    /** Return a method handle to invoke on the callerType, target, and remaining arguments.
+     *  The method handle must finish the call.
+     *  This is the first look at the caller type and target.
+     */
+    private MethodHandle dispatch(MethodType callerType, MethodHandle target) {
+        MethodType targetType = target.type();
+        if (USE_AS_TYPE_PATH || target.isVarargsCollector()) {
+            MethodHandle newTarget = target.asType(callerType);
+            targetType = callerType;
+            Invokers invokers = targetType.invokers();
+            MethodHandle invoker = invokers.erasedInvokerWithDrops;
+            if (invoker == null) {
+                invokers.erasedInvokerWithDrops = invoker =
+                    dropDispatchArguments(invokers.erasedInvoker());
+            }
+            return invoker.bindTo(newTarget);
+        }
+        throw new RuntimeException("NYI");
+    }
+
+    private MethodHandle dispatchWithConversion(MethodType callerType, MethodHandle target) {
+        MethodHandle finisher = dispatch(callerType, target);
+        if (returnConversionNeeded(callerType, target))
+            finisher = addReturnConversion(finisher, callerType.returnType());  //FIXME: slow
+        return finisher;
+    }
+
+    private boolean returnConversionPossible() {
+        Class<?> needType = erasedCallerType.returnType();
+        return !needType.isPrimitive();
+    }
+    private boolean returnConversionNeeded(MethodType callerType, MethodHandle target) {
+        Class<?> needType = callerType.returnType();
+        if (needType == erasedCallerType.returnType())
+            return false;  // no conversions possible, since must be primitive or Object
+        Class<?> haveType = target.type().returnType();
+        if (VerifyType.isNullConversion(haveType, needType))
+            return false;
+        return true;
+    }
+    private MethodHandle addReturnConversion(MethodHandle target, Class<?> type) {
+        if (true) throw new RuntimeException("NYI");
+        // FIXME: This is slow because it creates a closure node on every call that requires a return cast.
+        MethodType targetType = target.type();
+        MethodHandle caster = ValueConversions.identity(type);
+        caster = caster.asType(MethodType.methodType(type, targetType.returnType()));
+        // Drop irrelevant arguments, because we only care about the return value:
+        caster = MethodHandles.dropArguments(caster, 1, targetType.parameterList());
+        MethodHandle result = MethodHandles.foldArguments(caster, target);
+        return result.asType(target.type());
+    }
+
+    public String toString() {
+        return "InvokeGeneric"+erasedCallerType;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/Invokers.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.empty.Empty;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Construction and caching of often-used invokers.
+ * @author jrose
+ */
+class Invokers {
+    // exact type (sans leading taget MH) for the outgoing call
+    private final MethodType targetType;
+
+    // exact invoker for the outgoing call
+    private /*lazy*/ MethodHandle exactInvoker;
+
+    // erased (partially untyped but with primitives) invoker for the outgoing call
+    private /*lazy*/ MethodHandle erasedInvoker;
+    /*lazy*/ MethodHandle erasedInvokerWithDrops;  // for InvokeGeneric
+
+    // 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[] spreadInvokers;
+
+    // invoker for an unbound callsite
+    private /*lazy*/ MethodHandle uninitializedCallSite;
+
+    /** Compute and cache information common to all collecting adapters
+     *  that implement members of the erasure-family of the given erased type.
+     */
+    /*non-public*/ Invokers(MethodType targetType) {
+        this.targetType = targetType;
+        this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
+    }
+
+    /*non-public*/ static MethodType invokerType(MethodType targetType) {
+        return targetType.insertParameterTypes(0, MethodHandle.class);
+    }
+
+    /*non-public*/ MethodHandle exactInvoker() {
+        MethodHandle invoker = exactInvoker;
+        if (invoker != null)  return invoker;
+        try {
+            invoker = IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType);
+        } catch (ReflectiveOperationException ex) {
+            throw new InternalError("JVM cannot find invoker for "+targetType);
+        }
+        assert(invokerType(targetType) == invoker.type());
+        exactInvoker = invoker;
+        return invoker;
+    }
+
+    /*non-public*/ MethodHandle genericInvoker() {
+        MethodHandle invoker1 = exactInvoker();
+        MethodHandle invoker = genericInvoker;
+        if (invoker != null)  return invoker;
+        MethodType genericType = targetType.generic();
+        invoker = MethodHandles.convertArguments(invoker1, invokerType(genericType));
+        genericInvoker = invoker;
+        return invoker;
+    }
+
+    /*non-public*/ MethodHandle erasedInvoker() {
+        MethodHandle invoker1 = exactInvoker();
+        MethodHandle invoker = erasedInvoker;
+        if (invoker != null)  return invoker;
+        MethodType erasedType = targetType.erase();
+        if (erasedType == targetType.generic())
+            invoker = genericInvoker();
+        else
+            invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType));
+        erasedInvoker = invoker;
+        return invoker;
+    }
+
+    /*non-public*/ MethodHandle spreadInvoker(int objectArgCount) {
+        MethodHandle vaInvoker = spreadInvokers[objectArgCount];
+        if (vaInvoker != null)  return vaInvoker;
+        MethodHandle gInvoker = genericInvoker();
+        vaInvoker = gInvoker.asSpreader(Object[].class, targetType.parameterCount() - objectArgCount);
+        spreadInvokers[objectArgCount] = vaInvoker;
+        return vaInvoker;
+    }
+
+    private static MethodHandle THROW_UCS = null;
+
+    /*non-public*/ MethodHandle uninitializedCallSite() {
+        MethodHandle invoker = uninitializedCallSite;
+        if (invoker != null)  return invoker;
+        if (targetType.parameterCount() > 0) {
+            MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
+            Invokers invokers0 = type0.invokers();
+            invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
+                                                  0, targetType.parameterList());
+            assert(invoker.type().equals(targetType));
+            uninitializedCallSite = invoker;
+            return invoker;
+        }
+        if (THROW_UCS == null) {
+            try {
+                THROW_UCS = IMPL_LOOKUP
+                    .findStatic(CallSite.class, "uninitializedCallSite",
+                                MethodType.methodType(Empty.class));
+            } catch (ReflectiveOperationException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+        invoker = AdapterMethodHandle.makeRetypeRaw(targetType, THROW_UCS);
+        assert(invoker.type().equals(targetType));
+        uninitializedCallSite = invoker;
+        return invoker;
+    }
+
+    public String toString() {
+        return "Invokers"+targetType;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,718 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.BytecodeDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+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;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * A {@code MemberName} is a compact symbolic datum which fully characterizes
+ * a method or field reference.
+ * A member name refers to a field, method, constructor, or member type.
+ * Every member name has a simple name (a string) and a type (either a Class or MethodType).
+ * A member name may also have a non-null declaring class, or it may be simply
+ * a naked name/type pair.
+ * A member name may also have non-zero modifier flags.
+ * Finally, a member name may be either resolved or unresolved.
+ * If it is resolved, the existence of the named
+ * <p>
+ * Whether resolved or not, a member name provides no access rights or
+ * invocation capability to its possessor.  It is merely a compact
+ * representation of all symbolic information necessary to link to
+ * and properly use the named member.
+ * <p>
+ * When resolved, a member name's internal implementation may include references to JVM metadata.
+ * This representation is stateless and only decriptive.
+ * It provides no private information and no capability to use the member.
+ * <p>
+ * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
+ * about the internals of a method (except its bytecodes) and also
+ * allows invocation.  A MemberName is much lighter than a Method,
+ * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
+ * and those seven fields omit much of the information in Method.
+ * @author jrose
+ */
+/*non-public*/ final class MemberName implements Member, Cloneable {
+    private Class<?>   clazz;       // class in which the method is defined
+    private String     name;        // may be null if not yet materialized
+    private Object     type;        // may be null if not yet materialized
+    private int        flags;       // modifier bits; see reflect.Modifier
+
+    private Object     vmtarget;    // VM-specific target value
+    private int        vmindex;     // method index within class or interface
+
+    { vmindex = VM_INDEX_UNINITIALIZED; }
+
+    /** Return the declaring class of this member.
+     *  In the case of a bare name and type, the declaring class will be null.
+     */
+    public Class<?> getDeclaringClass() {
+        if (clazz == null && isResolved()) {
+            expandFromVM();
+        }
+        return clazz;
+    }
+
+    /** Utility method producing the class loader of the declaring class. */
+    public ClassLoader getClassLoader() {
+        return clazz.getClassLoader();
+    }
+
+    /** Return the simple name of this member.
+     *  For a type, it is the same as {@link Class#getSimpleName}.
+     *  For a method or field, it is the simple name of the member.
+     *  For a constructor, it is always {@code "&lt;init&gt;"}.
+     */
+    public String getName() {
+        if (name == null) {
+            expandFromVM();
+            if (name == null)  return null;
+        }
+        return name;
+    }
+
+    /** Return the declared type of this member, which
+     *  must be a method or constructor.
+     */
+    public MethodType getMethodType() {
+        if (type == null) {
+            expandFromVM();
+            if (type == null)  return null;
+        }
+        if (!isInvocable())
+            throw newIllegalArgumentException("not invocable, no method type");
+        if (type instanceof MethodType) {
+            return (MethodType) type;
+        }
+        if (type instanceof String) {
+            String sig = (String) type;
+            MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
+            this.type = res;
+            return res;
+        }
+        if (type instanceof Object[]) {
+            Object[] typeInfo = (Object[]) type;
+            Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
+            Class<?> rtype = (Class<?>) typeInfo[0];
+            MethodType res = MethodType.methodType(rtype, ptypes);
+            this.type = res;
+            return res;
+        }
+        throw new InternalError("bad method type "+type);
+    }
+
+    /** Return the actual type under which this method or constructor must be invoked.
+     *  For non-static methods or constructors, this is the type with a leading parameter,
+     *  a reference to declaring class.  For static methods, it is the same as the declared type.
+     */
+    public MethodType getInvocationType() {
+        MethodType itype = getMethodType();
+        if (!isStatic())
+            itype = itype.insertParameterTypes(0, clazz);
+        return itype;
+    }
+
+    /** Utility method producing the parameter types of the method type. */
+    public Class<?>[] getParameterTypes() {
+        return getMethodType().parameterArray();
+    }
+
+    /** Utility method producing the return type of the method type. */
+    public Class<?> getReturnType() {
+        return getMethodType().returnType();
+    }
+
+    /** Return the declared type of this member, which
+     *  must be a field or type.
+     *  If it is a type member, that type itself is returned.
+     */
+    public Class<?> getFieldType() {
+        if (type == null) {
+            expandFromVM();
+            if (type == null)  return null;
+        }
+        if (isInvocable())
+            throw newIllegalArgumentException("not a field or nested class, no simple type");
+        if (type instanceof Class<?>) {
+            return (Class<?>) type;
+        }
+        if (type instanceof String) {
+            String sig = (String) type;
+            MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
+            Class<?> res = mtype.returnType();
+            this.type = res;
+            return res;
+        }
+        throw new InternalError("bad field type "+type);
+    }
+
+    /** Utility method to produce either the method type or field type of this member. */
+    public Object getType() {
+        return (isInvocable() ? getMethodType() : getFieldType());
+    }
+
+    /** Utility method to produce the signature of this member,
+     *  used within the class file format to describe its type.
+     */
+    public String getSignature() {
+        if (type == null) {
+            expandFromVM();
+            if (type == null)  return null;
+        }
+        if (type instanceof String)
+            return (String) type;
+        if (isInvocable())
+            return BytecodeDescriptor.unparse(getMethodType());
+        else
+            return BytecodeDescriptor.unparse(getFieldType());
+    }
+
+    /** Return the modifier flags of this member.
+     *  @see java.lang.reflect.Modifier
+     */
+    public int getModifiers() {
+        return (flags & RECOGNIZED_MODIFIERS);
+    }
+
+    private void setFlags(int flags) {
+        this.flags = flags;
+        assert(testAnyFlags(ALL_KINDS));
+    }
+
+    private boolean testFlags(int mask, int value) {
+        return (flags & mask) == value;
+    }
+    private boolean testAllFlags(int mask) {
+        return testFlags(mask, mask);
+    }
+    private boolean testAnyFlags(int mask) {
+        return !testFlags(mask, 0);
+    }
+
+    /** Utility method to query the modifier flags of this member. */
+    public boolean isStatic() {
+        return Modifier.isStatic(flags);
+    }
+    /** Utility method to query the modifier flags of this member. */
+    public boolean isPublic() {
+        return Modifier.isPublic(flags);
+    }
+    /** Utility method to query the modifier flags of this member. */
+    public boolean isPrivate() {
+        return Modifier.isPrivate(flags);
+    }
+    /** Utility method to query the modifier flags of this member. */
+    public boolean isProtected() {
+        return Modifier.isProtected(flags);
+    }
+    /** Utility method to query the modifier flags of this member. */
+    public boolean isFinal() {
+        return Modifier.isFinal(flags);
+    }
+    /** Utility method to query the modifier flags of this member. */
+    public boolean isAbstract() {
+        return Modifier.isAbstract(flags);
+    }
+    // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
+
+    // unofficial modifier flags, used by HotSpot:
+    static final int BRIDGE    = 0x00000040;
+    static final int VARARGS   = 0x00000080;
+    static final int SYNTHETIC = 0x00001000;
+    static final int ANNOTATION= 0x00002000;
+    static final int ENUM      = 0x00004000;
+    /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
+    public boolean isBridge() {
+        return testAllFlags(IS_METHOD | BRIDGE);
+    }
+    /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
+    public boolean isVarargs() {
+        return testAllFlags(VARARGS) && isInvocable();
+    }
+    /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
+    public boolean isSynthetic() {
+        return testAllFlags(SYNTHETIC);
+    }
+
+    static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
+
+    // modifiers exported by the JVM:
+    static final int RECOGNIZED_MODIFIERS = 0xFFFF;
+
+    // private flags, not part of RECOGNIZED_MODIFIERS:
+    static final int
+            IS_METHOD      = MN_IS_METHOD,      // method (not constructor)
+            IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
+            IS_FIELD       = MN_IS_FIELD,       // field
+            IS_TYPE        = MN_IS_TYPE;        // nested type
+    static final int  // for MethodHandleNatives.getMembers
+            SEARCH_SUPERCLASSES = MN_SEARCH_SUPERCLASSES,
+            SEARCH_INTERFACES   = MN_SEARCH_INTERFACES;
+
+    static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
+    static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
+    static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
+    static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
+    static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES;
+
+    /** Utility method to query whether this member is a method or constructor. */
+    public boolean isInvocable() {
+        return testAnyFlags(IS_INVOCABLE);
+    }
+    /** Utility method to query whether this member is a method, constructor, or field. */
+    public boolean isFieldOrMethod() {
+        return testAnyFlags(IS_FIELD_OR_METHOD);
+    }
+    /** Query whether this member is a method. */
+    public boolean isMethod() {
+        return testAllFlags(IS_METHOD);
+    }
+    /** Query whether this member is a constructor. */
+    public boolean isConstructor() {
+        return testAllFlags(IS_CONSTRUCTOR);
+    }
+    /** Query whether this member is a field. */
+    public boolean isField() {
+        return testAllFlags(IS_FIELD);
+    }
+    /** Query whether this member is a type. */
+    public boolean isType() {
+        return testAllFlags(IS_TYPE);
+    }
+    /** Utility method to query whether this member is neither public, private, nor protected. */
+    public boolean isPackage() {
+        return !testAnyFlags(ALL_ACCESS);
+    }
+
+    /** Initialize a query.   It is not resolved. */
+    private void init(Class<?> defClass, String name, Object type, int flags) {
+        // defining class is allowed to be null (for a naked name/type pair)
+        //name.toString();  // null check
+        //type.equals(type);  // null check
+        // fill in fields:
+        this.clazz = defClass;
+        this.name = name;
+        this.type = type;
+        setFlags(flags);
+        assert(!isResolved());
+    }
+
+    private void expandFromVM() {
+        if (!isResolved())  return;
+        if (type instanceof Object[])
+            type = null;  // don't saddle JVM w/ typeInfo
+        MethodHandleNatives.expand(this);
+    }
+
+    // Capturing information from the Core Reflection API:
+    private static int flagsMods(int flags, int mods) {
+        assert((flags & RECOGNIZED_MODIFIERS) == 0);
+        assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
+        return flags | mods;
+    }
+    /** Create a name for the given reflected method.  The resulting name will be in a resolved state. */
+    public MemberName(Method m) {
+        Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() };
+        init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers()));
+        // fill in vmtarget, vmindex while we have m in hand:
+        MethodHandleNatives.init(this, m);
+        assert(isResolved());
+    }
+    /** Create a name for the given reflected constructor.  The resulting name will be in a resolved state. */
+    public MemberName(Constructor ctor) {
+        Object[] typeInfo = { void.class, ctor.getParameterTypes() };
+        init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
+        // fill in vmtarget, vmindex while we have ctor in hand:
+        MethodHandleNatives.init(this, ctor);
+        assert(isResolved());
+    }
+    /** Create a name for the given reflected field.  The resulting name will be in a resolved state. */
+    public MemberName(Field fld) {
+        init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers()));
+        // fill in vmtarget, vmindex while we have fld in hand:
+        MethodHandleNatives.init(this, fld);
+        assert(isResolved());
+    }
+    /** Create a name for the given class.  The resulting name will be in a resolved state. */
+    public MemberName(Class<?> type) {
+        init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers()));
+        vmindex = 0;  // isResolved
+        assert(isResolved());
+    }
+
+    // bare-bones constructor; the JVM will fill it in
+    MemberName() { }
+
+    // locally useful cloner
+    @Override protected MemberName clone() {
+        try {
+            return (MemberName) super.clone();
+        } catch (CloneNotSupportedException ex) {
+            throw new InternalError();
+        }
+     }
+
+    // %%% define equals/hashcode?
+
+    // Construction from symbolic parts, for queries:
+    /** Create a field or type name from the given components:  Declaring class, name, type, modifiers.
+     *  The declaring class may be supplied as null if this is to be a bare name and type.
+     *  The resulting name will in an unresolved state.
+     */
+    public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) {
+        init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS));
+    }
+    /** Create a field or type name from the given components:  Declaring class, name, type.
+     *  The declaring class may be supplied as null if this is to be a bare name and type.
+     *  The modifier flags default to zero.
+     *  The resulting name will in an unresolved state.
+     */
+    public MemberName(Class<?> defClass, String name, Class<?> type) {
+        this(defClass, name, type, 0);
+    }
+    /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
+     *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
+     *  The declaring class may be supplied as null if this is to be a bare name and type.
+     *  The resulting name will in an unresolved state.
+     */
+    public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) {
+        int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
+        init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS));
+    }
+    /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
+     *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
+     *  The declaring class may be supplied as null if this is to be a bare name and type.
+     *  The modifier flags default to zero.
+     *  The resulting name will in an unresolved state.
+     */
+    public MemberName(Class<?> defClass, String name, MethodType type) {
+        this(defClass, name, type, 0);
+    }
+
+    /** Query whether this member name is resolved.
+     *  A resolved member name is one for which the JVM has found
+     *  a method, constructor, field, or type binding corresponding exactly to the name.
+     *  (Document?)
+     */
+    public boolean isResolved() {
+        return (vmindex != VM_INDEX_UNINITIALIZED);
+    }
+
+    /** Query whether this member name is resolved to a non-static, non-final method.
+     */
+    public boolean hasReceiverTypeDispatch() {
+        return (isMethod() && getVMIndex() >= 0);
+    }
+
+    /** Produce a string form of this member name.
+     *  For types, it is simply the type's own string (as reported by {@code toString}).
+     *  For fields, it is {@code "DeclaringClass.name/type"}.
+     *  For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
+     *  If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
+     *  If the member is unresolved, a prefix {@code "*."} is prepended.
+     */
+    @Override
+    public String toString() {
+        if (isType())
+            return type.toString();  // class java.lang.String
+        // else it is a field, method, or constructor
+        StringBuilder buf = new StringBuilder();
+        if (getDeclaringClass() != null) {
+            buf.append(getName(clazz));
+            buf.append('.');
+        }
+        String name = getName();
+        buf.append(name == null ? "*" : name);
+        Object type = getType();
+        if (!isInvocable()) {
+            buf.append('/');
+            buf.append(type == null ? "*" : getName(type));
+        } else {
+            buf.append(type == null ? "(*)*" : getName(type));
+        }
+        /*
+        buf.append('/');
+        // key: Public, private, pRotected, sTatic, Final, sYnchronized,
+        // transient/Varargs, native, (interface), abstract, sTrict, sYnthetic,
+        // (annotation), Enum, (unused)
+        final String FIELD_MOD_CHARS  = "PprTF?vt????Y?E?";
+        final String METHOD_MOD_CHARS = "PprTFybVn?atY???";
+        String modChars = (isInvocable() ? METHOD_MOD_CHARS : FIELD_MOD_CHARS);
+        for (int i = 0; i < modChars.length(); i++) {
+            if ((flags & (1 << i)) != 0) {
+                char mc = modChars.charAt(i);
+                if (mc != '?')
+                    buf.append(mc);
+            }
+        }
+         */
+        return buf.toString();
+    }
+    private static String getName(Object obj) {
+        if (obj instanceof Class<?>)
+            return ((Class<?>)obj).getName();
+        return String.valueOf(obj);
+    }
+
+    // Queries to the JVM:
+    /** Document? */
+    /*non-public*/ int getVMIndex() {
+        if (!isResolved())
+            throw newIllegalStateException("not resolved", this);
+        return vmindex;
+    }
+//    /*non-public*/ Object getVMTarget() {
+//        if (!isResolved())
+//            throw newIllegalStateException("not resolved", this);
+//        return vmtarget;
+//    }
+
+    public IllegalAccessException makeAccessException(String message, Object from) {
+        message = message + ": "+ toString();
+        if (from != null)  message += ", from " + from;
+        return new IllegalAccessException(message);
+    }
+    public ReflectiveOperationException makeAccessException(String message) {
+        message = message + ": "+ toString();
+        if (isResolved())
+            return new IllegalAccessException(message);
+        else if (isConstructor())
+            return new NoSuchMethodException(message);
+        else if (isMethod())
+            return new NoSuchMethodException(message);
+        else
+            return new NoSuchFieldException(message);
+    }
+
+    /** Actually making a query requires an access check. */
+    /*non-public*/ static Factory getFactory() {
+        return Factory.INSTANCE;
+    }
+    /** A factory type for resolving member names with the help of the VM.
+     *  TBD: Define access-safe public constructors for this factory.
+     */
+    public static class Factory {
+        private Factory() { } // singleton pattern
+        static Factory INSTANCE = new Factory();
+
+        private static int ALLOWED_FLAGS = SEARCH_ALL_SUPERS | ALL_KINDS;
+
+        /// Queries
+        List<MemberName> getMembers(Class<?> defc,
+                String matchName, Object matchType,
+                int matchFlags, Class<?> lookupClass) {
+            matchFlags &= ALLOWED_FLAGS;
+            String matchSig = null;
+            if (matchType != null) {
+                matchSig = BytecodeDescriptor.unparse(matchType);
+                if (matchSig.startsWith("("))
+                    matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
+                else
+                    matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
+            }
+            final int BUF_MAX = 0x2000;
+            int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
+            MemberName[] buf = newMemberBuffer(len1);
+            int totalCount = 0;
+            ArrayList<MemberName[]> bufs = null;
+            int bufCount = 0;
+            for (;;) {
+                bufCount = MethodHandleNatives.getMembers(defc,
+                        matchName, matchSig, matchFlags,
+                        lookupClass,
+                        totalCount, buf);
+                if (bufCount <= buf.length) {
+                    if (bufCount < 0)  bufCount = 0;
+                    totalCount += bufCount;
+                    break;
+                }
+                // JVM returned to us with an intentional overflow!
+                totalCount += buf.length;
+                int excess = bufCount - buf.length;
+                if (bufs == null)  bufs = new ArrayList<MemberName[]>(1);
+                bufs.add(buf);
+                int len2 = buf.length;
+                len2 = Math.max(len2, excess);
+                len2 = Math.max(len2, totalCount / 4);
+                buf = newMemberBuffer(Math.min(BUF_MAX, len2));
+            }
+            ArrayList<MemberName> result = new ArrayList<MemberName>(totalCount);
+            if (bufs != null) {
+                for (MemberName[] buf0 : bufs) {
+                    Collections.addAll(result, buf0);
+                }
+            }
+            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.
+            if (matchType != null && matchType != matchSig) {
+                for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
+                    MemberName m = it.next();
+                    if (!matchType.equals(m.getType()))
+                        it.remove();
+                }
+            }
+            return result;
+        }
+        boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
+            if (m.name == null || m.type == null) {  // find unique non-overloaded name
+                Class<?> defc = m.getDeclaringClass();
+                List<MemberName> choices = null;
+                if (m.isMethod())
+                    choices = getMethods(defc, searchSupers, m.name, (MethodType) m.type, lookupClass);
+                else if (m.isConstructor())
+                    choices = getConstructors(defc, lookupClass);
+                else if (m.isField())
+                    choices = getFields(defc, searchSupers, m.name, (Class<?>) m.type, lookupClass);
+                //System.out.println("resolving "+m+" to "+choices);
+                if (choices == null || choices.size() != 1)
+                    return false;
+                if (m.name == null)  m.name = choices.get(0).name;
+                if (m.type == null)  m.type = choices.get(0).type;
+            }
+            MethodHandleNatives.resolve(m, lookupClass);
+            if (m.isResolved())  return true;
+            int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
+            String matchSig = m.getSignature();
+            MemberName[] buf = { m };
+            int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
+                    m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
+            if (n != 1)  return false;
+            return m.isResolved();
+        }
+        /** Produce a resolved version of the given member.
+         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
+         *  Access checking is performed on behalf of the given {@code lookupClass}.
+         *  If lookup fails or access is not permitted, null is returned.
+         *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
+         */
+        public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) {
+            MemberName result = m.clone();
+            if (resolveInPlace(result, searchSupers, lookupClass))
+                return result;
+            return null;
+        }
+        /** Produce a resolved version of the given member.
+         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
+         *  Access checking is performed on behalf of the given {@code lookupClass}.
+         *  If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
+         *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
+         */
+        public
+        <NoSuchMemberException extends ReflectiveOperationException>
+        MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass,
+                                 Class<NoSuchMemberException> nsmClass)
+                throws IllegalAccessException, NoSuchMemberException {
+            MemberName result = resolveOrNull(m, searchSupers, lookupClass);
+            if (result != null)
+                return result;
+            ReflectiveOperationException ex = m.makeAccessException("no access");
+            if (ex instanceof IllegalAccessException)  throw (IllegalAccessException) ex;
+            throw nsmClass.cast(ex);
+        }
+        /** Return a list of all methods defined by the given class.
+         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
+         *  Access checking is performed on behalf of the given {@code lookupClass}.
+         *  Inaccessible members are not added to the last.
+         */
+        public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
+                Class<?> lookupClass) {
+            return getMethods(defc, searchSupers, null, null, lookupClass);
+        }
+        /** Return a list of matching methods defined by the given class.
+         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
+         *  Returned methods will match the name (if not null) and the type (if not null).
+         *  Access checking is performed on behalf of the given {@code lookupClass}.
+         *  Inaccessible members are not added to the last.
+         */
+        public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
+                String name, MethodType type, Class<?> lookupClass) {
+            int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
+            return getMembers(defc, name, type, matchFlags, lookupClass);
+        }
+        /** Return a list of all constructors defined by the given class.
+         *  Access checking is performed on behalf of the given {@code lookupClass}.
+         *  Inaccessible members are not added to the last.
+         */
+        public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
+            return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
+        }
+        /** Return a list of all fields defined by the given class.
+         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
+         *  Access checking is performed on behalf of the given {@code lookupClass}.
+         *  Inaccessible members are not added to the last.
+         */
+        public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
+                Class<?> lookupClass) {
+            return getFields(defc, searchSupers, null, null, lookupClass);
+        }
+        /** Return a list of all fields defined by the given class.
+         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
+         *  Returned fields will match the name (if not null) and the type (if not null).
+         *  Access checking is performed on behalf of the given {@code lookupClass}.
+         *  Inaccessible members are not added to the last.
+         */
+        public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
+                String name, Class<?> type, Class<?> lookupClass) {
+            int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
+            return getMembers(defc, name, type, matchFlags, lookupClass);
+        }
+        /** Return a list of all nested types defined by the given class.
+         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
+         *  Access checking is performed on behalf of the given {@code lookupClass}.
+         *  Inaccessible members are not added to the last.
+         */
+        public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
+                Class<?> lookupClass) {
+            int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
+            return getMembers(defc, null, null, matchFlags, lookupClass);
+        }
+        private static MemberName[] newMemberBuffer(int length) {
+            MemberName[] buf = new MemberName[length];
+            // fill the buffer with dummy structs for the JVM to fill in
+            for (int i = 0; i < length; i++)
+                buf[i] = new MemberName();
+            return buf;
+        }
+    }
+
+//    static {
+//        System.out.println("Hello world!  My methods are:");
+//        System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
+//    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,1028 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * A method handle is a typed, directly executable reference to an underlying method,
+ * constructor, field, or similar low-level operation, with optional
+ * transformations of arguments or return values.
+ * These transformations are quite general, and include such patterns as
+ * {@linkplain #asType conversion},
+ * {@linkplain #bindTo insertion},
+ * {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
+ * and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
+ *
+ * <h3>Method handle contents</h3>
+ * Method handles are dynamically and strongly typed according to type descriptor.
+ * They are not distinguished by the name or defining class of their underlying methods.
+ * A method handle must be invoked using type descriptor which matches
+ * the method handle's own {@linkplain #type method type}.
+ * <p>
+ * Every method handle reports its type via the {@link #type type} accessor.
+ * This type descriptor is a {@link java.lang.invoke.MethodType MethodType} object,
+ * whose structure is a series of classes, one of which is
+ * the return type of the method (or {@code void.class} if none).
+ * <p>
+ * A method handle's type controls the types of invocations it accepts,
+ * and the kinds of transformations that apply to it.
+ * <p>
+ * A method handle contains a pair of special invoker methods
+ * called {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}.
+ * Both invoker methods provide direct access to the method handle's
+ * underlying method, constructor, field, or other operation,
+ * as modified by transformations of arguments and return values.
+ * Both invokers accept calls which exactly match the method handle's own type.
+ * The {@code invokeGeneric} invoker also accepts a range of other call types.
+ * <p>
+ * Method handles are immutable and have no visible state.
+ * Of course, they can be bound to underlying methods or data which exhibit state.
+ * With respect to the Java Memory Model, any method handle will behave
+ * as if all of its (internal) fields are final variables.  This means that any method
+ * handle made visible to the application will always be fully formed.
+ * This is true even if the method handle is published through a shared
+ * variable in a data race.
+ * <p>
+ * Method handles cannot be subclassed by the user.
+ * Implementations may (or may not) create internal subclasses of {@code MethodHandle}
+ * which may be visible via the {@link java.lang.Object#getClass Object.getClass}
+ * operation.  The programmer should not draw conclusions about a method handle
+ * from its specific class, as the method handle class hierarchy (if any)
+ * may change from time to time or across implementations from different vendors.
+ *
+ * <h3>Method handle compilation</h3>
+ * A Java method call expression naming {@code invokeExact} or {@code invokeGeneric}
+ * can invoke a method handle from Java source code.
+ * From the viewpoint of source code, these methods can take any arguments
+ * and their result can be cast to any return type.
+ * Formally this is accomplished by giving the invoker methods
+ * {@code Object} return types and variable-arity {@code Object} arguments,
+ * but they have an additional quality called <em>signature polymorphism</em>
+ * which connects this freedom of invocation directly to the JVM execution stack.
+ * <p>
+ * As is usual with virtual methods, source-level calls to {@code invokeExact}
+ * and {@code invokeGeneric} compile to an {@code invokevirtual} instruction.
+ * More unusually, the compiler must record the actual argument types,
+ * and may not perform method invocation conversions on the arguments.
+ * Instead, it must push them on the stack according to their own unconverted types.
+ * The method handle object itself is pushed on the stack before the arguments.
+ * The compiler then calls the method handle with a type descriptor which
+ * describes the argument and return types.
+ * <p>
+ * To issue a complete type descriptor, the compiler must also determine
+ * the return type.  This is based on a cast on the method invocation expression,
+ * if there is one, or else {@code Object} if the invocation is an expression
+ * or else {@code void} if the invocation is a statement.
+ * The cast may be to a primitive type (but not {@code void}).
+ * <p>
+ * As a corner case, an uncasted {@code null} argument is given
+ * a type descriptor of {@code java.lang.Void}.
+ * The ambiguity with the type {@code Void} is harmless, since there are no references of type
+ * {@code Void} except the null reference.
+ *
+ * <h3>Method handle invocation</h3>
+ * The first time a {@code invokevirtual} instruction is executed
+ * it is linked, by symbolically resolving the names in the instruction
+ * and verifying that the method call is statically legal.
+ * This is true of calls to {@code invokeExact} and {@code invokeGeneric}.
+ * In this case, the type descriptor emitted by the compiler is checked for
+ * correct syntax and names it contains are resolved.
+ * Thus, an {@code invokevirtual} instruction which invokes
+ * a method handle will always link, as long
+ * as the type descriptor is syntactically well-formed
+ * and the types exist.
+ * <p>
+ * When the {@code invokevirtual} is executed after linking,
+ * the receiving method handle's type is first checked by the JVM
+ * to ensure that it matches the descriptor.
+ * If the type match fails, it means that the method which the
+ * caller is invoking is not present on the individual
+ * method handle being invoked.
+ * <p>
+ * In the case of {@code invokeExact}, the type descriptor of the invocation
+ * (after resolving symbolic type names) must exactly match the method type
+ * of the receiving method handle.
+ * In the case of {@code invokeGeneric}, the resolved type descriptor
+ * must be a valid argument to the receiver's {@link #asType asType} method.
+ * Thus, {@code invokeGeneric} is more permissive than {@code invokeExact}.
+ * <p>
+ * After type matching, a call to {@code invokeExact} directly
+ * and immediately invoke the method handle's underlying method
+ * (or other behavior, as the case may be).
+ * <p>
+ * A call to {@code invokeGeneric} works the same as a call to
+ * {@code invokeExact}, if the type descriptor specified by the caller
+ * exactly matches the method handle's own type.
+ * If there is a type mismatch, {@code invokeGeneric} attempts
+ * to adjust the type of the receiving method handle,
+ * as if by a call to {@link #asType asType},
+ * to obtain an exactly invokable method handle {@code M2}.
+ * This allows a more powerful negotiation of method type
+ * between caller and callee.
+ * <p>
+ * (<em>Note:</em> The adjusted method handle {@code M2} is not directly observable,
+ * and implementations are therefore not required to materialize it.)
+ *
+ * <h3>Invocation checking</h3>
+ * In typical programs, method handle type matching will usually succeed.
+ * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
+ * either directly (in the case of {@code invokeExact}) or indirectly as if
+ * by a failed call to {@code asType} (in the case of {@code invokeGeneric}).
+ * <p>
+ * Thus, a method type mismatch which might show up as a linkage error
+ * in a statically typed program can show up as
+ * a dynamic {@code WrongMethodTypeException}
+ * in a program which uses method handles.
+ * <p>
+ * Because method types contain "live" {@code Class} objects,
+ * method type matching takes into account both types names and class loaders.
+ * Thus, even if a method handle {@code M} is created in one
+ * class loader {@code L1} and used in another {@code L2},
+ * method handle calls are type-safe, because the caller's type
+ * descriptor, as resolved in {@code L2},
+ * is matched against the original callee method's type descriptor,
+ * as resolved in {@code L1}.
+ * The resolution in {@code L1} happens when {@code M} is created
+ * and its type is assigned, while the resolution in {@code L2} happens
+ * when the {@code invokevirtual} instruction is linked.
+ * <p>
+ * Apart from the checking of type descriptors,
+ * a method handle's capability to call its underlying method is unrestricted.
+ * If a method handle is formed on a non-public method by a class
+ * that has access to that method, the resulting handle can be used
+ * in any place by any caller who receives a reference to it.
+ * <p>
+ * Unlike with the Core Reflection API, where access is checked every time
+ * a reflective method is invoked,
+ * method handle access checking is performed
+ * <a href="MethodHandles.Lookup.html#access">when the method handle is created</a>.
+ * In the case of {@code ldc} (see below), access checking is performed as part of linking
+ * the constant pool entry underlying the constant method handle.
+ * <p>
+ * Thus, handles to non-public methods, or to methods in non-public classes,
+ * should generally be kept secret.
+ * They should not be passed to untrusted code unless their use from
+ * the untrusted code would be harmless.
+ *
+ * <h3>Method handle creation</h3>
+ * Java code can create a method handle that directly accesses
+ * any method, constructor, or field that is accessible to that code.
+ * This is done via a reflective, capability-based API called
+ * {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
+ * For example, a static method handle can be obtained
+ * from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
+ * There are also conversion methods from Core Reflection API objects,
+ * such as {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
+ * <p>
+ * Like classes and strings, method handles that correspond to accessible
+ * fields, methods, and constructors can also be represented directly
+ * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
+ * A new type of constant pool entry, {@code CONSTANT_MethodHandle},
+ * refers directly to an associated {@code CONSTANT_Methodref},
+ * {@code CONSTANT_InterfaceMethodref}, or {@code CONSTANT_Fieldref}
+ * constant pool entry.
+ * (For more details on method handle constants,
+ * see the <a href="package-summary.html#mhcon">package summary</a>.)
+ * <p>
+ * Method handles produced by lookups or constant loads from methods or
+ * constructors with the variable arity modifier bit ({@code 0x0080})
+ * have a corresponding variable arity, as if they were defined with
+ * the help of {@link #asVarargsCollector asVarargsCollector}.
+ * <p>
+ * A method reference may refer either to a static or non-static method.
+ * In the non-static case, the method handle type includes an explicit
+ * receiver argument, prepended before any other arguments.
+ * In the method handle's type, the initial receiver argument is typed
+ * according to the class under which the method was initially requested.
+ * (E.g., if a non-static method handle is obtained via {@code ldc},
+ * the type of the receiver is the class named in the constant pool entry.)
+ * <p>
+ * When a method handle to a virtual method is invoked, the method is
+ * always looked up in the receiver (that is, the first argument).
+ * <p>
+ * A non-virtual method handle to a specific virtual method implementation
+ * 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} instruction to the same method.
+ *
+ * <h3>Usage examples</h3>
+ * 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)String
+mt = MethodType.methodType(String.class, char.class, char.class);
+mh = lookup.findVirtual(String.class, "replace", mt);
+s = (String) mh.invokeExact("daddy",'d','n');
+// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
+assert(s.equals("nanny"));
+// weakly typed invocation (using MHs.invoke)
+s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
+assert(s.equals("savvy"));
+// mt is (Object[])List
+mt = MethodType.methodType(java.util.List.class, Object[].class);
+mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
+assert(mh.isVarargsCollector());
+x = mh.invokeGeneric("one", "two");
+// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
+assert(x.equals(java.util.Arrays.asList("one","two")));
+// mt is (Object,Object,Object)Object
+mt = MethodType.genericMethodType(3);
+mh = mh.asType(mt);
+x = mh.invokeExact((Object)1, (Object)2, (Object)3);
+// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+assert(x.equals(java.util.Arrays.asList(1,2,3)));
+// mt is int()
+mt = MethodType.methodType(int.class);
+mh = lookup.findVirtual(java.util.List.class, "size", mt);
+i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
+// invokeExact(Ljava/util/List;)I
+assert(i == 3);
+mt = MethodType.methodType(void.class, String.class);
+mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
+mh.invokeExact(System.out, "Hello, world.");
+// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
+ * </pre></blockquote>
+ * Each of the above calls to {@code invokeExact} or {@code invokeGeneric}
+ * generates a single invokevirtual instruction with
+ * the type descriptor indicated in the following comment.
+ *
+ * <h3>Exceptions</h3>
+ * The methods {@code invokeExact} and {@code invokeGeneric} are declared
+ * to throw {@link java.lang.Throwable Throwable},
+ * 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 java.lang.Throwable Throwable}, or else must catch all
+ * throwables locally, rethrowing only those which are legal in the context,
+ * and wrapping ones which are illegal.
+ *
+ * <h3><a name="sigpoly"></a>Signature polymorphism</h3>
+ * The unusual compilation and linkage behavior of
+ * {@code invokeExact} and {@code invokeGeneric}
+ * is referenced by the term <em>signature polymorphism</em>.
+ * A signature polymorphic method is one which can operate with
+ * any of a wide range of call signatures and return types.
+ * In order to make this work, both the Java compiler and the JVM must
+ * give special treatment to signature polymorphic methods.
+ * <p>
+ * In source code, a call to a signature polymorphic method will
+ * compile, regardless of the requested type descriptor.
+ * As usual, the Java compiler emits an {@code invokevirtual}
+ * instruction with the given type descriptor against the named method.
+ * The unusual part is that the type descriptor is derived from
+ * the actual argument and return types, not from the method declaration.
+ * <p>
+ * When the JVM processes bytecode containing signature polymorphic calls,
+ * it will successfully link any such call, regardless of its type descriptor.
+ * (In order to retain type safety, the JVM will guard such calls with suitable
+ * dynamic type checks, as described elsewhere.)
+ * <p>
+ * Bytecode generators, including the compiler back end, are required to emit
+ * untransformed type descriptors for these methods.
+ * Tools which determine symbolic linkage are required to accept such
+ * untransformed descriptors, without reporting linkage errors.
+ * <p>
+ * For the sake of tools (but not as a programming API), the signature polymorphic
+ * methods are marked with a private yet standard annotation,
+ * {@code @java.lang.invoke.MethodHandle.PolymorphicSignature}.
+ * The annotation's retention is {@code RUNTIME}, so that all tools can see it.
+ *
+ * <h3>Formal rules for processing signature polymorphic methods</h3>
+ * <p>
+ * The following methods (and no others) are signature polymorphic:
+ * <ul>
+ * <li>{@link java.lang.invoke.MethodHandle#invokeExact   MethodHandle.invokeExact}
+ * <li>{@link java.lang.invoke.MethodHandle#invokeGeneric MethodHandle.invokeGeneric}
+ * </ul>
+ * <p>
+ * A signature polymorphic method will be declared with the following properties:
+ * <ul>
+ * <li>It must be native.
+ * <li>It must take a single varargs parameter of the form {@code Object...}.
+ * <li>It must produce a return value of type {@code Object}.
+ * <li>It must be contained within the {@code java.lang.invoke} package.
+ * </ul>
+ * Because of these requirements, a signature polymorphic method is able to accept
+ * any number and type of actual arguments, and can, with a cast, produce a value of any type.
+ * However, the JVM will treat these declaration features as a documentation convention,
+ * rather than a description of the actual structure of the methods as executed.
+ * <p>
+ * When a call to a signature polymorphic method is compiled, the associated linkage information for
+ * its arguments is not array of {@code Object} (as for other similar varargs methods)
+ * but rather the erasure of the static types of all the arguments.
+ * <p>
+ * In an argument position of a method invocation on a signature polymorphic method,
+ * a null literal has type {@code java.lang.Void}, unless cast to a reference type.
+ * (<em>Note:</em> This typing rule allows the null type to have its own encoding in linkage information
+ * distinct from other types.
+ * <p>
+ * The linkage information for the return type is derived from a context-dependent target typing convention.
+ * The return type for a signature polymorphic method invocation is determined as follows:
+ * <ul>
+ * <li>If the method invocation expression is an expression statement, the method is {@code void}.
+ * <li>Otherwise, if the method invocation expression is the immediate operand of a cast,
+ * the return type is the erasure of the cast type.
+ * <li>Otherwise, the return type is the method's nominal return type, {@code Object}.
+ * </ul>
+ * (Programmers are encouraged to use explicit casts unless it is clear that a signature polymorphic
+ * call will be used as a plain {@code Object} expression.)
+ * <p>
+ * The linkage information for argument and return types is stored in the descriptor for the
+ * compiled (bytecode) call site. As for any invocation instruction, the arguments and return value
+ * will be passed directly on the JVM stack, in accordance with the descriptor,
+ * and without implicit boxing or unboxing.
+ *
+ * <h3>Interoperation between method handles and the Core Reflection API</h3>
+ * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
+ * any class member represented by a Core Reflection API object
+ * can be converted to a behaviorally equivalent method handle.
+ * For example, a reflective {@link java.lang.reflect.Method Method} can
+ * be converted to a method handle using
+ * {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
+ * The resulting method handles generally provide more direct and efficient
+ * access to the underlying class members.
+ * <p>
+ * As a special case,
+ * when the Core Reflection API is used to view the signature polymorphic
+ * methods {@code invokeExact} or {@code invokeGeneric} in this class,
+ * they appear as single, non-polymorphic native methods.
+ * Calls to these native methods do not result in method handle invocations.
+ * Since {@code invokevirtual} instructions can natively
+ * invoke method handles under any type descriptor, this reflective view conflicts
+ * with the normal presentation via bytecodes.
+ * Thus, these two native methods, as viewed by
+ * {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod},
+ * are placeholders only.
+ * If invoked via {@link java.lang.reflect.Method#invoke Method.invoke},
+ * they will throw {@code UnsupportedOperationException}.
+ * <p>
+ * In order to obtain an invoker method for a particular type descriptor,
+ * use {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker},
+ * or {@link java.lang.invoke.MethodHandles#genericInvoker MethodHandles.genericInvoker}.
+ * The {@link java.lang.invoke.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
+ * API is also able to return a method handle
+ * to call {@code invokeExact} or {@code invokeGeneric},
+ * for any specified type descriptor .
+ *
+ * <h3>Interoperation between method handles and Java generics</h3>
+ * A method handle can be obtained on a method, constructor, or field
+ * which is declared with Java generic types.
+ * As with the Core Reflection API, the type of the method handle
+ * will constructed from the erasure of the source-level type.
+ * When a method handle is invoked, the types of its arguments
+ * or the return value cast type may be generic types or type instances.
+ * If this occurs, the compiler will replace those
+ * types by their erasures when when it constructs the type descriptor
+ * for the {@code invokevirtual} instruction.
+ * <p>
+ * Method handles do not represent
+ * their function-like types in terms of Java parameterized (generic) types,
+ * because there are three mismatches between function-like types and parameterized
+ * Java types.
+ * <ul>
+ * <li>Method types range over all possible arities,
+ * from no arguments to up to 255 of arguments (a limit imposed by the JVM).
+ * 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>
+ * </ul>
+ *
+ * @see MethodType
+ * @see MethodHandles
+ * @author John Rose, JSR 292 EG
+ */
+public abstract class MethodHandle {
+    // { JVM internals:
+
+    private byte       vmentry;    // adapter stub or method entry point
+    //private int      vmslots;    // optionally, hoist type.form.vmslots
+    /*non-public*/ Object vmtarget;   // VM-specific, class-specific target value
+
+    // TO DO:  vmtarget should be invisible to Java, since the JVM puts internal
+    // managed pointers into it.  Making it visible exposes it to debuggers,
+    // which can cause errors when they treat the pointer as an Object.
+
+    // These two dummy fields are present to force 'I' and 'J' signatures
+    // into this class's constant pool, so they can be transferred
+    // to vmentry when this class is loaded.
+    static final int  INT_FIELD = 0;
+    static final long LONG_FIELD = 0;
+
+    // vmentry (a void* field) is used *only* by the JVM.
+    // The JVM adjusts its type to int or long depending on system wordsize.
+    // Since it is statically typed as neither int nor long, it is impossible
+    // to use this field from Java bytecode.  (Please don't try to, either.)
+
+    // The vmentry is an assembly-language stub which is jumped to
+    // immediately after the method type is verified.
+    // For a direct MH, this stub loads the vmtarget's entry point
+    // and jumps to it.
+
+    // } End of JVM internals.
+
+    static { MethodHandleImpl.initStatics(); }
+
+    // interface MethodHandle<R throws X extends Exception,A...>
+    // { MethodType<R throws X,A...> type(); public R invokeExact(A...) throws X; }
+
+    /**
+     * Internal marker interface which distinguishes (to the Java compiler)
+     * those methods which are <a href="MethodHandle.html#sigpoly">signature polymorphic</a>.
+     */
+    @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
+    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
+    @interface PolymorphicSignature { }
+
+    private MethodType type;
+
+    /**
+     * Reports the type of this method handle.
+     * Every invocation of this method handle via {@code invokeExact} must exactly match this type.
+     * @return the method handle type
+     */
+    public MethodType type() {
+        return type;
+    }
+
+    /**
+     * Package-private constructor for the method handle implementation hierarchy.
+     * Method handle inheritance will be contained completely within
+     * the {@code java.lang.invoke} package.
+     */
+    // @param type type (permanently assigned) of the new method handle
+    /*non-public*/ MethodHandle(MethodType type) {
+        type.getClass();  // elicit NPE
+        this.type = type;
+    }
+
+    /**
+     * Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match.
+     * The type descriptor at the call site of {@code invokeExact} must
+     * exactly match this method handle's {@link #type type}.
+     * No conversions are allowed on arguments or return values.
+     * <p>
+     * When this method is observed via the Core Reflection API,
+     * it will appear as a single native method, taking an object array and returning an object.
+     * If this native method is invoked directly via
+     * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
+     * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
+     * it will throw an {@code UnsupportedOperationException}.
+     * @throws WrongMethodTypeException if the target's type is not identical with the caller's type descriptor
+     * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
+     */
+    public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
+
+    /**
+     * Invokes the method handle, allowing any caller type descriptor,
+     * and optionally performing conversions on arguments and return values.
+     * <p>
+     * If the call site type descriptor exactly matches this method handle's {@link #type type},
+     * the call proceeds as if by {@link #invokeExact invokeExact}.
+     * <p>
+     * Otherwise, the call proceeds as if this method handle were first
+     * adjusted by calling {@link #asType asType} to adjust this method handle
+     * to the required type, and then the call proceeds as if by
+     * {@link #invokeExact invokeExact} on the adjusted method handle.
+     * <p>
+     * There is no guarantee that the {@code asType} call is actually made.
+     * If the JVM can predict the results of making the call, it may perform
+     * adaptations directly on the caller's arguments,
+     * and call the target method handle according to its own exact type.
+     * <p>
+     * The type descriptor at the call site of {@code invokeGeneric} must
+     * be a valid argument to the receivers {@code asType} method.
+     * In particular, the caller must specify the same argument arity
+     * as the callee's type,
+     * if the callee is not a {@linkplain #asVarargsCollector variable arity collector}.
+     * <p>
+     * When this method is observed via the Core Reflection API,
+     * it will appear as a single native method, taking an object array and returning an object.
+     * If this native method is invoked directly via
+     * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
+     * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
+     * it will throw an {@code UnsupportedOperationException}.
+     * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type descriptor
+     * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
+     * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
+     */
+    public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable;
+
+    /**
+     * Performs a varargs invocation, passing the arguments in the given array
+     * to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
+     * which mentions only the type {@code Object}, and whose arity is the length
+     * of the argument array.
+     * <p>
+     * Specifically, execution proceeds as if by the following steps,
+     * although the methods are not guaranteed to be called if the JVM
+     * can predict their effects.
+     * <ul>
+     * <li>Determine the length of the argument array as {@code N}.
+     *     For a null reference, {@code N=0}. </li>
+     * <li>Determine the generic type {@code TN} of {@code N} arguments as
+     *     as {@code TN=MethodType.genericMethodType(N)}.</li>
+     * <li>Force the original target method handle {@code MH0} to the
+     *     required type, as {@code MH1 = MH0.asType(TN)}. </li>
+     * <li>Spread the array into {@code N} separate arguments {@code A0, ...}. </li>
+     * <li>Invoke the type-adjusted method handle on the unpacked arguments:
+     *     MH1.invokeExact(A0, ...). </li>
+     * <li>Take the return value as an {@code Object} reference. </li>
+     * </ul>
+     * <p>
+     * Because of the action of the {@code asType} step, the following argument
+     * conversions are applied as necessary:
+     * <ul>
+     * <li>reference casting
+     * <li>unboxing
+     * <li>widening primitive conversions
+     * </ul>
+     * <p>
+     * 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.spreadInvoker(this.type(), 0);
+     * Object result = invoker.invokeExact(this, arguments);
+     * </pre></blockquote>
+     * <p>
+     * Unlike the signature polymorphic methods {@code invokeExact} and {@code invokeGeneric},
+     * {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI.
+     * It can therefore be used as a bridge between native or reflective code and method handles.
+     *
+     * @param arguments the arguments to pass to the target
+     * @return the result returned by the target
+     * @throws ClassCastException if an argument cannot be converted by reference casting
+     * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
+     * @throws Throwable anything thrown by the target method invocation
+     * @see MethodHandles#spreadInvoker
+     */
+    public Object invokeWithArguments(Object... arguments) throws Throwable {
+        int argc = arguments == null ? 0 : arguments.length;
+        MethodType type = type();
+        if (type.parameterCount() != argc) {
+            // simulate invokeGeneric
+            return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
+        }
+        if (argc <= 10) {
+            MethodHandle invoker = type.invokers().genericInvoker();
+            switch (argc) {
+                case 0:  return invoker.invokeExact(this);
+                case 1:  return invoker.invokeExact(this,
+                                    arguments[0]);
+                case 2:  return invoker.invokeExact(this,
+                                    arguments[0], arguments[1]);
+                case 3:  return invoker.invokeExact(this,
+                                    arguments[0], arguments[1], arguments[2]);
+                case 4:  return invoker.invokeExact(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3]);
+                case 5:  return invoker.invokeExact(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4]);
+                case 6:  return invoker.invokeExact(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4], arguments[5]);
+                case 7:  return invoker.invokeExact(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4], arguments[5],
+                                    arguments[6]);
+                case 8:  return invoker.invokeExact(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4], arguments[5],
+                                    arguments[6], arguments[7]);
+                case 9:  return invoker.invokeExact(this,
+                                    arguments[0], arguments[1], arguments[2],
+                                    arguments[3], arguments[4], arguments[5],
+                                    arguments[6], arguments[7], arguments[8]);
+                case 10:  return invoker.invokeExact(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 = type.invokers().spreadInvoker(0);
+        return invoker.invokeExact(this, arguments);
+    }
+
+    /**
+     * Performs a varargs invocation, passing the arguments in the given array
+     * to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
+     * which mentions only the type {@code Object}, and whose arity is the length
+     * of the argument array.
+     * <p>
+     * This method is also equivalent to the following code:
+     * <p><blockquote><pre>
+     * {@link #invokeWithArguments(Object...) invokeWithArguments}(arguments.toArray())
+     * </pre></blockquote>
+     *
+     * @param arguments the arguments to pass to the target
+     * @return the result returned by the target
+     * @throws ClassCastException if an argument cannot be converted by reference casting
+     * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
+     * @throws Throwable anything thrown by the target method invocation
+     */
+    public Object invokeWithArguments(java.util.List<?> arguments) throws Throwable {
+        return invokeWithArguments(arguments.toArray());
+    }
+
+    /**
+     * Produces an adapter method handle which adapts the type of the
+     * current method handle to a new type.
+     * The resulting method handle is guaranteed to report 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 provides the crucial behavioral difference between
+     * {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}.  The two methods
+     * perform the same steps when the caller's type descriptor is identical
+     * with the callee's, but when the types differ, {@link #invokeGeneric invokeGeneric}
+     * also calls {@code asType} (or some internal equivalent) in order
+     * to match up the caller's and callee's types.
+     * <p>
+     * This method is equivalent to {@link MethodHandles#convertArguments convertArguments},
+     * except for variable arity method handles produced by {@link #asVarargsCollector asVarargsCollector}.
+     *
+     * @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 WrongMethodTypeException if the conversion cannot be made
+     * @see MethodHandles#convertArguments
+     */
+    public MethodHandle asType(MethodType newType) {
+        return MethodHandles.convertArguments(this, newType);
+    }
+
+    /**
+     * Makes an adapter which accepts a trailing array argument
+     * and spreads its elements as positional arguments.
+     * The new method handle 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 the final
+     * {@code arrayLength} parameters of the target's type are replaced
+     * by a single array parameter of type {@code arrayType}.
+     * <p>
+     * If the array element type differs from any of the corresponding
+     * argument types on the original target,
+     * the original target is adapted to take the array elements directly,
+     * as if by a call to {@link #asType asType}.
+     * <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
+     * 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 arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments
+     * @param arrayLength the number of arguments to spread from an incoming array argument
+     * @return a new method handle which spreads its final array argument,
+     *         before calling the original method handle
+     * @throws IllegalArgumentException if {@code arrayType} is not an array type
+     * @throws IllegalArgumentException if target does not have at least
+     *         {@code arrayLength} parameter types
+     * @throws WrongMethodTypeException if the implied {@code asType} call fails
+     * @see #asCollector
+     */
+    public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
+        Class<?> arrayElement = arrayType.getComponentType();
+        if (arrayElement == null)  throw newIllegalArgumentException("not an array type");
+        MethodType oldType = type();
+        int nargs = oldType.parameterCount();
+        if (nargs < arrayLength)  throw newIllegalArgumentException("bad spread array length");
+        int keepPosArgs = nargs - arrayLength;
+        MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs);
+        newType = newType.insertParameterTypes(keepPosArgs, arrayType);
+        return MethodHandles.spreadArguments(this, newType);
+    }
+
+    /**
+     * Makes an adapter which accepts a given number of trailing
+     * positional arguments and collects them into an array argument.
+     * The new method handle 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
+     * parameter (usually of type {@code arrayType}) is replaced by
+     * {@code arrayLength} parameters whose type is element type of {@code arrayType}.
+     * <p>
+     * If the array type differs from the final argument type on the original target,
+     * the original target is adapted to take the array type directly,
+     * as if by a call to {@link #asType asType}.
+     * <p>
+     * When called, the adapter replaces its trailing {@code arrayLength}
+     * arguments by a single new array of type {@code arrayType}, 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 arrayLength} is zero.)
+     * <p>
+     * (<em>Note:</em> The {@code arrayType} is often identical to the last
+     * parameter type of the original target.
+     * It is an explicit argument for symmetry with {@code asSpreader}, and also
+     * to allow the target to use a simple {@code Object} as its last parameter type.)
+     * <p>
+     * In order to create a collecting adapter which is not restricted to a particular
+     * number of collected arguments, use {@link #asVarargsCollector asVarargsCollector} instead.
+     * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
+     * @param arrayLength the number of arguments to collect into a new array argument
+     * @return a new method handle which collects some trailing argument
+     *         into an array, before calling the original method handle
+     * @throws IllegalArgumentException if {@code arrayType} is not an array type
+     *         or {@code arrayType} is not assignable to this method handle's trailing parameter type,
+     *         or {@code arrayLength} is not a legal array size
+     * @throws WrongMethodTypeException if the implied {@code asType} call fails
+     * @see #asSpreader
+     * @see #asVarargsCollector
+     */
+    public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
+        Class<?> arrayElement = arrayType.getComponentType();
+        if (arrayElement == null)  throw newIllegalArgumentException("not an array type");
+        MethodType oldType = type();
+        int nargs = oldType.parameterCount();
+        if (nargs == 0)  throw newIllegalArgumentException("no trailing argument");
+        MethodType newType = oldType.dropParameterTypes(nargs-1, nargs);
+        newType = newType.insertParameterTypes(nargs-1,
+                    java.util.Collections.<Class<?>>nCopies(arrayLength, arrayElement));
+        return MethodHandles.collectArguments(this, newType);
+    }
+
+    /**
+     * Makes a <em>variable arity</em> adapter which is able to accept
+     * any number of trailing positional arguments and collect them
+     * into an array argument.
+     * <p>
+     * The type and behavior of the adapter will be the same as
+     * the type and behavior of the target, except that certain
+     * {@code invokeGeneric} and {@code asType} requests can lead to
+     * trailing positional arguments being collected into target's
+     * trailing parameter.
+     * Also, the last parameter type of the adapter will be
+     * {@code arrayType}, even if the target has a different
+     * last parameter type.
+     * <p>
+     * When called with {@link #invokeExact invokeExact}, the adapter invokes
+     * the target with no argument changes.
+     * (<em>Note:</em> This behavior is different from a
+     * {@linkplain #asCollector fixed arity collector},
+     * since it accepts a whole array of indeterminate length,
+     * rather than a fixed number of arguments.)
+     * <p>
+     * When called with {@link #invokeGeneric invokeGeneric}, if the caller
+     * type is the same as the adapter, the adapter invokes the target as with
+     * {@code invokeExact}.
+     * (This is the normal behavior for {@code invokeGeneric} when types match.)
+     * <p>
+     * Otherwise, if the caller and adapter arity are the same, and the
+     * trailing parameter type of the caller is a reference type identical to
+     * or assignable to the trailing parameter type of the adapter,
+     * the arguments and return values are converted pairwise,
+     * as if by {@link MethodHandles#convertArguments convertArguments}.
+     * (This is also normal behavior for {@code invokeGeneric} in such a case.)
+     * <p>
+     * Otherwise, the arities differ, or the adapter's trailing parameter
+     * type is not assignable from the corresponding caller type.
+     * In this case, the adapter replaces all trailing arguments from
+     * the original trailing argument position onward, by
+     * a new array of type {@code arrayType}, whose elements
+     * comprise (in order) the replaced arguments.
+     * <p>
+     * The caller type must provides as least enough arguments,
+     * and of the correct type, to satisfy the target's requirement for
+     * positional arguments before the trailing array argument.
+     * Thus, the caller must supply, at a minimum, {@code N-1} arguments,
+     * where {@code N} is the arity of the target.
+     * Also, there must exist conversions from the incoming arguments
+     * to the target's arguments.
+     * As with other uses of {@code invokeGeneric}, if these basic
+     * requirements are not fulfilled, a {@code WrongMethodTypeException}
+     * may be thrown.
+     * <p>
+     * In all cases, what the target eventually returns is returned unchanged by the adapter.
+     * <p>
+     * In the final case, it is exactly as if the target method handle were
+     * temporarily adapted with a {@linkplain #asCollector fixed arity collector}
+     * to the arity required by the caller type.
+     * (As with {@code asCollector}, if the array length is zero,
+     * a shared constant may be used instead of a new array.
+     * If the implied call to {@code asCollector} would throw
+     * an {@code IllegalArgumentException} or {@code WrongMethodTypeException},
+     * the call to the variable arity adapter must throw
+     * {@code WrongMethodTypeException}.)
+     * <p>
+     * The behavior of {@link #asType asType} is also specialized for
+     * variable arity adapters, to maintain the invariant that
+     * {@code invokeGeneric} is always equivalent to an {@code asType}
+     * call to adjust the target type, followed by {@code invokeExact}.
+     * Therefore, a variable arity adapter responds
+     * to an {@code asType} request by building a fixed arity collector,
+     * if and only if the adapter and requested type differ either
+     * in arity or trailing argument type.
+     * The resulting fixed arity collector has its type further adjusted
+     * (if necessary) to the requested type by pairwise conversion,
+     * as if by another application of {@code asType}.
+     * <p>
+     * When a method handle is obtained by executing an {@code ldc} instruction
+     * of a {@code CONSTANT_MethodHandle} constant, and the target method is marked
+     * as a variable arity method (with the modifier bit {@code 0x0080}),
+     * the method handle will accept multiple arities, as if the method handle
+     * constant were created by means of a call to {@code asVarargsCollector}.
+     * <p>
+     * In order to create a collecting adapter which collects a predetermined
+     * number of arguments, and whose type reflects this predetermined number,
+     * use {@link #asCollector asCollector} instead.
+     * <p>
+     * No method handle transformations produce new method handles with
+     * variable arity, unless they are documented as doing so.
+     * Therefore, besides {@code asVarargsCollector},
+     * all methods in {@code MethodHandle} and {@code MethodHandles}
+     * will return a method handle with fixed arity,
+     * except in the cases where they are specified to return their original
+     * operand (e.g., {@code asType} of the method handle's own type).
+     * <p>
+     * Calling {@code asVarargsCollector} on a method handle which is already
+     * of variable arity will produce a method handle with the same type and behavior.
+     * It may (or may not) return the original variable arity method handle.
+     * <p>
+     * Here is an example, of a list-making variable arity method handle:
+     * <blockquote><pre>
+MethodHandle asList = publicLookup()
+  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
+  .asVarargsCollector(Object[].class);
+assertEquals("[]", asList.invokeGeneric().toString());
+assertEquals("[1]", asList.invokeGeneric(1).toString());
+assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString());
+Object[] argv = { "three", "thee", "tee" };
+assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString());
+List ls = (List) asList.invokeGeneric((Object)argv);
+assertEquals(1, ls.size());
+assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
+     * </pre></blockquote>
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * These rules are designed as a dynamically-typed variation
+     * of the Java rules for variable arity methods.
+     * In both cases, callers to a variable arity method or method handle
+     * can either pass zero or more positional arguments, or else pass
+     * pre-collected arrays of any length.  Users should be aware of the
+     * special role of the final argument, and of the effect of a
+     * type match on that final argument, which determines whether
+     * or not a single trailing argument is interpreted as a whole
+     * array or a single element of an array to be collected.
+     * Note that the dynamic type of the trailing argument has no
+     * effect on this decision, only a comparison between the static
+     * type descriptor of the call site and the type of the method handle.)
+     * <p style="font-size:smaller;">
+     * As a result of the previously stated rules, the variable arity behavior
+     * of a method handle may be suppressed, by binding it to the exact invoker
+     * of its own type, as follows:
+     * <blockquote><pre>
+MethodHandle vamh = publicLookup()
+  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
+  .asVarargsCollector(Object[].class);
+MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
+assert(vamh.type().equals(mh.type()));
+assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString());
+boolean failed = false;
+try { mh.invokeGeneric(1,2,3); }
+catch (WrongMethodTypeException ex) { failed = true; }
+assert(failed);
+     * </pre></blockquote>
+     * This transformation has no behavioral effect if the method handle is
+     * not of variable arity.
+     *
+     * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
+     * @return a new method handle which can collect any number of trailing arguments
+     *         into an array, before calling the original method handle
+     * @throws IllegalArgumentException if {@code arrayType} is not an array type
+     *         or {@code arrayType} is not assignable to this method handle's trailing parameter type
+     * @see #asCollector
+     * @see #isVarargsCollector
+     */
+    public MethodHandle asVarargsCollector(Class<?> arrayType) {
+        Class<?> arrayElement = arrayType.getComponentType();
+        if (arrayElement == null)  throw newIllegalArgumentException("not an array type");
+        return MethodHandles.asVarargsCollector(this, arrayType);
+    }
+
+    /**
+     * Determines if this method handle
+     * supports {@linkplain #asVarargsCollector variable arity} calls.
+     * Such method handles arise from the following sources:
+     * <ul>
+     * <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
+     * <li>a call to a {@linkplain java.lang.invoke.MethodHandles.Lookup lookup method}
+     *     which resolves to a variable arity Java method or constructor
+     * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
+     *     which resolves to a variable arity Java method or constructor
+     * </ul>
+     * @return true if this method handle accepts more than one arity of {@code invokeGeneric} calls
+     * @see #asVarargsCollector
+     */
+    public boolean isVarargsCollector() {
+        return false;
+    }
+
+    /**
+     * Binds a value {@code x} to the first argument of a method handle, without invoking it.
+     * The new method handle adapts, as its <i>target</i>,
+     * the current method handle by binding it to the given argument.
+     * 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.
+     * <p>
+     * (<em>Note:</em>  Because method handles are immutable, the target method handle
+     * retains its original type and behavior.)
+     * @param x  the value to bind to the first argument of the target
+     * @return a new method handle which prepends the given value to the incoming
+     *         argument list, 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
+     * @see MethodHandles#insertArguments
+     */
+    public MethodHandle bindTo(Object x) {
+        Class<?> ptype;
+        if (type().parameterCount() == 0 ||
+            (ptype = type().parameterType(0)).isPrimitive())
+            throw newIllegalArgumentException("no leading reference parameter", x);
+        x = MethodHandles.checkValue(ptype, x);
+        // Cf. MethodHandles.insertArguments for the following logic:
+        MethodHandle bmh = MethodHandleImpl.bindReceiver(this, x);
+        if (bmh != null)  return bmh;
+        return MethodHandleImpl.bindArgument(this, 0, x);
+    }
+
+    /**
+     * Returns a string representation of the method handle,
+     * starting with the string {@code "MethodHandle"} and
+     * ending with the string representation of the method handle's type.
+     * In other words, this method returns a string equal to the value of:
+     * <blockquote><pre>
+     * "MethodHandle" + type().toString()
+     * </pre></blockquote>
+     * <p>
+     * (<em>Note:</em>  Future releases of this API may add further information
+     * to the string representation.
+     * Therefore, the present syntax should not be parsed by applications.)
+     *
+     * @return a string representation of the method handle
+     */
+    @Override
+    public String toString() {
+        return getNameString(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,1106 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.VerifyType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import sun.invoke.empty.Empty;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
+import sun.misc.Unsafe;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Trusted implementation code for MethodHandle.
+ * @author jrose
+ */
+/*non-public*/ abstract class MethodHandleImpl {
+    /// Factory methods to create method handles:
+
+    private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE;
+
+    static void initStatics() {
+        // Trigger preceding sequence.
+    }
+
+    /** Look up a given method.
+     * Callable only from sun.invoke and related packages.
+     * <p>
+     * The resulting method handle type will be of the given type,
+     * with a receiver type {@code rcvc} prepended if the member is not static.
+     * <p>
+     * Access checks are made as of the given lookup class.
+     * In particular, if the method is protected and {@code defc} is in a
+     * different package from the lookup class, then {@code rcvc} must be
+     * the lookup class or a subclass.
+     * @param token Proof that the lookup class has access to this package.
+     * @param member Resolved method or constructor to call.
+     * @param name Name of the desired method.
+     * @param rcvc Receiver type of desired non-static method (else null)
+     * @param doDispatch whether the method handle will test the receiver type
+     * @param lookupClass access-check relative to this class
+     * @return a direct handle to the matching method
+     * @throws IllegalAccessException if the given method cannot be accessed by the lookup class
+     */
+    static
+    MethodHandle findMethod(MemberName method,
+                            boolean doDispatch, Class<?> lookupClass) throws IllegalAccessException {
+        MethodType mtype = method.getMethodType();
+        if (!method.isStatic()) {
+            // 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.insertParameterTypes(0, recvType);
+        }
+        DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
+        if (!mh.isValid())
+            throw method.makeAccessException("no access", lookupClass);
+        assert(mh.type() == mtype);
+        if (!method.isVarargs())
+            return mh;
+        else
+            return mh.asVarargsCollector(mtype.parameterType(mtype.parameterCount()-1));
+    }
+
+    static
+    MethodHandle makeAllocator(MethodHandle rawConstructor) {
+        MethodType rawConType = rawConstructor.type();
+        // Wrap the raw (unsafe) constructor with the allocation of a suitable object.
+        MethodHandle allocator
+            = AllocateObject.make(rawConType.parameterType(0), rawConstructor);
+        assert(allocator.type()
+               .equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
+        return allocator;
+    }
+
+    static final class AllocateObject<C> extends BoundMethodHandle {
+        private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+        private final Class<C> allocateClass;
+        private final MethodHandle rawConstructor;
+
+        private AllocateObject(MethodHandle invoker,
+                               Class<C> allocateClass, MethodHandle rawConstructor) {
+            super(invoker);
+            this.allocateClass = allocateClass;
+            this.rawConstructor = rawConstructor;
+        }
+        static MethodHandle make(Class<?> allocateClass, MethodHandle rawConstructor) {
+            MethodType rawConType = rawConstructor.type();
+            assert(rawConType.parameterType(0) == allocateClass);
+            MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
+            int nargs = rawConType.parameterCount() - 1;
+            if (nargs < INVOKES.length) {
+                MethodHandle invoke = INVOKES[nargs];
+                MethodType conType = CON_TYPES[nargs];
+                MethodHandle gcon = convertArguments(rawConstructor, conType, rawConType, null);
+                if (gcon == null)  return null;
+                MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
+                assert(galloc.type() == newType.generic());
+                return convertArguments(galloc, newType, galloc.type(), null);
+            } else {
+                MethodHandle invoke = VARARGS_INVOKE;
+                MethodType conType = CON_TYPES[nargs];
+                MethodHandle gcon = spreadArguments(rawConstructor, conType, 1);
+                if (gcon == null)  return null;
+                MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
+                return collectArguments(galloc, newType, 1, null);
+            }
+        }
+        @Override
+        public String toString() {
+            return addTypeString(allocateClass.getSimpleName(), this);
+        }
+        @SuppressWarnings("unchecked")
+        private C allocate() throws InstantiationException {
+            return (C) unsafe.allocateInstance(allocateClass);
+        }
+        private C invoke_V(Object... av) throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj, av);
+            return obj;
+        }
+        private C invoke_L0() throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj);
+            return obj;
+        }
+        private C invoke_L1(Object a0) throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj, a0);
+            return obj;
+        }
+        private C invoke_L2(Object a0, Object a1) throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj, a0, a1);
+            return obj;
+        }
+        private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj, a0, a1, a2);
+            return obj;
+        }
+        private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3);
+            return obj;
+        }
+        private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4);
+            return obj;
+        }
+        private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5);
+            return obj;
+        }
+        private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6);
+            return obj;
+        }
+        private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
+            C obj = allocate();
+            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7);
+            return obj;
+        }
+        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(AllocateObject.class, name, MethodType.genericMethodType(nargs));
+                } catch (ReflectiveOperationException 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(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
+            } catch (ReflectiveOperationException ex) {
+                throw uncaughtException(ex);
+            }
+        }
+        // Corresponding generic constructor types:
+        static final MethodType[] CON_TYPES = new MethodType[INVOKES.length];
+        static {
+            for (int i = 0; i < INVOKES.length; i++)
+                CON_TYPES[i] = makeConType(INVOKES[i]);
+        }
+        static final MethodType VARARGS_CON_TYPE = makeConType(VARARGS_INVOKE);
+        static MethodType makeConType(MethodHandle invoke) {
+            MethodType invType = invoke.type();
+            return invType.changeParameterType(0, Object.class).changeReturnType(void.class);
+        }
+    }
+
+    static
+    MethodHandle accessField(MemberName member, boolean isSetter,
+                             Class<?> lookupClass) {
+        // Use sun. misc.Unsafe to dig up the dirt on the field.
+        MethodHandle mh = new FieldAccessor(member, isSetter);
+        return mh;
+    }
+
+    static
+    MethodHandle accessArrayElement(Class<?> arrayClass, boolean isSetter) {
+        if (!arrayClass.isArray())
+            throw newIllegalArgumentException("not an array: "+arrayClass);
+        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 BoundMethodHandle {
+        private static final Unsafe unsafe = Unsafe.getUnsafe();
+        final Object base;  // for static refs only
+        final long offset;
+        final String name;
+
+        FieldAccessor(MemberName field, boolean isSetter) {
+            super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
+            this.offset = (long) field.getVMIndex();
+            this.name = field.getName();
+            this.base = staticBase(field);
+        }
+        @Override
+        public String toString() { return addTypeString(name, this); }
+
+        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) {
+                throw uncaughtException(ee);
+            }
+        }
+
+        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 (ReflectiveOperationException ex) {
+                throw uncaughtException(ex);
+            }
+            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 (ReflectiveOperationException ex) {
+                throw uncaughtException(ex);
+            }
+            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.
+     * Callable only from MethodHandles.
+     * @param token Proof that the caller has access to this package.
+     * @param target Any direct method handle.
+     * @param receiver Receiver (or first static method argument) to pre-bind.
+     * @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
+     */
+    static
+    MethodHandle bindReceiver(MethodHandle target, Object receiver) {
+        if (target instanceof AdapterMethodHandle &&
+            ((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
+            ) {
+            Object info = MethodHandleNatives.getTargetInfo(target);
+            if (info instanceof DirectMethodHandle) {
+                DirectMethodHandle dmh = (DirectMethodHandle) info;
+                if (receiver == null ||
+                    dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
+                    MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
+                    MethodType newType = target.type().dropParameterTypes(0, 1);
+                    return convertArguments(bmh, newType, bmh.type(), null);
+                }
+            }
+        }
+        if (target instanceof DirectMethodHandle)
+            return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
+        return null;   // let caller try something else
+    }
+
+    /** Bind a predetermined argument to the given arbitrary method handle.
+     * Callable only from MethodHandles.
+     * @param token Proof that the caller has access to this package.
+     * @param target Any method handle.
+     * @param receiver Argument (which can be a boxed primitive) to pre-bind.
+     * @return a suitable BoundMethodHandle
+     */
+    static
+    MethodHandle bindArgument(MethodHandle target, int argnum, Object receiver) {
+        return new BoundMethodHandle(target, receiver, argnum);
+    }
+
+    static MethodHandle convertArguments(MethodHandle target,
+                                                MethodType newType,
+                                                MethodType oldType,
+                                                int[] permutationOrNull) {
+        assert(oldType.parameterCount() == target.type().parameterCount());
+        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(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(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(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(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(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(newType, target);
+        if (res != null)
+            return res;
+        int argc = oldType.parameterCount();
+        // The JVM can't do it directly, so fill in the gap with a Java adapter.
+        // TO DO: figure out what to put here from case-by-case experience
+        // 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.genericMethodType(argc);
+        MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(objType, target);
+        if (objTarget == null)
+            objTarget = FromGeneric.make(target);
+        res = AdapterMethodHandle.makePairwiseConvert(newType, objTarget);
+        if (res != null)
+            return res;
+        return ToGeneric.make(newType, objTarget);
+    }
+
+    static MethodHandle spreadArguments(MethodHandle target,
+                                               MethodType newType,
+                                               int spreadArg) {
+        // TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
+        MethodType oldType = target.type();
+        // spread the last argument of newType to oldType
+        int spreadCount = oldType.parameterCount() - spreadArg;
+        Class<Object[]> spreadArgType = Object[].class;
+        MethodHandle res = AdapterMethodHandle.makeSpreadArguments(newType, target, spreadArgType, spreadArg, spreadCount);
+        if (res != null)
+            return res;
+        // try an intermediate adapter
+        Class<?> spreadType = null;
+        if (spreadArg < 0 || spreadArg >= newType.parameterCount()
+            || !VerifyType.isSpreadArgType(spreadType = newType.parameterType(spreadArg)))
+            throw newIllegalArgumentException("no restarg in "+newType);
+        Class<?>[] ptypes = oldType.parameterArray();
+        for (int i = 0; i < spreadCount; i++)
+            ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i);
+        MethodType midType = MethodType.methodType(newType.returnType(), ptypes);
+        // after spreading, some arguments may need further conversion
+        MethodHandle target2 = convertArguments(target, midType, oldType, null);
+        if (target2 == null)
+            throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType);
+        res = AdapterMethodHandle.makeSpreadArguments(newType, target2, spreadArgType, spreadArg, spreadCount);
+        if (res != null)
+            return res;
+        res = SpreadGeneric.make(target2, spreadCount);
+        if (res != null)
+            res = convertArguments(res, newType, res.type(), null);
+        return res;
+    }
+
+    static MethodHandle collectArguments(MethodHandle target,
+                                                MethodType newType,
+                                                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(target, oldType.generic(), oldType, null);
+        MethodHandle gcollector = convertArguments(collector, colType.generic(), colType, null);
+        if (gtarget == null || gcollector == null)  return null;
+        MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget);
+        MethodHandle result = convertArguments(gresult, newType, gresult.type(), null);
+        return result;
+    }
+
+    static MethodHandle filterArgument(MethodHandle target,
+                                              int pos,
+                                              MethodHandle filter) {
+        MethodType ttype = target.type(), gttype = ttype.generic();
+        if (ttype != gttype) {
+            target = convertArguments(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(filter, gftype, ftype, null);
+            ftype = gftype;
+        }
+        if (ftype == ttype) {
+            // simple unary case
+            return FilterOneArgument.make(filter, target);
+        }
+        return FilterGeneric.makeArgumentFilter(pos, filter, target);
+    }
+
+    static MethodHandle foldArguments(MethodHandle target,
+                                             MethodType newType,
+                                             MethodHandle combiner) {
+        MethodType oldType = target.type();
+        MethodType ctype = combiner.type();
+        MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, null);
+        MethodHandle gcombiner = convertArguments(combiner, ctype.generic(), ctype, null);
+        if (gtarget == null || gcombiner == null)  return null;
+        MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget);
+        MethodHandle result = convertArguments(gresult, newType, gresult.type(), null);
+        return result;
+    }
+
+    static
+    MethodHandle dropArguments(MethodHandle target,
+                               MethodType newType, int argnum) {
+        int drops = newType.parameterCount() - target.type().parameterCount();
+        MethodHandle res = AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops);
+        if (res != null)
+            return res;
+        throw new UnsupportedOperationException("NYI");
+    }
+
+    private static class GuardWithTest extends BoundMethodHandle {
+        private final MethodHandle test, target, fallback;
+        private GuardWithTest(MethodHandle invoker,
+                              MethodHandle test, MethodHandle target, MethodHandle fallback) {
+            super(invoker);
+            this.test = test;
+            this.target = target;
+            this.fallback = fallback;
+        }
+        static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
+            MethodType type = target.type();
+            int nargs = type.parameterCount();
+            if (nargs < INVOKES.length) {
+                MethodHandle invoke = INVOKES[nargs];
+                MethodType gtype = type.generic();
+                assert(invoke.type().dropParameterTypes(0,1) == gtype);
+                MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), null);
+                MethodHandle gtarget = convertArguments(target, gtype, type, null);
+                MethodHandle gfallback = convertArguments(fallback, gtype, type, null);
+                if (gtest == null || gtarget == null || gfallback == null)  return null;
+                MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
+                return convertArguments(gguard, type, gtype, null);
+            } else {
+                MethodHandle invoke = VARARGS_INVOKE;
+                MethodType gtype = MethodType.genericMethodType(1);
+                assert(invoke.type().dropParameterTypes(0,1) == gtype);
+                MethodHandle gtest = spreadArguments(test, gtype.changeReturnType(boolean.class), 0);
+                MethodHandle gtarget = spreadArguments(target, gtype, 0);
+                MethodHandle gfallback = spreadArguments(fallback, gtype, 0);
+                MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
+                if (gtest == null || gtarget == null || gfallback == null)  return null;
+                return collectArguments(gguard, type, 0, null);
+            }
+        }
+        @Override
+        public String toString() {
+            return addTypeString(target, this);
+        }
+        private Object invoke_V(Object... av) throws Throwable {
+            if ((boolean) test.invokeExact(av))
+                return target.invokeExact(av);
+            return fallback.invokeExact(av);
+        }
+        private Object invoke_L0() throws Throwable {
+            if ((boolean) test.invokeExact())
+                return target.invokeExact();
+            return fallback.invokeExact();
+        }
+        private Object invoke_L1(Object a0) throws Throwable {
+            if ((boolean) test.invokeExact(a0))
+                return target.invokeExact(a0);
+            return fallback.invokeExact(a0);
+        }
+        private Object invoke_L2(Object a0, Object a1) throws Throwable {
+            if ((boolean) test.invokeExact(a0, a1))
+                return target.invokeExact(a0, a1);
+            return fallback.invokeExact(a0, a1);
+        }
+        private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
+            if ((boolean) test.invokeExact(a0, a1, a2))
+                return target.invokeExact(a0, a1, a2);
+            return fallback.invokeExact(a0, a1, a2);
+        }
+        private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            if ((boolean) test.invokeExact(a0, a1, a2, a3))
+                return target.invokeExact(a0, a1, a2, a3);
+            return fallback.invokeExact(a0, a1, a2, a3);
+        }
+        private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
+            if ((boolean) test.invokeExact(a0, a1, a2, a3, a4))
+                return target.invokeExact(a0, a1, a2, a3, a4);
+            return fallback.invokeExact(a0, a1, a2, a3, a4);
+        }
+        private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
+            if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5))
+                return target.invokeExact(a0, a1, a2, a3, a4, a5);
+            return fallback.invokeExact(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 ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6))
+                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
+            return fallback.invokeExact(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 ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7))
+                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
+            return fallback.invokeExact(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 (ReflectiveOperationException 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 (ReflectiveOperationException ex) {
+                throw uncaughtException(ex);
+            }
+        }
+    }
+
+    static
+    MethodHandle makeGuardWithTest(MethodHandle test,
+                                   MethodHandle target,
+                                   MethodHandle fallback) {
+        return GuardWithTest.make(test, target, fallback);
+    }
+
+    private static class GuardWithCatch extends BoundMethodHandle {
+        private final MethodHandle target;
+        private final Class<? extends Throwable> exType;
+        private final MethodHandle catcher;
+        GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
+            this(INVOKES[target.type().parameterCount()], target, exType, catcher);
+        }
+       GuardWithCatch(MethodHandle invoker,
+                      MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
+            super(invoker);
+            this.target = target;
+            this.exType = exType;
+            this.catcher = catcher;
+        }
+        @Override
+        public String toString() {
+            return addTypeString(target, this);
+        }
+        private Object invoke_V(Object... av) throws Throwable {
+            try {
+                return target.invokeExact(av);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(t, av);
+            }
+        }
+        private Object invoke_L0() throws Throwable {
+            try {
+                return target.invokeExact();
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(t);
+            }
+        }
+        private Object invoke_L1(Object a0) throws Throwable {
+            try {
+                return target.invokeExact(a0);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(t, a0);
+            }
+        }
+        private Object invoke_L2(Object a0, Object a1) throws Throwable {
+            try {
+                return target.invokeExact(a0, a1);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(t, a0, a1);
+            }
+        }
+        private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
+            try {
+                return target.invokeExact(a0, a1, a2);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(t, a0, a1, a2);
+            }
+        }
+        private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+            try {
+                return target.invokeExact(a0, a1, a2, a3);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(t, a0, a1, a2, a3);
+            }
+        }
+        private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
+            try {
+                return target.invokeExact(a0, a1, a2, a3, a4);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
+            } catch (Throwable t) {
+                if (!exType.isInstance(t))  throw t;
+                return catcher.invokeExact(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 (ReflectiveOperationException 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 (ReflectiveOperationException ex) {
+                throw uncaughtException(ex);
+            }
+        }
+    }
+
+
+    static
+    MethodHandle makeGuardWithCatch(MethodHandle target,
+                                    Class<? extends Throwable> exType,
+                                    MethodHandle catcher) {
+        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(target, gtype, type, null);
+            MethodHandle gcatcher = convertArguments(catcher, gcatchType, ctype, null);
+            MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher);
+            if (gtarget == null || gcatcher == null || gguard == null)  return null;
+            return convertArguments(gguard, type, gtype, null);
+        } else {
+            MethodType gtype = MethodType.genericMethodType(0, true);
+            MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
+            MethodHandle gtarget = spreadArguments(target, gtype, 0);
+            MethodHandle gcatcher = spreadArguments(catcher, gcatchType, 1);
+            MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher);
+            if (gtarget == null || gcatcher == null || gguard == null)  return null;
+            return collectArguments(gguard, type, 0, null);
+        }
+    }
+
+    static
+    MethodHandle throwException(MethodType type) {
+        return AdapterMethodHandle.makeRetypeRaw(type, throwException());
+    }
+
+    static MethodHandle THROW_EXCEPTION;
+    static MethodHandle throwException() {
+        if (THROW_EXCEPTION != null)  return THROW_EXCEPTION;
+        try {
+            THROW_EXCEPTION
+            = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
+                    MethodType.methodType(Empty.class, Throwable.class));
+        } catch (ReflectiveOperationException ex) {
+            throw new RuntimeException(ex);
+        }
+        return THROW_EXCEPTION;
+    }
+    static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
+
+    // Linkage support:
+    static void registerBootstrap(Class<?> callerClass, MethodHandle bootstrapMethod) {
+        MethodHandleNatives.registerBootstrap(callerClass, bootstrapMethod);
+    }
+    static MethodHandle getBootstrap(Class<?> callerClass) {
+        return MethodHandleNatives.getBootstrap(callerClass);
+    }
+
+    static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
+        return AdapterMethodHandle.makeVarargsCollector(target, arrayType);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * The JVM interface for the method handles package is all here.
+ * This is an interface internal and private to an implemetantion of JSR 292.
+ * <em>This class is not part of the JSR 292 standard.</em>
+ * @author jrose
+ */
+class MethodHandleNatives {
+
+    private MethodHandleNatives() { } // static only
+
+    /// MethodName support
+
+    static native void init(MemberName self, Object ref);
+    static native void expand(MemberName self);
+    static native void resolve(MemberName self, Class<?> caller);
+    static native int getMembers(Class<?> defc, String matchName, String matchSig,
+            int matchFlags, Class<?> caller, int skip, MemberName[] results);
+
+    /// MethodHandle support
+
+    /** Initialize the method handle to adapt the call. */
+    static native void init(AdapterMethodHandle self, MethodHandle target, int argnum);
+    /** Initialize the method handle to call the correct method, directly. */
+    static native void init(BoundMethodHandle self, Object target, int argnum);
+    /** Initialize the method handle to call as if by an invoke* instruction. */
+    static native void init(DirectMethodHandle self, Object ref, boolean doDispatch, Class<?> caller);
+
+    /** Initialize a method type, once per form. */
+    static native void init(MethodType self);
+
+    /** Tell the JVM about a class's bootstrap method. */
+    static native void registerBootstrap(Class<?> caller, MethodHandle bootstrapMethod);
+
+    /** Ask the JVM about a class's bootstrap method. */
+    static native MethodHandle getBootstrap(Class<?> caller);
+
+    /** Tell the JVM that we need to change the target of an invokedynamic. */
+    static native void setCallSiteTarget(CallSite site, MethodHandle target);
+
+    /** Fetch the vmtarget field.
+     *  It will be sanitized as necessary to avoid exposing non-Java references.
+     *  This routine is for debugging and reflection.
+     */
+    static native Object getTarget(MethodHandle self, int format);
+
+    /** Fetch the name of the handled method, if available.
+     *  This routine is for debugging and reflection.
+     */
+    static MemberName getMethodName(MethodHandle self) {
+        return (MemberName) getTarget(self, ETF_METHOD_NAME);
+    }
+
+    /** Fetch the reflective version of the handled method, if available.
+     */
+    static AccessibleObject getTargetMethod(MethodHandle self) {
+        return (AccessibleObject) getTarget(self, ETF_REFLECT_METHOD);
+    }
+
+    /** Fetch the target of this method handle.
+     *  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) {
+        return getTarget(self, ETF_HANDLE_OR_METHOD_NAME);
+    }
+
+    static Object[] makeTarget(Class<?> defc, String name, String sig, int mods, Class<?> refc) {
+        return new Object[] { defc, name, sig, mods, refc };
+    }
+
+    /** Fetch MH-related JVM parameter.
+     *  which=0 retrieves MethodHandlePushLimit
+     *  which=1 retrieves stack slot push size (in address units)
+     */
+    static native int getConstant(int which);
+
+    /** Java copy of MethodHandlePushLimit in range 2..255. */
+    static final int JVM_PUSH_LIMIT;
+    /** JVM stack motion (in words) after one slot is pushed, usually -1.
+     */
+    static final int JVM_STACK_MOVE_UNIT;
+
+    /** Which conv-ops are implemented by the JVM? */
+    static final int CONV_OP_IMPLEMENTED_MASK;
+
+    private static native void registerNatives();
+    static {
+        int     JVM_PUSH_LIMIT_;
+        int     JVM_STACK_MOVE_UNIT_;
+        int     CONV_OP_IMPLEMENTED_MASK_;
+        try {
+            registerNatives();
+            JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
+            JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT);
+            CONV_OP_IMPLEMENTED_MASK_ = getConstant(Constants.GC_CONV_OP_IMPLEMENTED_MASK);
+            //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
+        } catch (UnsatisfiedLinkError ee) {
+            // ignore; if we use init() methods later we'll see linkage errors
+            JVM_PUSH_LIMIT_ = 3;  // arbitrary
+            JVM_STACK_MOVE_UNIT_ = -1;  // arbitrary
+            CONV_OP_IMPLEMENTED_MASK_ = 0;
+            JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
+            JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
+            throw ee;  // just die; hopeless to try to run with an older JVM
+        }
+        JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
+        JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
+        if (CONV_OP_IMPLEMENTED_MASK_ == 0)
+            CONV_OP_IMPLEMENTED_MASK_ = DEFAULT_CONV_OP_IMPLEMENTED_MASK;
+        CONV_OP_IMPLEMENTED_MASK = CONV_OP_IMPLEMENTED_MASK_;
+    }
+
+    // All compile-time constants go here.
+    // There is an opportunity to check them against the JVM's idea of them.
+    static class Constants {
+        Constants() { } // static only
+        // MethodHandleImpl
+        static final int // for getConstant
+                GC_JVM_PUSH_LIMIT = 0,
+                GC_JVM_STACK_MOVE_UNIT = 1,
+                GC_CONV_OP_IMPLEMENTED_MASK = 2;
+        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)
+                ETF_METHOD_NAME           = 2, // ultimate method as MemberName
+                ETF_REFLECT_METHOD        = 3; // ultimate method as java.lang.reflect object (sans refClass)
+
+        // MemberName
+        // The JVM uses values of -2 and above for vtable indexes.
+        // Field values are simple positive offsets.
+        // Ref: src/share/vm/oops/methodOop.hpp
+        // This value is negative enough to avoid such numbers,
+        // but not too negative.
+        static final int
+                MN_IS_METHOD           = 0x00010000, // method (not constructor)
+                MN_IS_CONSTRUCTOR      = 0x00020000, // constructor
+                MN_IS_FIELD            = 0x00040000, // field
+                MN_IS_TYPE             = 0x00080000, // nested type
+                MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
+                MN_SEARCH_INTERFACES   = 0x00200000, // for MHN.getMembers
+                VM_INDEX_UNINITIALIZED = -99;
+
+        // BoundMethodHandle
+        /** Constants for decoding the vmargslot field, which contains 2 values. */
+        static final int
+            ARG_SLOT_PUSH_SHIFT = 16,
+            ARG_SLOT_MASK = (1<<ARG_SLOT_PUSH_SHIFT)-1;
+
+        // AdapterMethodHandle
+        /** Conversions recognized by the JVM.
+         *  They must align with the constants in java.lang.invoke.AdapterMethodHandle,
+         *  in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp.
+         */
+        static final int
+            OP_RETYPE_ONLY   = 0x0, // no argument changes; straight retype
+            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.
+         */
+        static final int
+            CONV_OP_MASK     = 0xF00, // this nybble contains the conversion op field
+            CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
+            CONV_VMINFO_SHIFT     =  0, // position of bits in CONV_VMINFO_MASK
+            CONV_OP_SHIFT         =  8, // position of bits in CONV_OP_MASK
+            CONV_DEST_TYPE_SHIFT  = 12, // byte 2 has the adapter BasicType (if needed)
+            CONV_SRC_TYPE_SHIFT   = 16, // byte 2 has the source BasicType (if needed)
+            CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
+            CONV_STACK_MOVE_MASK  = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1;
+
+        /** Which conv-ops are implemented by the JVM? */
+        static final int DEFAULT_CONV_OP_IMPLEMENTED_MASK =
+                // Value to use if the corresponding JVM query fails.
+                ((1<<OP_RETYPE_ONLY)
+                |(1<<OP_RETYPE_RAW)
+                |(1<<OP_CHECK_CAST)
+                |(1<<OP_PRIM_TO_PRIM)
+                |(1<<OP_REF_TO_PRIM)
+                |(1<<OP_SWAP_ARGS)
+                |(1<<OP_ROT_ARGS)
+                |(1<<OP_DUP_ARGS)
+                |(1<<OP_DROP_ARGS)
+                //|(1<<OP_SPREAD_ARGS)
+                );
+
+        /**
+         * Basic types as encoded in the JVM.  These code values are not
+         * intended for use outside this class.  They are used as part of
+         * a private interface between the JVM and this class.
+         */
+        static final int
+            T_BOOLEAN  =  4,
+            T_CHAR     =  5,
+            T_FLOAT    =  6,
+            T_DOUBLE   =  7,
+            T_BYTE     =  8,
+            T_SHORT    =  9,
+            T_INT      = 10,
+            T_LONG     = 11,
+            T_OBJECT   = 12,
+            //T_ARRAY    = 13
+            T_VOID     = 14;
+            //T_ADDRESS  = 15
+
+        /**
+         * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
+         */
+        static final int
+            REF_getField                = 1,
+            REF_getStatic               = 2,
+            REF_putField                = 3,
+            REF_putStatic               = 4,
+            REF_invokeVirtual           = 5,
+            REF_invokeStatic            = 6,
+            REF_invokeSpecial           = 7,
+            REF_newInvokeSpecial        = 8,
+            REF_invokeInterface         = 9;
+    }
+
+    private static native int getNamedCon(int which, Object[] name);
+    static boolean verifyConstants() {
+        Object[] box = { null };
+        for (int i = 0; ; i++) {
+            box[0] = null;
+            int vmval = getNamedCon(i, box);
+            if (box[0] == null)  break;
+            String name = (String) box[0];
+            try {
+                Field con = Constants.class.getDeclaredField(name);
+                int jval = con.getInt(null);
+                if (jval != vmval)
+                    throw new InternalError(name+": JVM has "+vmval+" while Java has "+jval);
+            } catch (Exception ex) {
+                throw new InternalError(name+": access failed, got "+ex);
+            }
+        }
+        return true;
+    }
+    static {
+        verifyConstants();
+    }
+
+    // Up-calls from the JVM.
+    // These must NOT be public.
+
+    /**
+     * The JVM is linking an invokedynamic instruction.  Create a reified call site for it.
+     */
+    static CallSite makeDynamicCallSite(MethodHandle bootstrapMethod,
+                                        String name, MethodType type,
+                                        Object info,
+                                        MemberName callerMethod, int callerBCI) {
+        return CallSite.makeSite(bootstrapMethod, name, type, info, callerMethod, callerBCI);
+    }
+
+    /**
+     * Called by the JVM to check the length of a spread array.
+     */
+    static void checkSpreadArgument(Object av, int n) {
+        MethodHandleStatics.checkSpreadArgument(av, n);
+    }
+
+    /**
+     * The JVM wants a pointer to a MethodType.  Oblige it by finding or creating one.
+     */
+    static MethodType findMethodHandleType(Class<?> rtype, Class<?>[] ptypes) {
+        return MethodType.makeImpl(rtype, ptypes, true);
+    }
+
+    /**
+     * The JVM wants to use a MethodType with invokeGeneric.  Give the runtime fair warning.
+     */
+    static void notifyGenericMethodType(MethodType type) {
+        type.form().notifyGenericMethodType();
+    }
+
+    /**
+     * The JVM wants to raise an exception.  Here's the path.
+     */
+    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);
+        }
+    }
+
+    /**
+     * The JVM is resolving a CONSTANT_MethodHandle CP entry.  And it wants our help.
+     * It will make an up-call to this method.  (Do not change the name or signature.)
+     */
+    static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
+                                                 Class<?> defc, String name, Object type) {
+        try {
+            Lookup lookup = IMPL_LOOKUP.in(callerClass);
+            switch (refKind) {
+            case REF_getField:          return lookup.findGetter(       defc, name, (Class<?>)   type );
+            case REF_getStatic:         return lookup.findStaticGetter( defc, name, (Class<?>)   type );
+            case REF_putField:          return lookup.findSetter(       defc, name, (Class<?>)   type );
+            case REF_putStatic:         return lookup.findStaticSetter( defc, name, (Class<?>)   type );
+            case REF_invokeVirtual:     return lookup.findVirtual(      defc, name, (MethodType) type );
+            case REF_invokeStatic:      return lookup.findStatic(       defc, name, (MethodType) type );
+            case REF_invokeSpecial:     return lookup.findSpecial(      defc, name, (MethodType) type, callerClass );
+            case REF_newInvokeSpecial:  return lookup.findConstructor(  defc,       (MethodType) type );
+            case REF_invokeInterface:   return lookup.findVirtual(      defc, name, (MethodType) type );
+            }
+            throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
+        } catch (ReflectiveOperationException ex) {
+            Error err = new IncompatibleClassChangeError();
+            err.initCause(ex);
+            throw err;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * This class consists exclusively of static names internal to the
+ * method handle implementation.
+ * Usage:  {@code import static java.lang.invoke.MethodHandleStatics.*}
+ * @author John Rose, JSR 292 EG
+ */
+/*non-public*/ class MethodHandleStatics {
+
+    private MethodHandleStatics() { }  // do not instantiate
+
+    /*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
+        if (type == null)
+            type = target.type();
+        MemberName name = null;
+        if (target != null)
+            name = MethodHandleNatives.getMethodName(target);
+        if (name == null)
+            return "invoke" + type;
+        return name.getName() + type;
+    }
+
+    /*non-public*/ static String getNameString(MethodHandle target, MethodHandle typeHolder) {
+        return getNameString(target, typeHolder == null ? (MethodType) null : typeHolder.type());
+    }
+
+    /*non-public*/ static String getNameString(MethodHandle target) {
+        return getNameString(target, (MethodType) null);
+    }
+
+    /*non-public*/ static String addTypeString(Object obj, MethodHandle target) {
+        String str = String.valueOf(obj);
+        if (target == null)  return str;
+        int paren = str.indexOf('(');
+        if (paren >= 0) str = str.substring(0, paren);
+        return str + target.type();
+    }
+
+    static void checkSpreadArgument(Object av, int n) {
+        if (av == null ? n != 0 : ((Object[])av).length != n)
+            throw newIllegalArgumentException("Array is not of length "+n);
+    }
+
+    // handy shared exception makers (they simplify the common case code)
+    /*non-public*/ static RuntimeException newIllegalStateException(String message) {
+        return new IllegalStateException(message);
+    }
+    /*non-public*/ static RuntimeException newIllegalStateException(String message, Object obj) {
+        return new IllegalStateException(message(message, obj));
+    }
+    /*non-public*/ static RuntimeException newIllegalArgumentException(String message) {
+        return new IllegalArgumentException(message);
+    }
+    /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj) {
+        return new IllegalArgumentException(message(message, obj));
+    }
+    /*non-public*/ static Error uncaughtException(Exception ex) {
+        Error err = new InternalError("uncaught exception");
+        err.initCause(ex);
+        return err;
+    }
+    private static String message(String message, Object obj) {
+        if (obj != null)  message = message + ": " + obj;
+        return message;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,2357 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.lang.reflect.*;
+import sun.invoke.WrapperInstance;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.VerifyAccess;
+import sun.invoke.util.Wrapper;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import sun.reflect.Reflection;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * This class consists exclusively of static methods that operate on or return
+ * method handles. They fall into several categories:
+ * <ul>
+ * <li>Lookup methods which help create method handles for methods and fields.
+ * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
+ * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
+ * <li>Wrapper methods which can convert between method handles and interface types.
+ * </ul>
+ * <p>
+ * @author John Rose, JSR 292 EG
+ */
+public class MethodHandles {
+
+    private MethodHandles() { }  // do not instantiate
+
+    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
+    static { MethodHandleImpl.initStatics(); }
+    // See IMPL_LOOKUP below.
+
+    //// Method handle creation from ordinary methods.
+
+    /**
+     * Returns a {@link Lookup lookup object} on the caller,
+     * which has the capability to access any method handle that the caller has access to,
+     * including direct method handles to private fields and methods.
+     * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
+     * Do not store it in place where untrusted code can access it.
+     */
+    public static Lookup lookup() {
+        return new Lookup();
+    }
+
+    /**
+     * Returns a {@link Lookup lookup object} which is trusted minimally.
+     * It can only be used to create method handles to
+     * publicly accessible fields and methods.
+     * <p>
+     * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
+     * of this lookup object will be {@link java.lang.Object}.
+     * <p>
+     * The lookup class can be changed to any other class {@code C} using an expression of the form
+     * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
+     * Since all classes have equal access to public names,
+     * such a change would confer no new access rights.
+     */
+    public static Lookup publicLookup() {
+        return Lookup.PUBLIC_LOOKUP;
+    }
+
+    /**
+     * A <em>lookup object</em> is a factory for creating method handles,
+     * when the creation requires access checking.
+     * Method handles do not perform
+     * access checks when they are called, but rather when they are created.
+     * Therefore, method handle access
+     * restrictions must be enforced when a method handle is created.
+     * The caller class against which those restrictions are enforced
+     * is known as the {@linkplain #lookupClass lookup class}.
+     * <p>
+     * A lookup class which needs to create method handles will call
+     * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
+     * When the {@code Lookup} factory object is created, the identity of the lookup class is
+     * determined, and securely stored in the {@code Lookup} object.
+     * The lookup class (or its delegates) may then use factory methods
+     * on the {@code Lookup} object to create method handles for access-checked members.
+     * This includes all methods, constructors, and fields which are allowed to the lookup class,
+     * even private ones.
+     * <p>
+     * The factory methods on a {@code Lookup} object correspond to all major
+     * use cases for methods, constructors, and fields.
+     * Here is a summary of the correspondence between these factory methods and
+     * the behavior the resulting method handles:
+     * <code>
+     * <table border=1 cellpadding=5 summary="lookup method behaviors">
+     * <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
+     *     <td>FT f;</td><td>(T) this.f;</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
+     *     <td>static<br>FT f;</td><td>(T) C.f;</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
+     *     <td>FT f;</td><td>this.f = x;</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
+     *     <td>static<br>FT f;</td><td>C.f = arg;</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
+     *     <td>T m(A*);</td><td>(T) this.m(arg*);</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
+     *     <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
+     *     <td>T m(A*);</td><td>(T) super.m(arg*);</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
+     *     <td>C(A*);</td><td>(T) new C(arg*);</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
+     *     <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
+     *     <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
+     *     <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
+     *     <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td>
+     * </tr>
+     * <tr>
+     *     <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
+     *     <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
+     * </tr>
+     * </table>
+     * </code>
+     * Here, the type {@code C} is the class or interface being searched for a member,
+     * documented as a parameter named {@code refc} in the lookup methods.
+     * The method or constructor type {@code MT} is composed from the return type {@code T}
+     * and the sequence of argument types {@code A*}.
+     * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
+     * The formal parameter {@code this} stands for the self-reference of type {@code C};
+     * if it is present, it is always the leading argument to the method handle invocation.
+     * The name {@code arg} stands for all the other method handle arguments.
+     * In the code examples for the Core Reflection API, the name {@code thisOrNull}
+     * stands for a null reference if the accessed method or field is static,
+     * and {@code this} otherwise.
+     * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
+     * for reflective objects corresponding to the given members.
+     * <p>
+     * The equivalence between looked-up method handles and underlying
+     * class members can break down in a few ways:
+     * <ul>
+     * <li>If {@code C} is not symbolically accessible from the lookup class's loader,
+     * the lookup can still succeed, even when there is no equivalent
+     * Java expression or bytecoded constant.
+     * <li>Likewise, if {@code T} or {@code MT}
+     * is not symbolically accessible from the lookup class's loader,
+     * the lookup can still succeed.
+     * For example, lookups for {@code MethodHandle.invokeExact} and
+     * {@code MethodHandle.invokeGeneric} will always succeed, regardless of requested type.
+     * <li>If there is a security manager installed, it can forbid the lookup
+     * on various grounds (<a href="#secmgr">see below</a>).
+     * By contrast, the {@code ldc} instruction is not subject to
+     * security manager checks.
+     * </ul>
+     *
+     * <h3><a name="access"></a>Access checking</h3>
+     * Access checks are applied in the factory methods of {@code Lookup},
+     * when a method handle is created.
+     * This is a key difference from the Core Reflection API, since
+     * {@link java.lang.reflect.Method#invoke Method.invoke}
+     * performs access checking against every caller, on every call.
+     * <p>
+     * All access checks start from a {@code Lookup} object, which
+     * compares its recorded lookup class against all requests to
+     * create method handles.
+     * A single {@code Lookup} object can be used to create any number
+     * of access-checked method handles, all checked against a single
+     * lookup class.
+     * <p>
+     * A {@code Lookup} object can be shared with other trusted code,
+     * such as a metaobject protocol.
+     * A shared {@code Lookup} object delegates the capability
+     * to create method handles on private members of the lookup class.
+     * Even if privileged code uses the {@code Lookup} object,
+     * the access checking is confined to the privileges of the
+     * original lookup class.
+     * <p>
+     * A lookup can fail, because
+     * the containing class is not accessible to the lookup class, or
+     * because the desired class member is missing, or because the
+     * desired class member is not accessible to the lookup class.
+     * In any of these cases, a {@code ReflectiveOperationException} will be
+     * thrown from the attempted lookup.  The exact class will be one of
+     * the following:
+     * <ul>
+     * <li>NoSuchMethodException &mdash; if a method is requested but does not exist
+     * <li>NoSuchFieldException &mdash; if a field is requested but does not exist
+     * <li>IllegalAccessException &mdash; if the member exists but an access check fails
+     * </ul>
+     * <p>
+     * In general, the conditions under which a method handle may be
+     * looked up for a method {@code M} are exactly equivalent to the conditions
+     * under which the lookup class could have compiled and resolved a call to {@code M}.
+     * And the effect of invoking the method handle resulting from the lookup
+     * is exactly equivalent to executing the compiled and resolved call to {@code M}.
+     * The same point is true of fields and constructors.
+     * <p>
+     * In some cases, access between nested classes is obtained by the Java compiler by creating
+     * an wrapper method to access a private method of another class
+     * in the same top-level declaration.
+     * For example, a nested class {@code C.D}
+     * can access private members within other related classes such as
+     * {@code C}, {@code C.D.E}, or {@code C.B},
+     * but the Java compiler may need to generate wrapper methods in
+     * those related classes.  In such cases, a {@code Lookup} object on
+     * {@code C.E} would be unable to those private members.
+     * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
+     * which can transform a lookup on {@code C.E} into one on any of those other
+     * classes, without special elevation of privilege.
+     * <p>
+     * Although bytecode instructions can only refer to classes in
+     * a related class loader, this API can search for methods in any
+     * class, as long as a reference to its {@code Class} object is
+     * available.  Such cross-loader references are also possible with the
+     * Core Reflection API, and are impossible to bytecode instructions
+     * such as {@code invokestatic} or {@code getfield}.
+     * There is a {@linkplain java.lang.SecurityManager security manager API}
+     * to allow applications to check such cross-loader references.
+     * These checks apply to both the {@code MethodHandles.Lookup} API
+     * and the Core Reflection API
+     * (as found on {@link java.lang.Class Class}).
+     * <p>
+     * Access checks only apply to named and reflected methods,
+     * constructors, and fields.
+     * Other method handle creation methods, such as
+     * {@link #convertArguments MethodHandles.convertArguments},
+     * do not require any access checks, and are done
+     * with static methods of {@link MethodHandles},
+     * independently of any {@code Lookup} object.
+     *
+     * <h3>Security manager interactions</h3>
+     * <a name="secmgr"></a>
+     * If a security manager is present, member lookups are subject to
+     * additional checks.
+     * From one to four calls are made to the security manager.
+     * Any of these calls can refuse access by throwing a
+     * {@link java.lang.SecurityException SecurityException}.
+     * Define {@code smgr} as the security manager,
+     * {@code refc} as the containing class in which the member
+     * is being sought, and {@code defc} as the class in which the
+     * member is actually defined.
+     * The calls are made according to the following rules:
+     * <ul>
+     * <li>In all cases, {@link SecurityManager#checkMemberAccess
+     *     smgr.checkMemberAccess(refc, Member.PUBLIC)} is called.
+     * <li>If the class loader of the lookup class is not
+     *     the same as or an ancestor of the class loader of {@code refc},
+     *     then {@link SecurityManager#checkPackageAccess
+     *     smgr.checkPackageAccess(refcPkg)} is called,
+     *     where {@code refcPkg} is the package of {@code refc}.
+     * <li>If the retrieved member is not public,
+     *     {@link SecurityManager#checkMemberAccess
+     *     smgr.checkMemberAccess(defc, Member.DECLARED)} is called.
+     *     (Note that {@code defc} might be the same as {@code refc}.)
+     * <li>If the retrieved member is not public,
+     *     and if {@code defc} and {@code refc} are in different class loaders,
+     *     and if the class loader of the lookup class is not
+     *     the same as or an ancestor of the class loader of {@code defc},
+     *     then {@link SecurityManager#checkPackageAccess
+     *     smgr.checkPackageAccess(defcPkg)} is called,
+     *     where {@code defcPkg} is the package of {@code defc}.
+     * </ul>
+     * In all cases, the requesting class presented to the security
+     * manager will be the lookup class from the current {@code Lookup} object.
+     */
+    public static final
+    class Lookup {
+        /** The class on behalf of whom the lookup is being performed. */
+        private final Class<?> lookupClass;
+
+        /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
+        private final int allowedModes;
+
+        /** A single-bit mask representing {@code public} access,
+         *  which may contribute to the result of {@link #lookupModes lookupModes}.
+         *  The value, {@code 0x01}, happens to be the same as the value of the
+         *  {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
+         */
+        public static final int PUBLIC = Modifier.PUBLIC;
+
+        /** A single-bit mask representing {@code private} access,
+         *  which may contribute to the result of {@link #lookupModes lookupModes}.
+         *  The value, {@code 0x02}, happens to be the same as the value of the
+         *  {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
+         */
+        public static final int PRIVATE = Modifier.PRIVATE;
+
+        /** A single-bit mask representing {@code protected} access,
+         *  which may contribute to the result of {@link #lookupModes lookupModes}.
+         *  The value, {@code 0x04}, happens to be the same as the value of the
+         *  {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
+         */
+        public static final int PROTECTED = Modifier.PROTECTED;
+
+        /** A single-bit mask representing {@code package} access (default access),
+         *  which may contribute to the result of {@link #lookupModes lookupModes}.
+         *  The value is {@code 0x08}, which does not correspond meaningfully to
+         *  any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
+         */
+        public static final int PACKAGE = Modifier.STATIC;
+
+        private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
+        private static final int TRUSTED   = -1;
+
+        private static int fixmods(int mods) {
+            mods &= (ALL_MODES - PACKAGE);
+            return (mods != 0) ? mods : PACKAGE;
+        }
+
+        /** Tells which class is performing the lookup.  It is this class against
+         *  which checks are performed for visibility and access permissions.
+         *  <p>
+         *  The class implies a maximum level of access permission,
+         *  but the permissions may be additionally limited by the bitmask
+         *  {@link #lookupModes lookupModes}, which controls whether non-public members
+         *  can be accessed.
+         */
+        public Class<?> lookupClass() {
+            return lookupClass;
+        }
+
+        // This is just for calling out to MethodHandleImpl.
+        private Class<?> lookupClassOrNull() {
+            return (allowedModes == TRUSTED) ? null : lookupClass;
+        }
+
+        /** Tells which access-protection classes of members this lookup object can produce.
+         *  The result is a bit-mask of the bits
+         *  {@linkplain #PUBLIC PUBLIC (0x01)},
+         *  {@linkplain #PRIVATE PRIVATE (0x02)},
+         *  {@linkplain #PROTECTED PROTECTED (0x04)},
+         *  and {@linkplain #PACKAGE PACKAGE (0x08)}.
+         *  <p>
+         *  A freshly-created lookup object
+         *  on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class}
+         *  has all possible bits set, since the caller class can access all its own members.
+         *  A lookup object on a new lookup class
+         *  {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
+         *  may have some mode bits set to zero.
+         *  The purpose of this is to restrict access via the new lookup object,
+         *  so that it can access only names which can be reached by the original
+         *  lookup object, and also by the new lookup class.
+         */
+        public int lookupModes() {
+            return allowedModes & ALL_MODES;
+        }
+
+        /** Embody the current class (the lookupClass) as a lookup class
+         * for method handle creation.
+         * Must be called by from a method in this package,
+         * which in turn is called by a method not in this package.
+         * <p>
+         * Also, don't make it private, lest javac interpose
+         * an access$N method.
+         */
+        Lookup() {
+            this(getCallerClassAtEntryPoint(), ALL_MODES);
+            // make sure we haven't accidentally picked up a privileged class:
+            checkUnprivilegedlookupClass(lookupClass);
+        }
+
+        Lookup(Class<?> lookupClass) {
+            this(lookupClass, ALL_MODES);
+        }
+
+        private Lookup(Class<?> lookupClass, int allowedModes) {
+            this.lookupClass = lookupClass;
+            this.allowedModes = allowedModes;
+        }
+
+        /**
+         * Creates a lookup on the specified new lookup class.
+         * The resulting object will report the specified
+         * class as its own {@link #lookupClass lookupClass}.
+         * <p>
+         * However, the resulting {@code Lookup} object is guaranteed
+         * to have no more access capabilities than the original.
+         * In particular, access capabilities can be lost as follows:<ul>
+         * <li>If the new lookup class differs from the old one,
+         * protected members will not be accessible by virtue of inheritance.
+         * (Protected members may continue to be accessible because of package sharing.)
+         * <li>If the new lookup class is in a different package
+         * than the old one, protected and default (package) members will not be accessible.
+         * <li>If the new lookup class is not within the same package member
+         * as the old one, private members will not be accessible.
+         * <li>If the new lookup class is not accessible to the old lookup class,
+         * then no members, not even public members, will be accessible.
+         * (In all other cases, public members will continue to be accessible.)
+         * </ul>
+         *
+         * @param requestedLookupClass the desired lookup class for the new lookup object
+         * @return a lookup object which reports the desired lookup class
+         * @throws NullPointerException if the argument is null
+         */
+        public Lookup in(Class<?> requestedLookupClass) {
+            requestedLookupClass.getClass();  // null check
+            if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
+                return new Lookup(requestedLookupClass, ALL_MODES);
+            if (requestedLookupClass == this.lookupClass)
+                return this;  // keep same capabilities
+            int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
+            if ((newModes & PACKAGE) != 0
+                && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
+                newModes &= ~(PACKAGE|PRIVATE);
+            }
+            // Allow nestmate lookups to be created without special privilege:
+            if ((newModes & PRIVATE) != 0
+                && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
+                newModes &= ~PRIVATE;
+            }
+            if (newModes == PUBLIC
+                && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass)) {
+                // The requested class it not accessible from the lookup class.
+                // No permissions.
+                newModes = 0;
+            }
+            checkUnprivilegedlookupClass(requestedLookupClass);
+            return new Lookup(requestedLookupClass, newModes);
+        }
+
+        // Make sure outer class is initialized first.
+        static { IMPL_NAMES.getClass(); }
+
+        /** Version of lookup which is trusted minimally.
+         *  It can only be used to create method handles to
+         *  publicly accessible members.
+         */
+        static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
+
+        /** Package-private version of lookup which is trusted. */
+        static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
+
+        private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
+            String name = lookupClass.getName();
+            if (name.startsWith("java.lang.invoke."))
+                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
+        }
+
+        /**
+         * Displays the name of the class from which lookups are to be made.
+         * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
+         * If there are restrictions on the access permitted to this lookup,
+         * this is indicated by adding a suffix to the class name, consisting
+         * of a slash and a keyword.  The keyword represents the strongest
+         * allowed access, and is chosen as follows:
+         * <ul>
+         * <li>If no access is allowed, the suffix is "/noaccess".
+         * <li>If only public access is allowed, the suffix is "/public".
+         * <li>If only public and package access are allowed, the suffix is "/package".
+         * <li>If only public, package, and private access are allowed, the suffix is "/private".
+         * </ul>
+         * If none of the above cases apply, it is the case that full
+         * access (public, package, private, and protected) is allowed.
+         * In this case, no suffix is added.
+         * This is true only of an object obtained originally from
+         * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
+         * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in}
+         * always have restricted access, and will display a suffix.
+         * <p>
+         * (It may seem strange that protected access should be
+         * stronger than private access.  Viewed independently from
+         * package access, protected access is the first to be lost,
+         * because it requires a direct subclass relationship between
+         * caller and callee.)
+         * @see #in
+         */
+        @Override
+        public String toString() {
+            String cname = lookupClass.getName();
+            switch (allowedModes) {
+            case 0:  // no privileges
+                return cname + "/noaccess";
+            case PUBLIC:
+                return cname + "/public";
+            case PUBLIC|PACKAGE:
+                return cname + "/package";
+            case ALL_MODES & ~PROTECTED:
+                return cname + "/private";
+            case ALL_MODES:
+                return cname;
+            case TRUSTED:
+                return "/trusted";  // internal only; not exported
+            default:  // Should not happen, but it's a bitfield...
+                cname = cname + "/" + Integer.toHexString(allowedModes);
+                assert(false) : cname;
+                return cname;
+            }
+        }
+
+        // call this from an entry point method in Lookup with extraFrames=0.
+        private static Class<?> getCallerClassAtEntryPoint() {
+            final int CALLER_DEPTH = 4;
+            // 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);
+        }
+
+        /**
+         * Produces 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 {@link #findVirtual findVirtual} or {@link #findSpecial 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.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * @param refc the class from which the method is accessed
+         * @param name the name of the method
+         * @param type the type of the method
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the method does not exist
+         * @throws IllegalAccessException if access checking fails, or if the method is not {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public
+        MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+            MemberName method = resolveOrFail(refc, name, type, true);
+            checkMethod(refc, method, true);
+            return MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
+        }
+
+        /**
+         * Produces a method handle for a virtual method.
+         * The type of the method handle will be that of the method,
+         * with the receiver type (usually {@code refc}) prepended.
+         * The method and all its argument types must be accessible to the lookup class.
+         * <p>
+         * When called, the handle will treat the first argument as a receiver
+         * and dispatch on the receiver's type to determine which method
+         * implementation to enter.
+         * (The dispatching action is identical with that performed by an
+         * {@code invokevirtual} or {@code invokeinterface} instruction.)
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * <p>
+         * Because of the general equivalence between {@code invokevirtual}
+         * instructions and method handles produced by {@code findVirtual},
+         * if the class is {@code MethodHandle} and the name string is
+         * {@code invokeExact} or {@code invokeGeneric}, the resulting
+         * method handle is equivalent to one produced by
+         * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
+         * {@link java.lang.invoke.MethodHandles#genericInvoker MethodHandles.genericInvoker}
+         * with the same {@code type} argument.
+         *
+         * @param refc the class or interface 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
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the method does not exist
+         * @throws IllegalAccessException if access checking fails, or if the method is {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+            MemberName method = resolveOrFail(refc, name, type, false);
+            checkMethod(refc, method, false);
+            MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
+            return restrictProtectedReceiver(method, mh);
+        }
+
+        /**
+         * Produces a method handle which creates an object and initializes it, using
+         * the constructor of the specified type.
+         * The parameter types of the method handle will be those of the constructor,
+         * while the return type will be a reference to the constructor's class.
+         * The constructor and all its argument types must be accessible to the lookup class.
+         * If the constructor's class has not yet been initialized, that is done
+         * immediately, before the method handle is returned.
+         * <p>
+         * Note:  The requested type must have a return type of {@code void}.
+         * This is consistent with the JVM's treatment of constructor type descriptors.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
+         * @param refc the class or interface from which the method is accessed
+         * @param type the type of the method, with the receiver argument omitted, and a void return type
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the constructor does not exist
+         * @throws IllegalAccessException if access checking fails
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+            String name = "<init>";
+            MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
+            assert(ctor.isConstructor());
+            checkAccess(refc, ctor);
+            MethodHandle rawMH = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
+            MethodHandle allocMH = MethodHandleImpl.makeAllocator(rawMH);
+            return fixVarargs(allocMH, rawMH);
+        }
+
+        /** Return a version of MH which matches matchMH w.r.t. isVarargsCollector. */
+        private static MethodHandle fixVarargs(MethodHandle mh, MethodHandle matchMH) {
+            boolean va1 = mh.isVarargsCollector();
+            boolean va2 = matchMH.isVarargsCollector();
+            if (va1 == va2) {
+                return mh;
+            } else if (va2) {
+                MethodType type = mh.type();
+                int arity = type.parameterCount();
+                return mh.asVarargsCollector(type.parameterType(arity-1));
+            } else {
+                throw new InternalError("already varargs, but template is not: "+mh);
+            }
+        }
+
+        /**
+         * Produces an early-bound method handle for a virtual method,
+         * as if called from an {@code invokespecial}
+         * instruction from {@code caller}.
+         * The type of the method handle will be that of the method,
+         * with a suitably restricted receiver type (such as {@code caller}) prepended.
+         * The method and all its argument types must be accessible
+         * to the caller.
+         * <p>
+         * When called, the handle will treat the first argument as a receiver,
+         * but will not dispatch on the receiver's type.
+         * (This direct invocation action is identical with that performed by an
+         * {@code invokespecial} instruction.)
+         * <p>
+         * If the explicitly specified caller class is not identical with the
+         * lookup class, or if this lookup object does not have private access
+         * privileges, the access fails.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * @param refc the class or interface from which the method is accessed
+         * @param name the name of the method (which must not be "&lt;init&gt;")
+         * @param type the type of the method, with the receiver argument omitted
+         * @param specialCaller the proposed calling class to perform the {@code invokespecial}
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the method does not exist
+         * @throws IllegalAccessException if access checking fails
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
+                                        Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
+            checkSpecialCaller(specialCaller);
+            MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
+            checkMethod(refc, method, false);
+            MethodHandle mh = MethodHandleImpl.findMethod(method, false, specialCaller);
+            return restrictReceiver(method, mh, specialCaller);
+        }
+
+        /**
+         * Produces a method handle giving read access to a non-static field.
+         * The type of the method handle will have a return type of the field's
+         * value type.
+         * The method handle's single argument will be the instance containing
+         * the field.
+         * Access checking is performed immediately on behalf of the lookup class.
+         * @param refc the class or interface from which the method is accessed
+         * @param name the field's name
+         * @param type the field's type
+         * @return a method handle which can load values from the field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            return makeAccessor(refc, name, type, false, false);
+        }
+
+        /**
+         * Produces a method handle giving write access to a non-static field.
+         * The type of the method handle will have a void return type.
+         * The method handle will take two arguments, the instance containing
+         * the field, and the value to be stored.
+         * The second argument will be of the field's value type.
+         * Access checking is performed immediately on behalf of the lookup class.
+         * @param refc the class or interface from which the method is accessed
+         * @param name the field's name
+         * @param type the field's type
+         * @return a method handle which can store values into the field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            return makeAccessor(refc, name, type, false, true);
+        }
+
+        /**
+         * Produces a method handle giving read access to a static field.
+         * The type of the method handle will have a return type of the field's
+         * value type.
+         * The method handle will take no arguments.
+         * Access checking is performed immediately on behalf of the lookup class.
+         * @param refc the class or interface from which the method is accessed
+         * @param name the field's name
+         * @param type the field's type
+         * @return a method handle which can load values from the field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            return makeAccessor(refc, name, type, true, false);
+        }
+
+        /**
+         * Produces a method handle giving write access to a static field.
+         * The type of the method handle will have a void return type.
+         * The method handle will take a single
+         * argument, of the field's value type, the value to be stored.
+         * Access checking is performed immediately on behalf of the lookup class.
+         * @param refc the class or interface from which the method is accessed
+         * @param name the field's name
+         * @param type the field's type
+         * @return a method handle which can store values into the field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            return makeAccessor(refc, name, type, true, true);
+        }
+
+        /**
+         * Produces an early-bound method handle for a non-static method.
+         * 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,
+         * 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>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set
+         * <em>and</em> the trailing array argument is not the only argument.
+         * (If the trailing array argument is the only argument,
+         * the given receiver value will be bound to it.)
+         * <p>
+         * This is equivalent to the following code:
+         * <blockquote><pre>
+MethodHandle mh0 = {@link #findVirtual findVirtual}(defc, name, type);
+MethodHandle mh1 = mh0.{@link MethodHandle#bindTo bindTo}(receiver);
+MethodType mt1 = mh1.type();
+if (mh0.isVarargsCollector() && mt1.parameterCount() > 0) {
+  mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
+return mh1;
+         * </pre></blockquote>
+         * 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.
+         * (Note that {@code bindTo} does not preserve variable arity.)
+         * @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
+         * @return the desired method handle
+         * @throws NoSuchMethodException if the method does not exist
+         * @throws IllegalAccessException if access checking fails
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+            Class<? extends Object> refc = receiver.getClass(); // may get NPE
+            MemberName method = resolveOrFail(refc, name, type, false);
+            checkMethod(refc, method, false);
+            MethodHandle dmh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
+            MethodHandle bmh = MethodHandleImpl.bindReceiver(dmh, receiver);
+            if (bmh == null)
+                throw method.makeAccessException("no access", this);
+            if (dmh.type().parameterCount() == 0)
+                return dmh;  // bound the trailing parameter; no varargs possible
+            return fixVarargs(bmh, dmh);
+        }
+
+        /**
+         * Makes 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.
+         * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
+         * The type of the method handle will be that of the method,
+         * with the receiver type prepended (but only if it is non-static).
+         * If the method's {@code accessible} flag is not set,
+         * access checking is performed immediately on behalf of the lookup class.
+         * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * @param m the reflected method
+         * @return a method handle which can invoke the reflected method
+         * @throws IllegalAccessException if access checking fails
+         * @throws NullPointerException if the argument is null
+         */
+        public MethodHandle unreflect(Method m) throws IllegalAccessException {
+            MemberName method = new MemberName(m);
+            assert(method.isMethod());
+            if (!m.isAccessible())  checkMethod(method.getDeclaringClass(), method, method.isStatic());
+            MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
+            if (!m.isAccessible())  mh = restrictProtectedReceiver(method, mh);
+            return mh;
+        }
+
+        /**
+         * Produces a method handle for a reflected method.
+         * It will bypass checks for overriding methods on the receiver,
+         * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
+         * The type of the method handle will be that of the method,
+         * with the special caller type prepended (and <em>not</em> the receiver of the method).
+         * If the method'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.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the method's variable arity modifier bit ({@code 0x0080}) is set.
+         * @param m the reflected method
+         * @param specialCaller the class nominally calling the method
+         * @return a method handle which can invoke the reflected method
+         * @throws IllegalAccessException if access checking fails
+         * @throws NullPointerException if any argument is null
+         */
+        public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
+            checkSpecialCaller(specialCaller);
+            MemberName method = new MemberName(m);
+            assert(method.isMethod());
+            // ignore m.isAccessible:  this is a new kind of access
+            checkMethod(m.getDeclaringClass(), method, false);
+            MethodHandle mh = MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
+            return restrictReceiver(method, mh, specialCaller);
+        }
+
+        /**
+         * Produces a method handle for a reflected 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.
+         * <p>
+         * The returned method handle will have
+         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
+         * @param c the reflected constructor
+         * @return a method handle which can invoke the reflected constructor
+         * @throws IllegalAccessException if access checking fails
+         * @throws NullPointerException if the argument is null
+         */
+        public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException {
+            MemberName ctor = new MemberName(c);
+            assert(ctor.isConstructor());
+            if (!c.isAccessible())  checkAccess(c.getDeclaringClass(), ctor);
+            MethodHandle rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
+            MethodHandle allocator = MethodHandleImpl.makeAllocator(rawCtor);
+            return fixVarargs(allocator, rawCtor);
+        }
+
+        /**
+         * Produces 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.
+         * 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 field's {@code accessible} flag is not set,
+         * access checking is performed immediately on behalf of the lookup class.
+         * @param f the reflected field
+         * @return a method handle which can load values from the reflected field
+         * @throws IllegalAccessException if access checking fails
+         * @throws NullPointerException if the argument is null
+         */
+        public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
+            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
+        }
+
+        /**
+         * Produces a method handle giving write access to a reflected field.
+         * The type of the method handle will have a void return type.
+         * 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 field's {@code accessible} flag is not set,
+         * access checking is performed immediately on behalf of the lookup class.
+         * @param f the reflected field
+         * @return a method handle which can store values into the reflected field
+         * @throws IllegalAccessException if access checking fails
+         * @throws NullPointerException if the argument is null
+         */
+        public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
+            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
+        }
+
+        /// Helper methods, all package-private.
+
+        MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoSuchFieldException, IllegalAccessException {
+            checkSymbolicClass(refc);  // do this before attempting to resolve
+            name.getClass(); type.getClass();  // NPE
+            int mods = (isStatic ? Modifier.STATIC : 0);
+            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
+                                            NoSuchFieldException.class);
+        }
+
+        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoSuchMethodException, IllegalAccessException {
+            checkSymbolicClass(refc);  // do this before attempting to resolve
+            name.getClass(); type.getClass();  // NPE
+            int mods = (isStatic ? Modifier.STATIC : 0);
+            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
+                                            NoSuchMethodException.class);
+        }
+
+        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
+                                 boolean searchSupers, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
+            checkSymbolicClass(refc);  // do this before attempting to resolve
+            name.getClass(); type.getClass();  // NPE
+            int mods = (isStatic ? Modifier.STATIC : 0);
+            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller,
+                                            NoSuchMethodException.class);
+        }
+
+        void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
+            Class<?> caller = lookupClassOrNull();
+            if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
+                throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
+        }
+
+        void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws IllegalAccessException {
+            String message;
+            if (m.isConstructor())
+                message = "expected a method, not a constructor";
+            else if (!m.isMethod())
+                message = "expected a method";
+            else if (wantStatic != m.isStatic())
+                message = wantStatic ? "expected a static method" : "expected a non-static method";
+            else
+                { checkAccess(refc, m); return; }
+            throw m.makeAccessException(message, this);
+        }
+
+        void checkAccess(Class<?> refc, MemberName m) throws IllegalAccessException {
+            int allowedModes = this.allowedModes;
+            if (allowedModes == TRUSTED)  return;
+            int mods = m.getModifiers();
+            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
+                return;  // common case
+            int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
+            if ((requestedModes & allowedModes) != 0
+                && VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
+                                                   mods, lookupClass()))
+                return;
+            if (((requestedModes & ~allowedModes) & PROTECTED) != 0
+                && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
+                // Protected members can also be checked as if they were package-private.
+                return;
+            throw m.makeAccessException(accessFailedMessage(refc, m), this);
+        }
+
+        String accessFailedMessage(Class<?> refc, MemberName m) {
+            Class<?> defc = m.getDeclaringClass();
+            int mods = m.getModifiers();
+            // check the class first:
+            boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
+                               (defc == refc ||
+                                Modifier.isPublic(refc.getModifiers())));
+            if (!classOK && (allowedModes & PACKAGE) != 0) {
+                classOK = (VerifyAccess.isClassAccessible(defc, lookupClass()) &&
+                           (defc == refc ||
+                            VerifyAccess.isClassAccessible(refc, lookupClass())));
+            }
+            if (!classOK)
+                return "class is not public";
+            if (Modifier.isPublic(mods))
+                return "access to public member failed";  // (how?)
+            if (Modifier.isPrivate(mods))
+                return "member is private";
+            if (Modifier.isProtected(mods))
+                return "member is protected";
+            return "member is private to package";
+        }
+
+        private static final boolean ALLOW_NESTMATE_ACCESS = false;
+
+        void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
+            if (allowedModes == TRUSTED)  return;
+            if ((allowedModes & PRIVATE) == 0
+                || (specialCaller != lookupClass()
+                    && !(ALLOW_NESTMATE_ACCESS &&
+                         VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
+                throw new MemberName(specialCaller).
+                    makeAccessException("no private access for invokespecial", this);
+        }
+
+        MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws IllegalAccessException {
+            // The accessing class only has the right to use a protected member
+            // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
+            if (!method.isProtected() || method.isStatic()
+                || allowedModes == TRUSTED
+                || method.getDeclaringClass() == lookupClass()
+                || (ALLOW_NESTMATE_ACCESS &&
+                    VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
+                return mh;
+            else
+                return restrictReceiver(method, mh, lookupClass());
+        }
+        MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException {
+            assert(!method.isStatic());
+            Class<?> defc = method.getDeclaringClass();  // receiver type of mh is too wide
+            if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
+                throw method.makeAccessException("caller class must be a subclass below the method", caller);
+            }
+            MethodType rawType = mh.type();
+            if (rawType.parameterType(0) == caller)  return mh;
+            MethodType narrowType = rawType.changeParameterType(0, caller);
+            MethodHandle narrowMH = MethodHandleImpl.convertArguments(mh, narrowType, rawType, null);
+            return fixVarargs(narrowMH, mh);
+        }
+
+        MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type,
+                                  boolean isStatic, boolean isSetter) throws NoSuchFieldException, IllegalAccessException {
+            MemberName field = resolveOrFail(refc, name, type, isStatic);
+            if (isStatic != field.isStatic())
+                throw field.makeAccessException(isStatic
+                                                ? "expected a static field"
+                                                : "expected a non-static field", this);
+            return makeAccessor(refc, field, false, isSetter);
+        }
+
+        MethodHandle makeAccessor(Class<?> refc, MemberName field,
+                                  boolean trusted, boolean isSetter) throws IllegalAccessException {
+            assert(field.isField());
+            if (trusted)
+                return MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
+            checkAccess(refc, field);
+            MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
+            return restrictProtectedReceiver(field, mh);
+        }
+    }
+
+    /**
+     * Produces a method handle giving read access to elements of an array.
+     * The type of the method handle will have a return type of the array's
+     * element type.  Its first argument will be the array type,
+     * and the second will be {@code int}.
+     * @param arrayClass an array type
+     * @return a method handle which can load values from the given array type
+     * @throws NullPointerException if the argument is null
+     * @throws  IllegalArgumentException if arrayClass is not an array type
+     */
+    public static
+    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
+        return MethodHandleImpl.accessArrayElement(arrayClass, false);
+    }
+
+    /**
+     * Produces a method handle giving write access to elements of an array.
+     * The type of the method handle will have a void return type.
+     * Its last argument will be the array's element type.
+     * The first and second arguments will be the array type and int.
+     * @return a method handle which can store values into the array type
+     * @throws NullPointerException if the argument is null
+     * @throws IllegalArgumentException if arrayClass is not an array type
+     */
+    public static
+    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
+        return MethodHandleImpl.accessArrayElement(arrayClass, true);
+    }
+
+    /// method handle invocation (reflective style)
+
+    /**
+     * Produces a method handle which will invoke any method handle of the
+     * given {@code 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>
+     * <p>
+     * The invoker will behave like a call to {@link MethodHandle#invokeGeneric invokeGeneric} with
+     * the indicated {@code type}.
+     * That is, if the target is exactly of the given {@code type}, it will behave
+     * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
+     * is used to convert the target to the required {@code type}.
+     * <p>
+     * The type of the returned invoker will not be the given {@code type}, but rather
+     * will have all parameter and return types replaced by {@code Object}, except for
+     * the last parameter type, which will be the array type {@code Object[]}.
+     * <p>
+     * Before invoking its target, the invoker will spread the varargs array, apply
+     * reference casts as necessary, and unbox and widen 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 method is equivalent to the following code (though it may be more efficient):
+     * <p><blockquote><pre>
+MethodHandle invoker = MethodHandles.genericInvoker(type);
+int spreadArgCount = type.parameterCount - objectArgCount;
+invoker = invoker.asSpreader(Object[].class, spreadArgCount);
+return invoker;
+     * </pre></blockquote>
+     * <p>
+     * This method throws no reflective or security exceptions.
+     * @param type the desired target type
+     * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
+     * @return a method handle suitable for invoking any method handle of the given type
+     */
+    static public
+    MethodHandle spreadInvoker(MethodType type, int objectArgCount) {
+        if (objectArgCount < 0 || objectArgCount > type.parameterCount())
+            throw new IllegalArgumentException("bad argument count "+objectArgCount);
+        return type.invokers().spreadInvoker(objectArgCount);
+    }
+
+    /**
+     * Produces a special <em>invoker method handle</em> which can be used to
+     * invoke any method handle of the given type, as if by {@code invokeExact}.
+     * 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 method is equivalent to the following code (though it may be more efficient):
+     * <p><blockquote><pre>
+publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
+     * </pre></blockquote>
+     *
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * Invoker method handles can be useful when working with variable method handles
+     * of unknown types.
+     * For example, to emulate an {@code invokeExact} call to a variable method
+     * handle {@code M}, extract its type {@code T},
+     * look up the invoker method {@code X} for {@code T},
+     * and call the invoker method, as {@code X.invokeGeneric(T, A...)}.
+     * (It would not work to call {@code X.invokeExact}, since the type {@code T}
+     * is unknown.)
+     * If spreading, collecting, or other argument transformations are required,
+     * they can be applied once to the invoker {@code X} and reused on many {@code M}
+     * method handle values, as long as they are compatible with the type of {@code X}.
+     * <p>
+     * <em>(Note:  The invoker method is not available via the Core Reflection API.
+     * An attempt to call {@linkplain java.lang.reflect.Method#invoke Method.invoke}
+     * on the declared {@code invokeExact} or {@code invokeGeneric} method will raise an
+     * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
+     * <p>
+     * This method throws no reflective or security exceptions.
+     * @param type the desired target type
+     * @return a method handle suitable for invoking any method handle of the given type
+     */
+    static public
+    MethodHandle exactInvoker(MethodType type) {
+        return type.invokers().exactInvoker();
+    }
+
+    /**
+     * Produces a special <em>invoker method handle</em> which can be used to
+     * invoke any method handle of the given type, as if by {@code invokeGeneric}.
+     * 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>
+     * Before invoking its target, the invoker will apply reference casts as
+     * necessary and unbox and widen primitive arguments, as if by {@link #convertArguments 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>
+publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
+     * </pre></blockquote>
+     * <p>
+     * This method throws no reflective or security exceptions.
+     * @param type the desired target type
+     * @return a method handle suitable for invoking any method handle convertible to the given type
+     */
+    static public
+    MethodHandle genericInvoker(MethodType type) {
+        return type.invokers().genericInvoker();
+    }
+
+    /**
+     * Perform value checking, exactly as if for an adapted method handle.
+     * It is assumed that the given value is either null, of type T0,
+     * or (if T0 is primitive) of the wrapper type corresponding to T0.
+     * The following checks and conversions are made:
+     * <ul>
+     * <li>If T0 and T1 are references, 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 primitives, then a widening or narrowing
+     *     conversion is applied, if one exists.
+     * <li>If T0 is a primitive and T1 a reference, and
+     *     T0 has a wrapper type TW, a boxing conversion to TW is applied,
+     *     possibly followed by a reference conversion.
+     *     T1 must be TW or a supertype.
+     * <li>If T0 is a reference and T1 a primitive, and
+     *     T1 has a wrapper type TW, an unboxing conversion is applied,
+     *     possibly preceded by a reference conversion.
+     *     T0 must be TW or a supertype.
+     * <li>If T1 is void, the return 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.
+     * </ul>
+     * If the value is discarded, null will be returned.
+     * @param valueType
+     * @param value
+     * @return the value, converted if necessary
+     * @throws java.lang.ClassCastException if a cast fails
+     */
+    static
+    <T0, T1> T1 checkValue(Class<T0> t0, Class<T1> t1, Object value)
+       throws ClassCastException
+    {
+        if (t0 == t1) {
+            // no conversion needed; just reassert the same type
+            if (t0.isPrimitive())
+                return Wrapper.asPrimitiveType(t1).cast(value);
+            else
+                return Wrapper.OBJECT.convert(value, t1);
+        }
+        boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
+        if (!prim0) {
+            // check contract with caller
+            Wrapper.OBJECT.convert(value, t0);
+            if (!prim1) {
+                return Wrapper.OBJECT.convert(value, t1);
+            }
+            // convert reference to primitive by unboxing
+            Wrapper w1 = Wrapper.forPrimitiveType(t1);
+            return w1.convert(value, t1);
+        }
+        // check contract with caller:
+        Wrapper.asWrapperType(t0).cast(value);
+        Wrapper w1 = Wrapper.forPrimitiveType(t1);
+        return w1.convert(value, t1);
+    }
+
+    static
+    Object checkValue(Class<?> T1, Object value)
+       throws ClassCastException
+    {
+        Class<?> T0;
+        if (value == null)
+            T0 = Object.class;
+        else
+            T0 = value.getClass();
+        return checkValue(T0, T1, value);
+    }
+
+    /// method handle modification (creation from other method handles)
+
+    /**
+     * Produces a method handle which adapts the type of the
+     * 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 report a type
+     * which is equal to the desired new type.
+     * <p>
+     * If the original type and new type are equal, returns target.
+     * <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, 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 primitives, then a Java method invocation
+     *     conversion (JLS 5.3) is applied, if one exists.
+     * <li>If T0 is a primitive and T1 a reference, a boxing
+     *     conversion is applied if one exists, possibly followed by
+     *     a reference conversion to a superclass.
+     *     T1 must be a wrapper class or a supertype of one.
+     * <li>If T0 is a reference and T1 a primitive, an unboxing
+     *     conversion will be applied at runtime, possibly followed
+     *     by a Java method invocation conversion (JLS 5.3)
+     *     on the primitive value.  (These are the widening conversions.)
+     *     T0 must be a wrapper class or a supertype of one.
+     *     (In the case where T0 is Object, these are the conversions
+     *     allowed by java.lang.reflect.Method.invoke.)
+     * <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 NullPointerException if either argument is null
+     * @throws WrongMethodTypeException if the conversion cannot be made
+     * @see MethodHandle#asType
+     * @see MethodHandles#explicitCastArguments
+     */
+    public static
+    MethodHandle convertArguments(MethodHandle target, MethodType newType) {
+        MethodType oldType = target.type();
+        if (oldType.equals(newType))
+            return target;
+        MethodHandle res = null;
+        try {
+            res = MethodHandleImpl.convertArguments(target,
+                                                    newType, oldType, null);
+        } catch (IllegalArgumentException ex) {
+        }
+        if (res == null)
+            throw new WrongMethodTypeException("cannot convert to "+newType+": "+target);
+        return res;
+    }
+
+    /**
+     * Produces a method handle which adapts the type of the
+     * 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 report a type
+     * which is equal to the desired new type.
+     * <p>
+     * If the original type and new type are equal, returns target.
+     * <p>
+     * The same conversions are allowed as for {@link #convertArguments convertArguments},
+     * and some additional conversions are also applied if those conversions fail.
+     * Given types T0, T1, one of the following conversions is applied
+     * in addition, if the conversions specified for {@code convertArguments}
+     * would be insufficient:
+     * <ul>
+     * <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 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 a primitive value would be converted by {@code convertArguments}
+     *     using Java method invocation conversion (JLS 5.3),
+     *     Java casting conversion (JLS 5.5) may be used also.
+     *     This allows primitives to be narrowed as well as widened.
+     * </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 NullPointerException if either argument is null
+     * @throws WrongMethodTypeException if the conversion cannot be made
+     * @see MethodHandle#asType
+     * @see MethodHandles#convertArguments
+     */
+    public static
+    MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
+        return convertArguments(target, newType);  // FIXME!
+    }
+
+    /*
+      FIXME: Reconcile javadoc with 10/22/2010 EG notes on conversion:
+
+      Both converters arrange for their method handles to convert arguments
+      and return values.  The conversion rules are the same for arguments
+      and return values, and depend only on source and target types, S and
+      T.  The conversions allowed by castConvertArguments are a strict
+      superset of those performed by convertArguments.
+
+      In all cases, if S and T are references, a simple checkcast is done.
+      If neither S nor T is a primitive, no attempt is made to unbox and
+      box.  A failed conversion throws ClassCastException.
+
+      If T is void, the value is dropped.
+
+      For compatibility with reflection, if S is void and T is a reference,
+      a null value is produced.
+
+      For compatibility with reflection, if S is a reference and T is a
+      primitive, S is first unboxed and then undergoes primitive conversion.
+      In the case of 'convertArguments', only assignment conversion is
+      performed (no narrowing primitive conversion).
+
+      If S is a primitive, S is boxed, and then the above rules are applied.
+      If S and T are both primitives, the boxing will be undetectable; only
+      the primitive conversions will be apparent to the user.  The key point
+      is that if S is a primitive type, the implementation may box it and
+      treat is as Object, without loss of information, or it may use a "fast
+      path" which does not use boxing.
+
+      Notwithstanding the rules above, for compatibility with the verifier,
+      if T is an interface, it is treated as if it were Object.  [KEEP THIS?]
+
+      Also, for compatibility with the verifier, a boolean may be undergo
+      widening or narrowing conversion to any other primitive type.  [KEEP THIS?]
+    */
+
+    /**
+     * Produces a method handle which adapts the calling sequence of the
+     * given method handle to a new type, by reordering the arguments.
+     * The resulting method handle is guaranteed to report a type
+     * which is equal to the desired new type.
+     * <p>
+     * The given array controls the reordering.
+     * Call {@code #I} the number of incoming parameters (the value
+     * {@code newType.parameterCount()}, and call {@code #O} the number
+     * of outgoing parameters (the value {@code target.type().parameterCount()}).
+     * Then the length of the reordering array must be {@code #O},
+     * and each element must be a non-negative number less than {@code #I}.
+     * For every {@code N} less than {@code #O}, the {@code N}-th
+     * outgoing argument will be taken from the {@code I}-th incoming
+     * argument, where {@code I} is {@code reorder[N]}.
+     * <p>
+     * No argument or return value conversions are applied.
+     * The type of each incoming argument, as determined by {@code newType},
+     * must be identical to the type of the corresponding outgoing argument
+     * or arguments in the target method handle.
+     * The return type of {@code newType} must be identical to the return
+     * type of the original target.
+     * <p>
+     * The reordering array need not specify an actual permutation.
+     * An incoming argument will be duplicated if its index appears
+     * more than once in the array, and an incoming argument will be dropped
+     * if its index does not appear in the array.
+     * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
+     * incoming arguments which are not mentioned in the reordering array
+     * are may be any type, as determined only by {@code newType}.
+     * <blockquote><pre>
+MethodType intfn1 = MethodType.methodType(int.class, int.class);
+MethodType intfn2 = MethodType.methodType(int.class, int.class, int.class);
+MethodHandle sub = ... {int x, int y => x-y} ...;
+assert(sub.type().equals(intfn2));
+MethodHandle sub1 = MethodHandles.permuteArguments(sub, intfn2, 0, 1);
+MethodHandle rsub = MethodHandles.permuteArguments(sub, intfn2, 1, 0);
+assert((int)rsub.invokeExact(1, 100) == 99);
+MethodHandle add = ... {int x, int y => x+y} ...;
+assert(add.type().equals(intfn2));
+MethodHandle twice = MethodHandles.permuteArguments(add, intfn1, 0, 0);
+assert(twice.type().equals(intfn1));
+assert((int)twice.invokeExact(21) == 42);
+     * </pre></blockquote>
+     * @param target the method handle to invoke after arguments are reordered
+     * @param newType the expected type of the new method handle
+     * @param reorder a string which controls the reordering
+     * @return a method handle which delegates to {@code target} after it
+     *           drops unused arguments and moves and/or duplicates the other arguments
+     * @throws NullPointerException if any argument is null
+     */
+    public static
+    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
+        MethodType oldType = target.type();
+        checkReorder(reorder, newType, oldType);
+        return MethodHandleImpl.convertArguments(target,
+                                                 newType, oldType,
+                                                 reorder);
+    }
+
+    private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
+        if (reorder.length == oldType.parameterCount()) {
+            int limit = newType.parameterCount();
+            boolean bad = false;
+            for (int i : reorder) {
+                if (i < 0 || i >= limit) {
+                    bad = true; break;
+                }
+            }
+            if (!bad)  return;
+        }
+        throw newIllegalArgumentException("bad reorder array");
+    }
+
+    /**
+     * Equivalent to the following code:
+     * <p><blockquote><pre>
+     * int spreadPos = newType.parameterCount() - 1;
+     * Class&lt;?&gt; spreadType = newType.parameterType(spreadPos);
+     * int spreadCount = target.type().parameterCount() - spreadPos;
+     * MethodHandle adapter = target.asSpreader(spreadType, spreadCount);
+     * adapter = adapter.asType(newType);
+     * return adapter;
+     * </pre></blockquote>
+     * @param target the method handle to invoke after argument spreading
+     * @param newType the expected type of the new method handle
+     * @return a method handle which spreads its final argument,
+     *         before calling the original method handle
+     */
+    /*non-public*/ static
+    MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
+        MethodType oldType = target.type();
+        int inargs  = newType.parameterCount();
+        int outargs = oldType.parameterCount();
+        int spreadPos = inargs - 1;
+        int numSpread = (outargs - spreadPos);
+        MethodHandle res = null;
+        if (spreadPos >= 0 && numSpread >= 0) {
+            res = MethodHandleImpl.spreadArguments(target, newType, spreadPos);
+        }
+        if (res == null) {
+            throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
+        }
+        return res;
+    }
+
+    /**
+     * Equivalent to the following code:
+     * <p><blockquote><pre>
+     * int collectPos = target.type().parameterCount() - 1;
+     * Class&lt;?&gt; collectType = target.type().parameterType(collectPos);
+     * if (!collectType.isArray())  collectType = Object[].class;
+     * int collectCount = newType.parameterCount() - collectPos;
+     * MethodHandle adapter = target.asCollector(collectType, collectCount);
+     * adapter = adapter.asType(newType);
+     * return adapter;
+     * </pre></blockquote>
+     * @param target the method handle to invoke after argument collection
+     * @param newType the expected type of the new method handle
+     * @return a method handle which collects some trailing argument
+     *         into an array, before calling the original method handle
+     */
+    /*non-public*/ static
+    MethodHandle collectArguments(MethodHandle target, MethodType newType) {
+        MethodType oldType = target.type();
+        int inargs  = newType.parameterCount();
+        int outargs = oldType.parameterCount();
+        int collectPos = outargs - 1;
+        int numCollect = (inargs - collectPos);
+        if (collectPos < 0 || numCollect < 0)
+            throw newIllegalArgumentException("wrong number of arguments");
+        MethodHandle res = MethodHandleImpl.collectArguments(target, newType, collectPos, null);
+        if (res == null) {
+            throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
+        }
+        return res;
+    }
+
+    /**
+     * Produces a method handle of the requested return type which returns the given
+     * constant value every time it is invoked.
+     * <p>
+     * Before the method handle is returned, the passed-in value is converted to the requested type.
+     * If the requested type is primitive, widening primitive conversions are attempted,
+     * else reference conversions are attempted.
+     * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)},
+     * unless the type is {@code void}, in which case it is {@code identity(type)}.
+     * @param type the return type of the desired method handle
+     * @param value the value to return
+     * @return a method handle of the given return type and no arguments, which always returns the given value
+     * @throws NullPointerException if the {@code type} argument is null
+     * @throws ClassCastException if the value cannot be converted to the required return type
+     * @throws IllegalArgumentException if the given type is {@code void.class}
+     */
+    public static
+    MethodHandle constant(Class<?> type, Object value) {
+        if (type.isPrimitive()) {
+            if (type == void.class)
+                throw newIllegalArgumentException("void type");
+            Wrapper w = Wrapper.forPrimitiveType(type);
+            return identity(type).bindTo(w.convert(value, type));
+        } else {
+            return identity(type).bindTo(type.cast(value));
+        }
+    }
+
+    /**
+     * Produces a method handle which returns its sole argument when invoked.
+     * <p>The identity function for {@code void} takes no arguments and returns no values.
+     * @param type the type of the sole parameter and return value of the desired method handle
+     * @return a unary method handle which accepts and returns the given type
+     * @throws NullPointerException if the argument is null
+     * @throws IllegalArgumentException if the given type is {@code void.class}
+     */
+    public static
+    MethodHandle identity(Class<?> type) {
+        if (type == void.class)
+            throw newIllegalArgumentException("void type");
+        else if (type == Object.class)
+            return ValueConversions.identity();
+        else if (type.isPrimitive())
+            return ValueConversions.identity(Wrapper.forPrimitiveType(type));
+        else
+            return AdapterMethodHandle.makeRetypeRaw(
+                    MethodType.methodType(type, type), ValueConversions.identity());
+    }
+
+    /**
+     * Produces 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>
+     * 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 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 values the series of arguments to insert
+     * @return a method handle which inserts an additional argument,
+     *         before calling the original method handle
+     * @throws NullPointerException if the {@code target} argument or the {@code values} array is null
+     * @see MethodHandle#bindTo
+     */
+    public static
+    MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
+        int insCount = values.length;
+        MethodType oldType = target.type();
+        int outargs = oldType.parameterCount();
+        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");
+        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(result, value);
+                if (bmh != null) {
+                    result = bmh;
+                    continue;
+                }
+                // else fall through to general adapter machinery
+            }
+            result = MethodHandleImpl.bindArgument(result, pos, value);
+        }
+        return result;
+    }
+
+    /**
+     * Produces a method handle which calls the original method handle,
+     * after dropping the given argument(s) at the given position.
+     * 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</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>
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
+MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
+assertEquals(bigType, d0.type());
+assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
+     * </pre></blockquote>
+     * <p>
+     * This method is also equivalent to the following code:
+     * <p><blockquote><pre>
+     * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}(target, pos, valueTypes.toArray(new Class[0]))
+     * </pre></blockquote>
+     * @param target the method handle to invoke after the arguments are dropped
+     * @param valueTypes the type(s) of the argument(s) to drop
+     * @param pos position of first argument to drop (zero for the leftmost)
+     * @return a method handle which drops arguments of the given types,
+     *         before calling the original method handle
+     * @throws NullPointerException if the {@code target} argument is null,
+     *                              or if the {@code valueTypes} list or any of its elements is null
+     * @throws IllegalArgumentException if any of the {@code valueTypes} is {@code void.class}
+     */
+    public static
+    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.size();
+        if (pos < 0 || pos >= inargs)
+            throw newIllegalArgumentException("no argument type to remove");
+        ArrayList<Class<?>> ptypes =
+                new ArrayList<Class<?>>(oldType.parameterList());
+        ptypes.addAll(pos, valueTypes);
+        MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
+        return MethodHandleImpl.dropArguments(target, newType, pos);
+    }
+
+    /**
+     * Produces a method handle which calls the original method handle,
+     * after dropping the given argument(s) at the given position.
+     * 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</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>
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle d0 = dropArguments(cat, 0, String.class);
+assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
+MethodHandle d1 = dropArguments(cat, 1, String.class);
+assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
+MethodHandle d2 = dropArguments(cat, 2, String.class);
+assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
+MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
+     * </pre></blockquote>
+     * <p>
+     * This method is also equivalent to the following code:
+     * <p><blockquote><pre>
+     * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
+     * </pre></blockquote>
+     * @param target the method handle to invoke after the arguments are dropped
+     * @param valueTypes the type(s) of the argument(s) to drop
+     * @param pos position of first argument to drop (zero for the leftmost)
+     * @return a method handle which drops arguments of the given types,
+     *         before calling the original method handle
+     * @throws NullPointerException if the {@code target} argument is null,
+     *                              or if the {@code valueTypes} array or any of its elements is null
+     * @throws IllegalArgumentException if any of the {@code valueTypes} is {@code void.class}
+     */
+    public static
+    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
+        return dropArguments(target, pos, Arrays.asList(valueTypes));
+    }
+
+    /**
+     * Adapts 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 elements of the {@code filters} array.
+     * Null arguments in the array are ignored, and the corresponding arguments left unchanged.
+     * (If there are no non-null elements in the array, the original target is returned.)
+     * Each filter 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 elements of {@code filters}
+     * which do not correspond to argument positions in the target.
+     * <b>Example:</b>
+     * <p><blockquote><pre>
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle upcase = lookup().findVirtual(String.class,
+  "toUpperCase", methodType(String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle f0 = filterArguments(cat, 0, upcase);
+assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
+MethodHandle f1 = filterArguments(cat, 1, upcase);
+assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
+MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
+assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
+     * </pre></blockquote>
+     *
+     * @param target the method handle to invoke after arguments are filtered
+     * @param pos the position of the first argument to filter
+     * @param filters method handles to call initially on filtered arguments
+     * @return method handle which incorporates the specified argument filtering logic
+     * @throws NullPointerException if the {@code target} argument is null
+     *                              or if the {@code filters} array is null
+     * @throws IllegalArgumentException if a non-null element of {@code filters}
+     *          does not match a corresponding argument type of {@code target} as described above,
+     *          or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()}
+     */
+    public static
+    MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
+        MethodType targetType = target.type();
+        MethodHandle adapter = target;
+        MethodType adapterType = targetType;
+        int maxPos = targetType.parameterCount();
+        if (pos + filters.length > maxPos)
+            throw newIllegalArgumentException("too many filters");
+        int curPos = pos-1;  // pre-incremented
+        for (MethodHandle filter : filters) {
+            curPos += 1;
+            if (filter == null)  continue;  // ignore null elements of filters
+            MethodType filterType = filter.type();
+            if (filterType.parameterCount() != 1
+                || filterType.returnType() != targetType.parameterType(curPos))
+                throw newIllegalArgumentException("target and filter types do not match");
+            adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0));
+            adapter = MethodHandleImpl.filterArgument(adapter, curPos, filter);
+        }
+        MethodType midType = adapter.type();
+        if (midType != adapterType)
+            adapter = MethodHandleImpl.convertArguments(adapter, adapterType, midType, null);
+        return adapter;
+    }
+
+    /**
+     * Adapts a target method handle {@code target} by post-processing
+     * its return value with a unary filter function.
+     * <p>
+     * If a filter {@code F} applies to the return value of
+     * the target method handle, then {@code F} must be a method handle which
+     * takes exactly one argument.  The return type of {@code F}
+     * replaces the return type of the target
+     * in the resulting adapted method handle.
+     * The argument type of {@code F} must be identical to the
+     * return type of the target.
+     * <b>Example:</b>
+     * <p><blockquote><pre>
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle length = lookup().findVirtual(String.class,
+  "length", methodType(int.class));
+System.out.println((String) cat.invokeExact("x", "y")); // xy
+MethodHandle f0 = filterReturnValue(cat, length);
+System.out.println((int) f0.invokeExact("x", "y")); // 2
+     * </pre></blockquote>
+     * @param target the method handle to invoke before filtering the return value
+     * @param filter method handle to call on the return value
+     * @return method handle which incorporates the specified return value filtering logic
+     * @throws NullPointerException if either argument is null
+     * @throws IllegalArgumentException if {@code filter}
+     *          does not match the return type of {@code target} as described above
+     */
+    public static
+    MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
+        MethodType targetType = target.type();
+        MethodType filterType = filter.type();
+        if (filterType.parameterCount() != 1
+            || filterType.parameterType(0) != targetType.returnType())
+            throw newIllegalArgumentException("target and filter types do not match");
+        // result = fold( lambda(retval, arg...) { filter(retval) },
+        //                lambda(        arg...) { target(arg...) } )
+        // FIXME: Too many nodes here.
+        MethodHandle returner = dropArguments(filter, 1, targetType.parameterList());
+        return foldArguments(returner, target);
+    }
+
+    /**
+     * Adapts 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(MethodHandle,int,List) 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 MethodHandle#asCollector asCollector} 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 NullPointerException if either argument is null
+     * @throws IllegalArgumentException if the first argument type of
+     *          {@code target} is not the same as {@code combiner}'s return type,
+     *          or if the following 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 && !combinerType.parameterList().equals(targetType.parameterList().subList(1, foldArgs+1)))
+            ok = false;
+        if (ok && !combinerType.returnType().equals(targetType.parameterType(0)))
+            ok = false;
+        if (!ok)
+            throw misMatchedTypes("target and combiner types", targetType, combinerType);
+        MethodType newType = targetType.dropParameterTypes(0, 1);
+        return MethodHandleImpl.foldArguments(target, newType, combiner);
+    }
+
+    /**
+     * Makes a method handle which adapts a target method handle,
+     * by guarding it with a test, a boolean-valued method handle.
+     * 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, 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>
+     * boolean test(A...);
+     * T target(A...,B...);
+     * T fallback(A...,B...);
+     * T adapter(A... a,B... b) {
+     *   if (test(a...))
+     *     return target(a..., b...);
+     *   else
+     *     return fallback(a..., b...);
+     * }
+     * </pre></blockquote>
+     * Note that the test arguments ({@code a...} in the pseudocode) cannot
+     * be modified by execution of the test, and so are passed unchanged
+     * from the caller to the target or fallback as appropriate.
+     * @param test method handle used for test, must return boolean
+     * @param target method handle to call if test passes
+     * @param fallback method handle to call if test fails
+     * @return method handle which incorporates the specified if/then/else logic
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code test} does not return boolean,
+     *          or if all three method types do not match (with the return
+     *          type of {@code test} changed to match that of {@code target}).
+     */
+    public static
+    MethodHandle guardWithTest(MethodHandle test,
+                               MethodHandle target,
+                               MethodHandle fallback) {
+        MethodType gtype = test.type();
+        MethodType ttype = target.type();
+        MethodType ftype = fallback.type();
+        if (!ttype.equals(ftype))
+            throw misMatchedTypes("target and fallback types", ttype, ftype);
+        if (gtype.returnType() != boolean.class)
+            throw newIllegalArgumentException("guard type is not a predicate "+gtype);
+        List<Class<?>> targs = ttype.parameterList();
+        List<Class<?>> gargs = gtype.parameterList();
+        if (!targs.equals(gargs)) {
+            int gpc = gargs.size(), tpc = targs.size();
+            if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
+                throw misMatchedTypes("target and test types", ttype, gtype);
+            test = dropArguments(test, gpc, targs.subList(gpc, tpc));
+            gtype = test.type();
+        }
+        return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
+    }
+
+    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
+        return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
+    }
+
+    /**
+     * Makes 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 target and handler must have the same corresponding
+     * argument and return types, except that handler may omit trailing arguments
+     * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
+     * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>
+     * T target(A..., B...);
+     * T handler(ExType, A...);
+     * T adapter(A... a, B... b) {
+     *   try {
+     *     return target(a..., b...);
+     *   } catch (ExType ex) {
+     *     return handler(ex, a...);
+     *   }
+     * }
+     * </pre></blockquote>
+     * Note that the saved arguments ({@code a...} in the pseudocode) cannot
+     * be modified by execution of the target, and so are passed unchanged
+     * from the caller to the handler, if the handler is invoked.
+     * <p>
+     * The target and handler must return the same type, even if the handler
+     * always throws.  (This might happen, for instance, because the handler
+     * is simulating a {@code finally} clause).
+     * To create such a throwing handler, compose the handler creation logic
+     * with {@link #throwException throwException},
+     * in order to create a method handle of the correct return type.
+     * @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 NullPointerException if any argument is null
+     * @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 catchException(MethodHandle target,
+                                Class<? extends Throwable> exType,
+                                MethodHandle handler) {
+        MethodType ttype = target.type();
+        MethodType htype = handler.type();
+        if (htype.parameterCount() < 1 ||
+            !htype.parameterType(0).isAssignableFrom(exType))
+            throw newIllegalArgumentException("handler does not accept exception type "+exType);
+        if (htype.returnType() != ttype.returnType())
+            throw misMatchedTypes("target and handler return types", ttype, htype);
+        List<Class<?>> targs = ttype.parameterList();
+        List<Class<?>> hargs = htype.parameterList();
+        hargs = hargs.subList(1, hargs.size());  // omit leading parameter from handler
+        if (!targs.equals(hargs)) {
+            int hpc = hargs.size(), tpc = targs.size();
+            if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
+                throw misMatchedTypes("target and handler types", ttype, htype);
+            handler = dropArguments(handler, hpc, hargs.subList(hpc, tpc));
+            htype = handler.type();
+        }
+        return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
+    }
+
+    /**
+     * Produces 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.
+     * @return method handle which can throw the given exceptions
+     * @throws NullPointerException if either argument is null
+     */
+    public static
+    MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
+        return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
+    }
+
+    /**
+     * Produces an instance of the given single-method interface which redirects
+     * its calls to the given method handle.
+     * <p>
+     * A single-method interface is an interface which declares a unique method.
+     * When determining the unique method of a single-method interface,
+     * the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
+     * are disregarded.  For example, {@link java.util.Comparator} is a single-method interface,
+     * even though it re-declares the {@code Object.equals} method.
+     * <p>
+     * The type must be public.  No additional access checks are performed.
+     * <p>
+     * The resulting instance of the required type will respond to
+     * invocation of the type's single abstract method by calling
+     * the given {@code target} on the incoming arguments,
+     * and returning or throwing whatever the {@code target}
+     * returns or throws.  The invocation will be as if by
+     * {@code target.invokeGeneric}.
+     * The target's type will be checked before the
+     * instance is created, as if by a call to {@code asType},
+     * which may result in a {@code WrongMethodTypeException}.
+     * <p>
+     * The wrapper instance will implement the requested interface
+     * and its super-types, but no other single-method interfaces.
+     * This means that the instance will not unexpectedly
+     * pass an {@code instanceof} test for any unrequested type.
+     * <p style="font-size:smaller;">
+     * <em>Implementation Note:</em>
+     * Therefore, each instance must implement a unique single-method interface.
+     * Implementations may not bundle together
+     * multiple single-method interfaces onto single implementation classes
+     * in the style of {@link java.awt.AWTEventMulticaster}.
+     * <p>
+     * The method handle may throw an <em>undeclared exception</em>,
+     * which means any checked exception (or other checked throwable)
+     * not declared by the requested type's single abstract method.
+     * If this happens, the throwable will be wrapped in an instance of
+     * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
+     * and thrown in that wrapped form.
+     * <p>
+     * Like {@link java.lang.Integer#valueOf Integer.valueOf},
+     * {@code asInstance} is a factory method whose results are defined
+     * by their behavior.
+     * It is not guaranteed to return a new instance for every call.
+     * <p>
+     * Because of the possibility of {@linkplain java.lang.reflect.Method#isBridge bridge methods}
+     * and other corner cases, the interface may also have several abstract methods
+     * with the same name but having distinct descriptors (types of returns and parameters).
+     * In this case, all the methods are bound in common to the one given {@code target}.
+     * The type check and effective {@code asType} conversion is applied to each
+     * method type descriptor, and all abstract methods are bound to the {@code target} in common.
+     * Beyond this type check, no further checks are made to determine that the
+     * abstract methods are related in any way.
+     * <p>
+     * Future versions of this API may accept additional types,
+     * such as abstract classes with single abstract methods.
+     * Future versions of this API may also equip wrapper instances
+     * with one or more additional public "marker" interfaces.
+     *
+     * @param target the method handle to invoke from the wrapper
+     * @param smType the desired type of the wrapper, a single-method interface
+     * @return a correctly-typed wrapper for the given {@code target}
+     * @throws NullPointerException if either argument is null
+     * @throws IllegalArgumentException if the {@code smType} is not a
+     *         valid argument to this method
+     * @throws WrongMethodTypeException if the {@code target} cannot
+     *         be converted to the type required by the requested interface
+     */
+    // Other notes to implementors:
+    // <p>
+    // No stable mapping is promised between the single-method interface and
+    // the implementation class C.  Over time, several implementation
+    // classes might be used for the same type.
+    // <p>
+    // If the implementation is able
+    // to prove that a wrapper of the required type
+    // has already been created for a given
+    // method handle, or for another method handle with the
+    // same behavior, the implementation may return that wrapper in place of
+    // a new wrapper.
+    // <p>
+    // This method is designed to apply to common use cases
+    // where a single method handle must interoperate with
+    // an interface that implements a function-like
+    // API.  Additional variations, such as single-abstract-method classes with
+    // private constructors, or interfaces with multiple but related
+    // entry points, must be covered by hand-written or automatically
+    // generated adapter classes.
+    //
+    public static
+    <T> T asInstance(final MethodHandle target, final Class<T> smType) {
+        // POC implementation only; violates the above contract several ways
+        final Method sm = getSingleMethod(smType);
+        if (sm == null)
+            throw new IllegalArgumentException("not a single-method interface: "+smType.getName());
+        MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
+        MethodHandle checkTarget = target.asType(smMT);  // make throw WMT
+        checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
+        final MethodHandle vaTarget = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
+        return smType.cast(Proxy.newProxyInstance(
+                smType.getClassLoader(),
+                new Class[]{ smType, WrapperInstance.class },
+                new InvocationHandler() {
+                    private Object getArg(String name) {
+                        if ((Object)name == "getWrapperInstanceTarget")  return target;
+                        if ((Object)name == "getWrapperInstanceType")    return smType;
+                        throw new AssertionError();
+                    }
+                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                        if (method.getDeclaringClass() == WrapperInstance.class)
+                            return getArg(method.getName());
+                        if (method.equals(sm))
+                            return vaTarget.invokeExact(args);
+                        if (isObjectMethod(method))
+                            return callObjectMethod(this, method, args);
+                        throw new InternalError();
+                    }
+                }));
+    }
+
+    /**
+     * Determines if the given object was produced by a call to {@link #asInstance asInstance}.
+     * @param x any reference
+     * @return true if the reference is not null and points to an object produced by {@code asInstance}
+     */
+    public static
+    boolean isWrapperInstance(Object x) {
+        return x instanceof WrapperInstance;
+    }
+
+    private static WrapperInstance asWrapperInstance(Object x) {
+        try {
+            if (x != null)
+                return (WrapperInstance) x;
+        } catch (ClassCastException ex) {
+        }
+        throw new IllegalArgumentException("not a wrapper instance");
+    }
+
+    /**
+     * Produces or recovers a target method handle which is behaviorally
+     * equivalent to the unique method of this wrapper instance.
+     * The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
+     * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
+     * @param x any reference
+     * @return a method handle implementing the unique method
+     * @throws IllegalArgumentException if the reference x is not to a wrapper instance
+     */
+    public static
+    MethodHandle wrapperInstanceTarget(Object x) {
+        return asWrapperInstance(x).getWrapperInstanceTarget();
+    }
+
+    /**
+     * Recovers the unique single-method interface type for which this wrapper instance was created.
+     * The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
+     * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
+     * @param x any reference
+     * @return the single-method interface type for which the wrapper was created
+     * @throws IllegalArgumentException if the reference x is not to a wrapper instance
+     */
+    public static
+    Class<?> wrapperInstanceType(Object x) {
+        return asWrapperInstance(x).getWrapperInstanceType();
+    }
+
+    private static
+    boolean isObjectMethod(Method m) {
+        switch (m.getName()) {
+        case "toString":
+            return (m.getReturnType() == String.class
+                    && m.getParameterTypes().length == 0);
+        case "hashCode":
+            return (m.getReturnType() == int.class
+                    && m.getParameterTypes().length == 0);
+        case "equals":
+            return (m.getReturnType() == boolean.class
+                    && m.getParameterTypes().length == 1
+                    && m.getParameterTypes()[0] == Object.class);
+        }
+        return false;
+    }
+
+    private static
+    Object callObjectMethod(Object self, Method m, Object[] args) {
+        assert(isObjectMethod(m)) : m;
+        switch (m.getName()) {
+        case "toString":
+            return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
+        case "hashCode":
+            return System.identityHashCode(self);
+        case "equals":
+            return (self == args[0]);
+        }
+        return null;
+    }
+
+    private static
+    Method getSingleMethod(Class<?> smType) {
+        Method sm = null;
+        for (Method m : smType.getMethods()) {
+            int mod = m.getModifiers();
+            if (Modifier.isAbstract(mod)) {
+                if (sm != null && !isObjectMethod(sm))
+                    return null;  // too many abstract methods
+                sm = m;
+            }
+        }
+        if (!smType.isInterface() && getSingleConstructor(smType) == null)
+            return null;  // wrong kind of constructor
+        return sm;
+    }
+
+    private static
+    Constructor getSingleConstructor(Class<?> smType) {
+        for (Constructor c : smType.getDeclaredConstructors()) {
+            if (c.getParameterTypes().length == 0) {
+                int mod = c.getModifiers();
+                if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
+                    return c;
+            }
+        }
+        return null;
+    }
+
+    /*non-public*/
+    static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
+        return MethodHandleImpl.asVarargsCollector(target, arrayType);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import sun.invoke.util.BytecodeDescriptor;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * A method type represents the arguments and return type accepted and
+ * returned by a method handle, or the arguments and return type passed
+ * and expected  by a method handle caller.  Method types must be properly
+ * matched between a method handle and all its callers,
+ * and the JVM's operations enforce this matching at, specifically
+ * during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact}
+ * and {@link MethodHandle#invokeGeneric MethodHandle.invokeGeneric}, and during execution
+ * of {@code invokedynamic} instructions.
+ * <p>
+ * The structure is a return type accompanied by any number of parameter types.
+ * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
+ * (For ease of exposition, we treat {@code void} as if it were a type.
+ * In fact, it denotes the absence of a return type.)
+ * <p>
+ * All instances of {@code MethodType} are immutable.
+ * Two instances are completely interchangeable if they compare equal.
+ * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
+ * <p>
+ * This type can be created only by factory methods.
+ * All factory methods may cache values, though caching is not guaranteed.
+ * Some factory methods are static, while others are virtual methods which
+ * modify precursor method types, e.g., by changing a selected parameter.
+ * <p>
+ * Factory methods which operate on groups of parameter types
+ * are systematically presented in two versions, so that both Java arrays and
+ * Java lists can be used to work with groups of parameter types.
+ * The query methods {@code parameterArray} and {@code parameterList}
+ * also provide a choice between arrays and lists.
+ * <p>
+ * {@code MethodType} objects are sometimes derived from bytecode instructions
+ * such as {@code invokedynamic}, specifically from the type descriptor strings associated
+ * with the instructions in a class file's constant pool.
+ * <p>
+ * Like classes and strings, method types can also be represented directly
+ * in a class file's constant pool as constants.
+ * A method type may be loaded by an {@code ldc} instruction which refers
+ * to a suitable {@code CONSTANT_MethodType} constant pool entry.
+ * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
+ * For more details, see the <a href="package-summary.html#mtcon">package summary</a>.
+ * <p>
+ * When the JVM materializes a {@code MethodType} from a descriptor string,
+ * all classes named in the descriptor must be accessible, and will be loaded.
+ * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
+ * This loading may occur at any time before the {@code MethodType} object is first derived.
+ * @author John Rose, JSR 292 EG
+ */
+public final
+class MethodType implements java.io.Serializable {
+    private static final long serialVersionUID = 292L;  // {rtype, {ptype...}}
+
+    // The rtype and ptypes fields define the structural identity of the method type:
+    private final Class<?>   rtype;
+    private final Class<?>[] ptypes;
+
+    // The remaining fields are caches of various sorts:
+    private MethodTypeForm form; // erased form, plus cached data about primitives
+    private MethodType wrapAlt;  // alternative wrapped/unwrapped version
+    private Invokers invokers;   // cache of handy higher-order adapters
+
+    /**
+     * Check the given parameters for validity and store them into the final fields.
+     */
+    private MethodType(Class<?> rtype, Class<?>[] ptypes) {
+        checkRtype(rtype);
+        checkPtypes(ptypes);
+        this.rtype = rtype;
+        this.ptypes = ptypes;
+    }
+
+    /*trusted*/ MethodTypeForm form() { return form; }
+    /*trusted*/ Class<?> rtype() { return rtype; }
+    /*trusted*/ Class<?>[] ptypes() { return ptypes; }
+
+    private static void checkRtype(Class<?> rtype) {
+        rtype.equals(rtype);  // null check
+    }
+    private static int checkPtype(Class<?> ptype) {
+        ptype.getClass();  //NPE
+        if (ptype == void.class)
+            throw newIllegalArgumentException("parameter type cannot be void");
+        if (ptype == double.class || ptype == long.class)  return 1;
+        return 0;
+    }
+    /** Return number of extra slots (count of long/double args). */
+    private static int checkPtypes(Class<?>[] ptypes) {
+        int slots = 0;
+        for (Class<?> ptype : ptypes) {
+            slots += checkPtype(ptype);
+        }
+        checkSlotCount(ptypes.length + slots);
+        return slots;
+    }
+    private static void checkSlotCount(int count) {
+        if ((count & 0xFF) != count)
+            throw newIllegalArgumentException("bad parameter count "+count);
+    }
+    private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num) {
+        if (num instanceof Integer)  num = "bad index: "+num;
+        return new IndexOutOfBoundsException(num.toString());
+    }
+
+    static final HashMap<MethodType,MethodType> internTable
+            = new HashMap<MethodType, MethodType>();
+
+    static final Class<?>[] NO_PTYPES = {};
+
+    /**
+     * Finds or creates an instance of the given method type.
+     * @param rtype  the return type
+     * @param ptypes the parameter types
+     * @return a method type with the given components
+     * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
+     * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
+     */
+    public static
+    MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
+        return makeImpl(rtype, ptypes, false);
+    }
+
+    /**
+     * Finds or creates a method type with the given components.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * @return a method type with the given components
+     * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
+     * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
+     */
+    public static
+    MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) {
+        boolean notrust = false;  // random List impl. could return evil ptypes array
+        return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust);
+    }
+
+    /**
+     * Finds or creates a method type with the given components.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * The leading parameter type is prepended to the remaining array.
+     * @return a method type with the given components
+     * @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null
+     * @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class}
+     */
+    public static
+    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);
+    }
+
+    /**
+     * Finds or creates a method type with the given components.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * The resulting method has no parameter types.
+     * @return a method type with the given return value
+     * @throws NullPointerException if {@code rtype} is null
+     */
+    public static
+    MethodType methodType(Class<?> rtype) {
+        return makeImpl(rtype, NO_PTYPES, true);
+    }
+
+    /**
+     * Finds or creates a method type with the given components.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * The resulting method has the single given parameter type.
+     * @return a method type with the given return value and parameter type
+     * @throws NullPointerException if {@code rtype} or {@code ptype0} is null
+     * @throws IllegalArgumentException if {@code ptype0} is {@code void.class}
+     */
+    public static
+    MethodType methodType(Class<?> rtype, Class<?> ptype0) {
+        return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
+    }
+
+    /**
+     * Finds or creates a method type with the given components.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * The resulting method has the same parameter types as {@code ptypes},
+     * and the specified return type.
+     * @throws NullPointerException if {@code rtype} or {@code ptypes} is null
+     */
+    public static
+    MethodType methodType(Class<?> rtype, MethodType ptypes) {
+        return makeImpl(rtype, ptypes.ptypes, true);
+    }
+
+    /**
+     * Sole factory method to find or create an interned method type.
+     * @param rtype desired return type
+     * @param ptypes desired parameter types
+     * @param trusted whether the ptypes can be used without cloning
+     * @return the unique method type of the desired structure
+     */
+    /*trusted*/ static
+    MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
+        if (ptypes == null || ptypes.length == 0) {
+            ptypes = NO_PTYPES; trusted = true;
+        }
+        MethodType mt1 = new MethodType(rtype, ptypes);
+        MethodType mt0;
+        synchronized (internTable) {
+            mt0 = internTable.get(mt1);
+            if (mt0 != null)
+                return mt0;
+        }
+        if (!trusted)
+            // defensively copy the array passed in by the user
+            mt1 = new MethodType(rtype, ptypes.clone());
+        // promote the object to the Real Thing, and reprobe
+        MethodTypeForm form = MethodTypeForm.findForm(mt1);
+        mt1.form = form;
+        if (form.erasedType == mt1) {
+            // This is a principal (erased) type; show it to the JVM.
+            MethodHandleNatives.init(mt1);
+        }
+        synchronized (internTable) {
+            mt0 = internTable.get(mt1);
+            if (mt0 != null)
+                return mt0;
+            internTable.put(mt1, mt1);
+        }
+        return mt1;
+    }
+
+    private static final MethodType[] objectOnlyTypes = new MethodType[20];
+
+    /**
+     * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * 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 {@code Object[]}
+     * @return a totally generic method type, given only its count of parameters and varargs
+     * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
+     * @see #genericMethodType(int)
+     */
+    public static
+    MethodType genericMethodType(int objectArgCount, boolean varargs) {
+        MethodType mt;
+        checkSlotCount(objectArgCount);
+        int ivarargs = (!varargs ? 0 : 1);
+        int ootIndex = objectArgCount*2 + ivarargs;
+        if (ootIndex < objectOnlyTypes.length) {
+            mt = objectOnlyTypes[ootIndex];
+            if (mt != null)  return mt;
+        }
+        Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
+        Arrays.fill(ptypes, Object.class);
+        if (ivarargs != 0)  ptypes[objectArgCount] = Object[].class;
+        mt = makeImpl(Object.class, ptypes, true);
+        if (ootIndex < objectOnlyTypes.length) {
+            objectOnlyTypes[ootIndex] = mt;     // cache it here also!
+        }
+        return mt;
+    }
+
+    /**
+     * Finds or creates a method type whose components are all {@code Object}.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * 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
+     * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
+     * @see #genericMethodType(int, boolean)
+     */
+    public static
+    MethodType genericMethodType(int objectArgCount) {
+        return genericMethodType(objectArgCount, false);
+    }
+
+    /**
+     * Finds or creates a method type with a single different parameter type.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * @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
+     * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
+     * @throws IllegalArgumentException if {@code nptype} is {@code void.class}
+     * @throws NullPointerException if {@code nptype} is null
+     */
+    public MethodType changeParameterType(int num, Class<?> nptype) {
+        if (parameterType(num) == nptype)  return this;
+        checkPtype(nptype);
+        Class<?>[] nptypes = ptypes.clone();
+        nptypes[num] = nptype;
+        return makeImpl(rtype, nptypes, true);
+    }
+
+    /**
+     * Finds or creates a method type with additional parameter types.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * @param num    the position (zero-based) of the inserted parameter type(s)
+     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
+     * @return the same type, except with the selected parameter(s) inserted
+     * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
+     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
+     *                                  or if the resulting method type would have more than 255 parameter slots
+     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
+     */
+    public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
+        int len = ptypes.length;
+        if (num < 0 || num > len)
+            throw newIndexOutOfBoundsException(num);
+        int ins = checkPtypes(ptypesToInsert);
+        checkSlotCount(parameterSlotCount() + ptypesToInsert.length + ins);
+        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);
+    }
+
+    /**
+     * Finds or creates a method type with additional parameter types.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
+     * @return the same type, except with the selected parameter(s) appended
+     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
+     *                                  or if the resulting method type would have more than 255 parameter slots
+     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
+     */
+    public MethodType appendParameterTypes(Class<?>... ptypesToInsert) {
+        return insertParameterTypes(parameterCount(), ptypesToInsert);
+    }
+
+    /**
+     * Finds or creates a method type with additional parameter types.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * @param num    the position (zero-based) of the inserted parameter type(s)
+     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
+     * @return the same type, except with the selected parameter(s) inserted
+     * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
+     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
+     *                                  or if the resulting method type would have more than 255 parameter slots
+     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
+     */
+    public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
+        return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES));
+    }
+
+    /**
+     * Finds or creates a method type with additional parameter types.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
+     * @return the same type, except with the selected parameter(s) appended
+     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
+     *                                  or if the resulting method type would have more than 255 parameter slots
+     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
+     */
+    public MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) {
+        return insertParameterTypes(parameterCount(), ptypesToInsert);
+    }
+
+    /**
+     * Finds or creates a method type with some parameter types omitted.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * @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
+     * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
+     *                                  or if {@code end} is negative or greater than {@code parameterCount()}
+     *                                  or if {@code start} is greater than {@code end}
+     */
+    public MethodType dropParameterTypes(int start, int end) {
+        int len = ptypes.length;
+        if (!(0 <= start && start <= end && end <= len))
+            throw newIndexOutOfBoundsException("start="+start+" end="+end);
+        if (start == end)  return this;
+        Class<?>[] nptypes;
+        if (start == 0) {
+            if (end == len) {
+                // drop all parameters
+                nptypes = NO_PTYPES;
+            } else {
+                // drop initial parameter(s)
+                nptypes = Arrays.copyOfRange(ptypes, end, len);
+            }
+        } else {
+            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);
+    }
+
+    /**
+     * Finds or creates a method type with a different return type.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * @param nrtype a return parameter type to replace the old one with
+     * @return the same type, except with the return type change
+     * @throws NullPointerException if {@code nrtype} is null
+     */
+    public MethodType changeReturnType(Class<?> nrtype) {
+        if (returnType() == nrtype)  return this;
+        return makeImpl(nrtype, ptypes, true);
+    }
+
+    /**
+     * Reports 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() {
+        return form.hasPrimitives();
+    }
+
+    /**
+     * Reports 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;
+    }
+
+    /**
+     * Erases all reference types to {@code Object}.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * 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();
+    }
+
+    /**
+     * Converts all types, both reference and primitive, to {@code Object}.
+     * Convenience method for {@link #genericMethodType(int) genericMethodType}.
+     * 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 genericMethodType(parameterCount());
+    }
+
+    /**
+     * Converts all primitive types to their corresponding wrapper types.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * 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;
+    }
+
+    /**
+     * Converts all wrapper types to their corresponding primitive types.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * 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
+     */
+    public MethodType unwrap() {
+        MethodType noprims = !hasPrimitives() ? this : wrapWithPrims(this);
+        return unwrapWithNoPrims(noprims);
+    }
+
+    private static MethodType wrapWithPrims(MethodType pt) {
+        assert(pt.hasPrimitives());
+        MethodType wt = pt.wrapAlt;
+        if (wt == null) {
+            // fill in lazily
+            wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP);
+            assert(wt != null);
+            pt.wrapAlt = wt;
+        }
+        return wt;
+    }
+
+    private static MethodType unwrapWithNoPrims(MethodType wt) {
+        assert(!wt.hasPrimitives());
+        MethodType uwt = wt.wrapAlt;
+        if (uwt == null) {
+            // fill in lazily
+            uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP);
+            if (uwt == null)
+                uwt = wt;    // type has no wrappers or prims at all
+            wt.wrapAlt = uwt;
+        }
+        return uwt;
+    }
+
+    /**
+     * Returns the parameter type at the specified index, within this method type.
+     * @param num the index (zero-based) of the desired parameter type
+     * @return the selected parameter type
+     * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
+     */
+    public Class<?> parameterType(int num) {
+        return ptypes[num];
+    }
+    /**
+     * Returns the number of parameter types in this method type.
+     * @return the number of parameter types
+     */
+    public int parameterCount() {
+        return ptypes.length;
+    }
+    /**
+     * Returns the return type of this method type.
+     * @return the return type
+     */
+    public Class<?> returnType() {
+        return rtype;
+    }
+
+    /**
+     * Presents the parameter types as a list (a convenience method).
+     * The list will be immutable.
+     * @return the parameter types (as an immutable list)
+     */
+    public List<Class<?>> parameterList() {
+        return Collections.unmodifiableList(Arrays.asList(ptypes));
+    }
+
+    /**
+     * Presents the parameter types as an array (a convenience method).
+     * 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() {
+        return ptypes.clone();
+    }
+
+    /**
+     * Compares the specified object with this type for equality.
+     * That is, it returns <tt>true</tt> if and only if the specified object
+     * is also a method type with exactly the same parameters and return type.
+     * @param x object to compare
+     * @see Object#equals(Object)
+     */
+    @Override
+    public boolean equals(Object x) {
+        return this == x || x instanceof MethodType && equals((MethodType)x);
+    }
+
+    private boolean equals(MethodType that) {
+        return this.rtype == that.rtype
+            && Arrays.equals(this.ptypes, that.ptypes);
+    }
+
+    /**
+     * Returns the hash code value for this method type.
+     * It is defined to be the same as the hashcode of a List
+     * whose elements are the return type followed by the
+     * parameter types.
+     * @return the hash code value for this method type
+     * @see Object#hashCode()
+     * @see #equals(Object)
+     * @see List#hashCode()
+     */
+    @Override
+    public int hashCode() {
+      int hashCode = 31 + rtype.hashCode();
+      for (Class<?> ptype : ptypes)
+          hashCode = 31*hashCode + ptype.hashCode();
+      return hashCode;
+    }
+
+    /**
+     * Returns a string representation of the method type,
+     * of the form {@code "(PT0,PT1...)RT"}.
+     * The string representation of a method type is a
+     * parenthesis enclosed, comma separated list of type names,
+     * followed immediately by the return type.
+     * <p>
+     * Each type is represented by its
+     * {@link java.lang.Class#getSimpleName simple name}.
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("(");
+        for (int i = 0; i < ptypes.length; i++) {
+            if (i > 0)  sb.append(",");
+            sb.append(ptypes[i].getSimpleName());
+        }
+        sb.append(")");
+        sb.append(rtype.getSimpleName());
+        return sb.toString();
+    }
+
+    /// Queries which have to do with the bytecode architecture
+
+    /** Reports the number of JVM stack slots required to invoke a method
+     * of this type.  Note that (for historical reasons) the JVM requires
+     * a second stack slot to pass long and double arguments.
+     * So this method returns {@link #parameterCount() parameterCount} plus the
+     * number of long and double parameters (if any).
+     * <p>
+     * This method is included for the benfit of applications that must
+     * generate bytecodes that process method handles and invokedynamic.
+     * @return the number of JVM stack slots for this type's parameters
+     */
+    /*non-public*/ int parameterSlotCount() {
+        return form.parameterSlotCount();
+    }
+
+    /*non-public*/ Invokers invokers() {
+        Invokers inv = invokers;
+        if (inv != null)  return inv;
+        invokers = inv = new Invokers(this);
+        return inv;
+    }
+
+    /** Reports the 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
+     * according to their trailing edge.  Thus, to obtain the depth
+     * in the outgoing call stack of parameter {@code N}, obtain
+     * the {@code parameterSlotDepth} of its trailing edge
+     * at position {@code N+1}.
+     * <p>
+     * Parameters of type {@code long} and {@code double} occupy
+     * two stack slots (for historical reasons) and all others occupy one.
+     * Therefore, the number returned is the number of arguments
+     * <em>including</em> and <em>after</em> the given parameter,
+     * <em>plus</em> the number of long or double arguments
+     * at or after after the argument for the given parameter.
+     * <p>
+     * This method is included for the benfit of applications that must
+     * generate bytecodes that process method handles and invokedynamic.
+     * @param num an index (zero-based, inclusive) within the parameter types
+     * @return the index of the (shallowest) JVM stack slot transmitting the
+     *         given parameter
+     * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
+     */
+    /*non-public*/ int parameterSlotDepth(int num) {
+        if (num < 0 || num > ptypes.length)
+            parameterType(num);  // force a range check
+        return form.parameterToArgSlot(num-1);
+    }
+
+    /** Reports the number of JVM stack slots required to receive a return value
+     * from a method of this type.
+     * If the {@link #returnType() return type} is void, it will be zero,
+     * else if the return type is long or double, it will be two, else one.
+     * <p>
+     * This method is included for the benfit of applications that must
+     * generate bytecodes that process method handles and invokedynamic.
+     * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
+     * Will be removed for PFD.
+     */
+    /*non-public*/ int returnSlotCount() {
+        return form.returnSlotCount();
+    }
+
+    /**
+     * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * Any class or interface name embedded in the descriptor string
+     * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
+     * on the given loader (or if it is null, on the system class loader).
+     * <p>
+     * Note that it is possible to encounter method types which cannot be
+     * constructed by this method, because their component types are
+     * not all reachable from a common class loader.
+     * <p>
+     * This method is included for the benfit of applications that must
+     * generate bytecodes that process method handles and {@code invokedynamic}.
+     * @param descriptor a bytecode-level type descriptor string "(T...)T"
+     * @param loader the class loader in which to look up the types
+     * @return a method type matching the bytecode-level type descriptor
+     * @throws IllegalArgumentException if the string is not well-formed
+     * @throws TypeNotPresentException if a named type cannot be found
+     */
+    public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
+        throws IllegalArgumentException, TypeNotPresentException
+    {
+        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);
+    }
+
+    /**
+     * Produces a bytecode descriptor representation of the method type.
+     * <p>
+     * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
+     * Two distinct classes which share a common name but have different class loaders
+     * will appear identical when viewed within descriptor strings.
+     * <p>
+     * This method is included for the benfit of applications that must
+     * generate bytecodes that process method handles and {@code invokedynamic}.
+     * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
+     * because the latter requires a suitable class loader argument.
+     * @return the bytecode type descriptor representation
+     */
+    public String toMethodDescriptorString() {
+        return BytecodeDescriptor.unparse(this);
+    }
+
+    /// Serialization.
+
+    /**
+     * There are no serializable fields for {@code MethodType}.
+     */
+    private static final java.io.ObjectStreamField[] serialPersistentFields = { };
+
+    /**
+     * Save the {@code MethodType} instance to a stream.
+     *
+     * @serialData
+     * For portability, the serialized format does not refer to named fields.
+     * Instead, the return type and parameter type arrays are written directly
+     * from the {@code writeObject} method, using two calls to {@code s.writeObject}
+     * as follows:
+     * <blockquote><pre>
+s.writeObject(this.returnType());
+s.writeObject(this.parameterArray());
+     * </pre></blockquote>
+     * <p>
+     * The deserialized field values are checked as if they were
+     * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
+     * For example, null values, or {@code void} parameter types,
+     * will lead to exceptions during deserialization.
+     * @param the stream to write the object to
+     */
+    private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
+        s.defaultWriteObject();  // requires serialPersistentFields to be an empty array
+        s.writeObject(returnType());
+        s.writeObject(parameterArray());
+    }
+
+    /**
+     * Reconstitute the {@code MethodType} instance from a stream (that is,
+     * deserialize it).
+     * This instance is a scratch object with bogus final fields.
+     * It provides the parameters to the factory method called by
+     * {@link #readResolve readResolve}.
+     * After that call it is discarded.
+     * @param the stream to read the object from
+     * @see #MethodType()
+     * @see #readResolve
+     * @see #writeObject
+     */
+    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
+        s.defaultReadObject();  // requires serialPersistentFields to be an empty array
+
+        Class<?>   returnType     = (Class<?>)   s.readObject();
+        Class<?>[] parameterArray = (Class<?>[]) s.readObject();
+
+        // Probably this object will never escape, but let's check
+        // the field values now, just to be sure.
+        checkRtype(returnType);
+        checkPtypes(parameterArray);
+
+        parameterArray = parameterArray.clone();  // make sure it is unshared
+        MethodType_init(returnType, parameterArray);
+    }
+
+    /**
+     * For serialization only.
+     * Sets the final fields to null, pending {@code Unsafe.putObject}.
+     */
+    private MethodType() {
+        this.rtype = null;
+        this.ptypes = null;
+    }
+    private void MethodType_init(Class<?> rtype, Class<?>[] ptypes) {
+        // In order to communicate these values to readResolve, we must
+        // store them into the implementation-specific final fields.
+        checkRtype(rtype);
+        checkPtypes(ptypes);
+        unsafe.putObject(this, rtypeOffset, rtype);
+        unsafe.putObject(this, ptypesOffset, ptypes);
+    }
+
+    // Support for resetting final fields while deserializing
+    private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+    private static final long rtypeOffset, ptypesOffset;
+    static {
+        try {
+            rtypeOffset = unsafe.objectFieldOffset
+                (MethodType.class.getDeclaredField("rtype"));
+            ptypesOffset = unsafe.objectFieldOffset
+                (MethodType.class.getDeclaredField("ptypes"));
+        } catch (Exception ex) {
+            throw new Error(ex);
+        }
+    }
+
+    /**
+     * Resolves and initializes a {@code MethodType} object
+     * after serialization.
+     * @return the fully initialized {@code MethodType} object
+     */
+    private Object readResolve() {
+        // Do not use a trusted path for deserialization:
+        //return makeImpl(rtype, ptypes, true);
+        // Verify all operands, and make sure ptypes is unshared:
+        return methodType(rtype, ptypes);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * Shared information for a group of method types, which differ
+ * only by reference types, and therefore share a common erasure
+ * and wrapping.
+ * <p>
+ * For an empirical discussion of the structure of method types,
+ * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
+ * the thread "Avoiding Boxing" on jvm-languages</a>.
+ * There are approximately 2000 distinct erased method types in the JDK.
+ * There are a little over 10 times that number of unerased types.
+ * No more than half of these are likely to be loaded at once.
+ * @author John Rose
+ */
+class MethodTypeForm {
+    final int[] argToSlotTable, slotToArgTable;
+    final long argCounts;               // packed slot & value counts
+    final long primCounts;              // packed prim & double counts
+    final int vmslots;                  // total number of parameter slots
+    final MethodType erasedType;        // the canonical erasure
+
+    /*lazy*/ MethodType primsAsBoxes;   // replace prims by wrappers
+    /*lazy*/ MethodType primArgsAsBoxes; // wrap args only; make raw return
+    /*lazy*/ MethodType primsAsInts;    // replace prims by int/long
+    /*lazy*/ MethodType primsAsLongs;   // replace prims by long
+    /*lazy*/ MethodType primsAtEnd;     // reorder primitives to the end
+
+    // 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*/ MethodHandle genericInvoker; // hook for invokeGeneric
+
+    public MethodType erasedType() {
+        return erasedType;
+    }
+
+    protected MethodTypeForm(MethodType erasedType) {
+        this.erasedType = erasedType;
+
+        Class<?>[] ptypes = erasedType.ptypes();
+        int ptypeCount = ptypes.length;
+        int pslotCount = ptypeCount;            // temp. estimate
+        int rtypeCount = 1;                     // temp. estimate
+        int rslotCount = 1;                     // temp. estimate
+
+        int[] argToSlotTab = null, slotToArgTab = null;
+
+        // Walk the argument types, looking for primitives.
+        int pac = 0, lac = 0, prc = 0, lrc = 0;
+        Class<?> epts[] = ptypes;
+        for (int i = 0; i < epts.length; i++) {
+            Class<?> pt = epts[i];
+            if (pt != Object.class) {
+                assert(pt.isPrimitive());
+                ++pac;
+                if (hasTwoArgSlots(pt))  ++lac;
+            }
+        }
+        pslotCount += lac;                  // #slots = #args + #longs
+        Class<?> rt = erasedType.returnType();
+        if (rt != Object.class) {
+            ++prc;          // even void.class counts as a prim here
+            if (hasTwoArgSlots(rt))  ++lrc;
+            // adjust #slots, #args
+            if (rt == void.class)
+                rtypeCount = rslotCount = 0;
+            else
+                rslotCount += lrc;
+        }
+        if (lac != 0) {
+            int slot = ptypeCount + lac;
+            slotToArgTab = new int[slot+1];
+            argToSlotTab = new int[1+ptypeCount];
+            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
+            for (int i = 0; i < epts.length; i++) {
+                Class<?> pt = epts[i];
+                if (hasTwoArgSlots(pt))  --slot;
+                --slot;
+                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
+                argToSlotTab[1+i]  = slot;
+            }
+            assert(slot == 0);  // filled the table
+        }
+        this.primCounts = pack(lrc, prc, lac, pac);
+        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
+        if (slotToArgTab == null) {
+            int slot = ptypeCount; // first arg is deepest in stack
+            slotToArgTab = new int[slot+1];
+            argToSlotTab = new int[1+ptypeCount];
+            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
+            for (int i = 0; i < ptypeCount; i++) {
+                --slot;
+                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
+                argToSlotTab[1+i]  = slot;
+            }
+        }
+        this.argToSlotTable = argToSlotTab;
+        this.slotToArgTable = slotToArgTab;
+
+        if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
+
+        // send a few bits down to the JVM:
+        this.vmslots = parameterSlotCount();
+
+        // short circuit some no-op canonicalizations:
+        if (!hasPrimitives()) {
+            primsAsBoxes = erasedType;
+            primArgsAsBoxes = erasedType;
+            primsAsInts  = erasedType;
+            primsAsLongs = erasedType;
+            primsAtEnd   = erasedType;
+        }
+    }
+
+    /** Turn all primitive types to corresponding wrapper types.
+     */
+    public MethodType primsAsBoxes() {
+        MethodType ct = primsAsBoxes;
+        if (ct != null)  return ct;
+        MethodType t = erasedType;
+        ct = canonicalize(erasedType, WRAP, WRAP);
+        if (ct == null)  ct = t;  // no prims to box
+        return primsAsBoxes = ct;
+    }
+
+    /** Turn all primitive argument types to corresponding wrapper types.
+     *  Subword and void return types are promoted to int.
+     */
+    public MethodType primArgsAsBoxes() {
+        MethodType ct = primArgsAsBoxes;
+        if (ct != null)  return ct;
+        MethodType t = erasedType;
+        ct = canonicalize(erasedType, RAW_RETURN, WRAP);
+        if (ct == null)  ct = t;  // no prims to box
+        return primArgsAsBoxes = ct;
+    }
+
+    /** Turn all primitive types to either int or long.
+     *  Floating point return types are not changed, because
+     *  they may require special calling sequences.
+     *  A void return value is turned to int.
+     */
+    public MethodType primsAsInts() {
+        MethodType ct = primsAsInts;
+        if (ct != null)  return ct;
+        MethodType t = erasedType;
+        ct = canonicalize(t, RAW_RETURN, INTS);
+        if (ct == null)  ct = t;  // no prims to int-ify
+        return primsAsInts = ct;
+    }
+
+    /** Turn all primitive types to either int or long.
+     *  Floating point return types are not changed, because
+     *  they may require special calling sequences.
+     *  A void return value is turned to int.
+     */
+    public MethodType primsAsLongs() {
+        MethodType ct = primsAsLongs;
+        if (ct != null)  return ct;
+        MethodType t = erasedType;
+        ct = canonicalize(t, RAW_RETURN, LONGS);
+        if (ct == null)  ct = t;  // no prims to int-ify
+        return primsAsLongs = ct;
+    }
+
+    /** Stably sort parameters into 3 buckets: ref, int, long. */
+    public MethodType primsAtEnd() {
+        MethodType ct = primsAtEnd;
+        if (ct != null)  return ct;
+        MethodType t = erasedType;
+
+        int pac = primitiveParameterCount();
+        if (pac == 0)
+            return primsAtEnd = t;
+
+        int argc = parameterCount();
+        int lac = longPrimitiveParameterCount();
+        if (pac == argc && (lac == 0 || lac == argc))
+            return primsAtEnd = t;
+
+        // known to have a mix of 2 or 3 of ref, int, long
+        int[] reorder = primsAtEndOrder(t);
+        ct = reorderParameters(t, reorder, null);
+        //System.out.println("t="+t+" / reorder="+java.util.Arrays.toString(reorder)+" => "+ct);
+        return primsAtEnd = ct;
+    }
+
+    /** Compute a new ordering of parameters so that all references
+     *  are before all ints or longs, and all ints are before all longs.
+     *  For this ordering, doubles count as longs, and all other primitive
+     *  values count as ints.
+     *  As a special case, if the parameters are already in the specified
+     *  order, this method returns a null reference, rather than an array
+     *  specifying a null permutation.
+     *  <p>
+     *  For example, the type {@code (int,boolean,int,Object,String)void}
+     *  produces the order {@code {3,4,0,1,2}}, the type
+     *  {@code (long,int,String)void} produces {@code {2,1,2}}, and
+     *  the type {@code (Object,int)Object} produces {@code null}.
+     */
+    public static int[] primsAtEndOrder(MethodType mt) {
+        MethodTypeForm form = mt.form();
+        if (form.primsAtEnd == form.erasedType)
+            // quick check shows no reordering is necessary
+            return null;
+
+        int argc = form.parameterCount();
+        int[] paramOrder = new int[argc];
+
+        // 3-way bucket sort:
+        int pac = form.primitiveParameterCount();
+        int lac = form.longPrimitiveParameterCount();
+        int rfill = 0, ifill = argc - pac, lfill = argc - lac;
+
+        Class<?>[] ptypes = mt.ptypes();
+        boolean changed = false;
+        for (int i = 0; i < ptypes.length; i++) {
+            Class<?> pt = ptypes[i];
+            int ord;
+            if (!pt.isPrimitive())             ord = rfill++;
+            else if (!hasTwoArgSlots(pt))      ord = ifill++;
+            else                               ord = lfill++;
+            if (ord != i)  changed = true;
+            assert(paramOrder[ord] == 0);
+            paramOrder[ord] = i;
+        }
+        assert(rfill == argc - pac && ifill == argc - lac && lfill == argc);
+        if (!changed) {
+            form.primsAtEnd = form.erasedType;
+            return null;
+        }
+        return paramOrder;
+    }
+
+    /** Put the existing parameters of mt into a new order, given by newParamOrder.
+     *  The third argument is logically appended to mt.parameterArray,
+     *  so that elements of newParamOrder can index either pre-existing or
+     *  new parameter types.
+     */
+    public static MethodType reorderParameters(MethodType mt, int[] newParamOrder, Class<?>[] moreParams) {
+        if (newParamOrder == null)  return mt;  // no-op reordering
+        Class<?>[] ptypes = mt.ptypes();
+        Class<?>[] ntypes = new Class<?>[newParamOrder.length];
+        int maxParam = ptypes.length + (moreParams == null ? 0 : moreParams.length);
+        boolean changed = (ntypes.length != ptypes.length);
+        for (int i = 0; i < newParamOrder.length; i++) {
+            int param = newParamOrder[i];
+            if (param != i)  changed = true;
+            Class<?> nt;
+            if (param < ptypes.length)   nt = ptypes[param];
+            else if (param == maxParam)  nt = mt.returnType();
+            else                         nt = moreParams[param - ptypes.length];
+            ntypes[i] = nt;
+        }
+        if (!changed)  return mt;
+        return MethodType.makeImpl(mt.returnType(), ntypes, true);
+    }
+
+    private static boolean hasTwoArgSlots(Class<?> type) {
+        return type == long.class || type == double.class;
+    }
+
+    private static long pack(int a, int b, int c, int d) {
+        assert(((a|b|c|d) & ~0xFFFF) == 0);
+        long hw = ((a << 16) | b), lw = ((c << 16) | d);
+        return (hw << 32) | lw;
+    }
+    private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
+        assert(word <= 3);
+        return (char)(packed >> ((3-word) * 16));
+    }
+
+    public int parameterCount() {                      // # outgoing values
+        return unpack(argCounts, 3);
+    }
+    public int parameterSlotCount() {                  // # outgoing interpreter slots
+        return unpack(argCounts, 2);
+    }
+    public int returnCount() {                         // = 0 (V), or 1
+        return unpack(argCounts, 1);
+    }
+    public int returnSlotCount() {                     // = 0 (V), 2 (J/D), or 1
+        return unpack(argCounts, 0);
+    }
+    public int primitiveParameterCount() {
+        return unpack(primCounts, 3);
+    }
+    public int longPrimitiveParameterCount() {
+        return unpack(primCounts, 2);
+    }
+    public int primitiveReturnCount() {                // = 0 (obj), or 1
+        return unpack(primCounts, 1);
+    }
+    public int longPrimitiveReturnCount() {            // = 1 (J/D), or 0
+        return unpack(primCounts, 0);
+    }
+    public boolean hasPrimitives() {
+        return primCounts != 0;
+    }
+//    public boolean hasNonVoidPrimitives() {
+//        if (primCounts == 0)  return false;
+//        if (primitiveParameterCount() != 0)  return true;
+//        return (primitiveReturnCount() != 0 && returnCount() != 0);
+//    }
+    public boolean hasLongPrimitives() {
+        return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
+    }
+    public int parameterToArgSlot(int i) {
+        return argToSlotTable[1+i];
+    }
+    public int argSlotToParameter(int argSlot) {
+        // Note:  Empty slots are represented by zero in this table.
+        // Valid arguments slots contain incremented entries, so as to be non-zero.
+        // We return -1 the caller to mean an empty slot.
+        return slotToArgTable[argSlot] - 1;
+    }
+
+    static MethodTypeForm findForm(MethodType mt) {
+        MethodType erased = canonicalize(mt, ERASE, ERASE);
+        if (erased == null) {
+            // It is already erased.  Make a new MethodTypeForm.
+            return new MethodTypeForm(mt);
+        } else {
+            // Share the MethodTypeForm with the erased version.
+            return erased.form();
+        }
+    }
+
+    /** Codes for {@link #canonicalize(java.lang.Class, int)}.
+     * ERASE means change every reference to {@code Object}.
+     * WRAP means convert primitives (including {@code void} to their
+     * corresponding wrapper types.  UNWRAP means the reverse of WRAP.
+     * INTS means convert all non-void primitive types to int or long,
+     * according to size.  LONGS means convert all non-void primitives
+     * to long, regardless of size.  RAW_RETURN means convert a type
+     * (assumed to be a return type) to int if it is smaller than an int,
+     * or if it is void.
+     */
+    public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
+
+    /** Canonicalize the types in the given method type.
+     * If any types change, intern the new type, and return it.
+     * Otherwise return null.
+     */
+    public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
+        Class<?>[] ptypes = mt.ptypes();
+        Class<?>[] ptc = MethodTypeForm.canonicalizes(ptypes, howArgs);
+        Class<?> rtype = mt.returnType();
+        Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
+        if (ptc == null && rtc == null) {
+            // It is already canonical.
+            return null;
+        }
+        // Find the erased version of the method type:
+        if (rtc == null)  rtc = rtype;
+        if (ptc == null)  ptc = ptypes;
+        return MethodType.makeImpl(rtc, ptc, true);
+    }
+
+    /** Canonicalize the given return or param type.
+     *  Return null if the type is already canonicalized.
+     */
+    static Class<?> canonicalize(Class<?> t, int how) {
+        Class<?> ct;
+        if (t == Object.class) {
+            // no change, ever
+        } else if (!t.isPrimitive()) {
+            switch (how) {
+                case UNWRAP:
+                    ct = Wrapper.asPrimitiveType(t);
+                    if (ct != t)  return ct;
+                    break;
+                case RAW_RETURN:
+                case ERASE:
+                    return Object.class;
+            }
+        } else if (t == void.class) {
+            // no change, usually
+            switch (how) {
+                case RAW_RETURN:
+                    return int.class;
+                case WRAP:
+                    return Void.class;
+            }
+        } else {
+            // non-void primitive
+            switch (how) {
+                case WRAP:
+                    return Wrapper.asWrapperType(t);
+                case INTS:
+                    if (t == int.class || t == long.class)
+                        return null;  // no change
+                    if (t == double.class)
+                        return long.class;
+                    return int.class;
+                case LONGS:
+                    if (t == long.class)
+                        return null;  // no change
+                    return long.class;
+                case RAW_RETURN:
+                    if (t == int.class || t == long.class ||
+                        t == float.class || t == double.class)
+                        return null;  // no change
+                    // everything else returns as an int
+                    return int.class;
+            }
+        }
+        // no change; return null to signify
+        return null;
+    }
+
+    /** Canonicalize each param type in the given array.
+     *  Return null if all types are already canonicalized.
+     */
+    static Class<?>[] canonicalizes(Class<?>[] ts, int how) {
+        Class<?>[] cs = null;
+        for (int imax = ts.length, i = 0; i < imax; i++) {
+            Class<?> c = canonicalize(ts[i], how);
+            if (c != null) {
+                if (cs == null)
+                    cs = ts.clone();
+                cs[i] = c;
+            }
+        }
+        return cs;
+    }
+
+    /*non-public*/ void notifyGenericMethodType() {
+        if (genericInvoker != null)  return;
+        try {
+            // Trigger adapter creation.
+            genericInvoker = InvokeGeneric.genericInvokerOf(erasedType);
+        } catch (Exception ex) {
+            Error err = new InternalError("Exception while resolving invokeGeneric");
+            err.initCause(ex);
+            throw err;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "Form"+erasedType;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MutableCallSite.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A {@code MutableCallSite} is a {@link CallSite} whose target variable
+ * behaves like an ordinary field.
+ * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates
+ * all calls to the site's current target.
+ * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site
+ * also delegates each call to the site's current target.
+ * <p>
+ * Here is an example of a mutable call site which introduces a
+ * state variable into a method handle chain.
+ * <blockquote><pre>
+MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
+MethodHandle MH_name = name.dynamicInvoker();
+MethodType MT_str2 = MethodType.methodType(String.class, String.class);
+MethodHandle MH_upcase = MethodHandles.lookup()
+    .findVirtual(String.class, "toUpperCase", MT_str2);
+MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
+name.setTarget(MethodHandles.constant(String.class, "Rocky"));
+assertEquals("ROCKY", (String) worker1.invokeExact());
+name.setTarget(MethodHandles.constant(String.class, "Fred"));
+assertEquals("FRED", (String) worker1.invokeExact());
+// (mutation can be continued indefinitely)
+ * </pre></blockquote>
+ * <p>
+ * The same call site may be used in several places at once.
+ * <blockquote><pre>
+MethodHandle MH_dear = MethodHandles.lookup()
+    .findVirtual(String.class, "concat", MT_str2).bindTo(", dear?");
+MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
+assertEquals("Fred, dear?", (String) worker2.invokeExact());
+name.setTarget(MethodHandles.constant(String.class, "Wilma"));
+assertEquals("WILMA", (String) worker1.invokeExact());
+assertEquals("Wilma, dear?", (String) worker2.invokeExact());
+ * </pre></blockquote>
+ * <p>
+ * <em>Non-synchronization of target values:</em>
+ * A write to a mutable call site's target does not force other threads
+ * to become aware of the updated value.  Threads which do not perform
+ * suitable synchronization actions relative to the updated call site
+ * may cache the old target value and delay their use of the new target
+ * value indefinitely.
+ * (This is a normal consequence of the Java Memory Model as applied
+ * to object fields.)
+ * <p>
+ * The {@link #syncAll syncAll} operation provides a way to force threads
+ * to accept a new target value, even if there is no other synchronization.
+ * <p>
+ * For target values which will be frequently updated, consider using
+ * a {@linkplain VolatileCallSite volatile call site} instead.
+ * @author John Rose, JSR 292 EG
+ */
+public class MutableCallSite extends CallSite {
+    /**
+     * Creates a blank call site object with the given method type.
+     * The initial target is set to a method handle of the given type
+     * which will throw an {@link IllegalStateException} if called.
+     * <p>
+     * The type of the call site is permanently set to the given type.
+     * <p>
+     * Before this {@code CallSite} object is returned from a bootstrap method,
+     * or invoked in some other manner,
+     * it is usually provided with a more useful target method,
+     * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
+     * @param type the method type that this call site will have
+     * @throws NullPointerException if the proposed type is null
+     */
+    public MutableCallSite(MethodType type) {
+        super(type);
+    }
+
+    /**
+     * Creates a call site object with an initial target method handle.
+     * The type of the call site is permanently set to the initial target's type.
+     * @param target the method handle that will be the initial target of the call site
+     * @throws NullPointerException if the proposed target is null
+     */
+    public MutableCallSite(MethodHandle target) {
+        super(target);
+    }
+
+    /**
+     * Returns the target method of the call site, which behaves
+     * like a normal field of the {@code MutableCallSite}.
+     * <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
+     * non-volatile, non-final field.
+     * <p>
+     * In particular, the current thread may choose to reuse the result
+     * of a previous read of the target from memory, and may fail to see
+     * a recent update to the target by another thread.
+     *
+     * @return the linkage state of this call site, a method handle which can change over time
+     * @see #setTarget
+     */
+    @Override public final MethodHandle getTarget() {
+        return target;
+    }
+
+    /**
+     * Updates the target method of this call site, as a normal variable.
+     * The type of the new target must agree with the type of the old target.
+     * <p>
+     * The interactions with memory are the same
+     * as of a write to an ordinary variable, such as an array element or a
+     * non-volatile, non-final field.
+     * <p>
+     * In particular, unrelated threads may fail to see the updated target
+     * until they perform a read from memory.
+     * Stronger guarantees can be created by putting appropriate operations
+     * into the bootstrap method and/or the target methods used
+     * at any given call site.
+     *
+     * @param newTarget the new target
+     * @throws NullPointerException if the proposed new target is null
+     * @throws WrongMethodTypeException if the proposed new target
+     *         has a method type that differs from the previous target
+     * @see #getTarget
+     */
+    @Override public void setTarget(MethodHandle newTarget) {
+        checkTargetChange(this.target, newTarget);
+        setTargetNormal(newTarget);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public final MethodHandle dynamicInvoker() {
+        return makeDynamicInvoker();
+    }
+
+    /**
+     * Performs a synchronization operation on each call site in the given array,
+     * forcing all other threads to throw away any cached values previously
+     * loaded from the target of any of the call sites.
+     * <p>
+     * This operation does not reverse any calls that have already started
+     * on an old target value.
+     * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.)
+     * <p>
+     * The overall effect is to force all future readers of each call site's target
+     * to accept the most recently stored value.
+     * ("Most recently" is reckoned relative to the {@code syncAll} itself.)
+     * Conversely, the {@code syncAll} call may block until all readers have
+     * (somehow) decached all previous versions of each call site's target.
+     * <p>
+     * To avoid race conditions, calls to {@code setTarget} and {@code syncAll}
+     * should generally be performed under some sort of mutual exclusion.
+     * Note that reader threads may observe an updated target as early
+     * as the {@code setTarget} call that install the value
+     * (and before the {@code syncAll} that confirms the value).
+     * On the other hand, reader threads may observe previous versions of
+     * the target until the {@code syncAll} call returns
+     * (and after the {@code setTarget} that attempts to convey the updated version).
+     * <p>
+     * This operation is likely to be expensive and should be used sparingly.
+     * If possible, it should be buffered for batch processing on sets of call sites.
+     * <p>
+     * If {@code sites} contains a null element,
+     * a {@code NullPointerException} will be raised.
+     * In this case, some non-null elements in the array may be
+     * processed before the method returns abnormally.
+     * Which elements these are (if any) is implementation-dependent.
+     *
+     * <h3>Java Memory Model details</h3>
+     * In terms of the Java Memory Model, this operation performs a synchronization
+     * action which is comparable in effect to the writing of a volatile variable
+     * by the current thread, and an eventual volatile read by every other thread
+     * that may access one of the affected call sites.
+     * <p>
+     * The following effects are apparent, for each individual call site {@code S}:
+     * <ul>
+     * <li>A new volatile variable {@code V} is created, and written by the current thread.
+     *     As defined by the JMM, this write is a global synchronization event.
+     * <li>As is normal with thread-local ordering of write events,
+     *     every action already performed by the current thread is
+     *     taken to happen before the volatile write to {@code V}.
+     *     (In some implementations, this means that the current thread
+     *     performs a global release operation.)
+     * <li>Specifically, the write to the current target of {@code S} is
+     *     taken to happen before the volatile write to {@code V}.
+     * <li>The volatile write to {@code V} is placed
+     *     (in an implementation specific manner)
+     *     in the global synchronization order.
+     * <li>Consider an arbitrary thread {@code T} (other than the current thread).
+     *     If {@code T} executes a synchronization action {@code A}
+     *     after the volatile write to {@code V} (in the global synchronization order),
+     *     it is therefore required to see either the current target
+     *     of {@code S}, or a later write to that target,
+     *     if it executes a read on the target of {@code S}.
+     *     (This constraint is called "synchronization-order consistency".)
+     * <li>The JMM specifically allows optimizing compilers to elide
+     *     reads or writes of variables that are known to be useless.
+     *     Such elided reads and writes have no effect on the happens-before
+     *     relation.  Regardless of this fact, the volatile {@code V}
+     *     will not be elided, even though its written value is
+     *     indeterminate and its read value is not used.
+     * </ul>
+     * Because of the last point, the implementation behaves as if a
+     * volatile read of {@code V} were performed by {@code T}
+     * immediately after its action {@code A}.  In the local ordering
+     * of actions in {@code T}, this read happens before any future
+     * read of the target of {@code S}.  It is as if the
+     * implementation arbitrarily picked a read of {@code S}'s target
+     * by {@code T}, and forced a read of {@code V} to precede it,
+     * thereby ensuring communication of the new target value.
+     * <p>
+     * As long as the constraints of the Java Memory Model are obeyed,
+     * implementations may delay the completion of a {@code syncAll}
+     * operation while other threads ({@code T} above) continue to
+     * use previous values of {@code S}'s target.
+     * However, implementations are (as always) encouraged to avoid
+     * livelock, and to eventually require all threads to take account
+     * of the updated target.
+     *
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * For performance reasons, {@code syncAll} is not a virtual method
+     * on a single call site, but rather applies to a set of call sites.
+     * Some implementations may incur a large fixed overhead cost
+     * for processing one or more synchronization operations,
+     * but a small incremental cost for each additional call site.
+     * In any case, this operation is likely to be costly, since
+     * other threads may have to be somehow interrupted
+     * in order to make them notice the updated target value.
+     * However, it may be observed that a single call to synchronize
+     * several sites has the same formal effect as many calls,
+     * each on just one of the sites.
+     *
+     * <p style="font-size:smaller;">
+     * <em>Implementation Note:</em>
+     * Simple implementations of {@code MutableCallSite} may use
+     * a volatile variable for the target of a mutable call site.
+     * In such an implementation, the {@code syncAll} method can be a no-op,
+     * and yet it will conform to the JMM behavior documented above.
+     *
+     * @param sites an array of call sites to be synchronized
+     * @throws NullPointerException if the {@code sites} array reference is null
+     *                              or the array contains a null
+     */
+    public static void syncAll(MutableCallSite[] sites) {
+        if (sites.length == 0)  return;
+        STORE_BARRIER.lazySet(0);
+        for (int i = 0; i < sites.length; i++) {
+            sites[i].getClass();  // trigger NPE on first null
+        }
+        // FIXME: NYI
+    }
+    private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/SpreadGeneric.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,678 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.ValueConversions;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * 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);
+        MethodTypeForm form = targetType.form();
+        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) {
+        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 = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+            } catch (ReflectiveOperationException 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 BoundMethodHandle {
+        /*
+         * 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 addTypeString(target, this);
+        }
+
+        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; // "java.lang.invoke.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.invokeExact(a0, a1)); }
+        protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1);
+             return target.invokeExact(a0,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1);
+             return target.invokeExact(
+                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.invokeExact(@av@); }",
+        "        //@each-S@",
+        "        protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);",
+        "            return target.invokeExact(@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.invokeExact(); }
+    }
+    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.invokeExact(a0); }
+        protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1);
+            return target.invokeExact(
+                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.invokeExact(a0, a1); }
+        protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1);
+            return target.invokeExact(a0,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2);
+            return target.invokeExact(
+                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.invokeExact(a0, a1, a2); }
+        protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1);
+            return target.invokeExact(a0, a1,
+                super.select(av,0)); }
+        protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2);
+            return target.invokeExact(a0,
+                super.select(av,0), super.select(av,1)); }
+        protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3);
+            return target.invokeExact(
+                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
+                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
+                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
+                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
+                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
+                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
+                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
+                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)); }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/SwitchPoint.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * <p>
+ * A {@code SwitchPoint} is an object which can publish state transitions to other threads.
+ * A switch point is initially in the <em>valid</em> state, but may at any time be
+ * changed to the <em>invalid</em> state.  Invalidation cannot be reversed.
+ * A switch point can combine a <em>guarded pair</em> of method handles into a
+ * <em>guarded delegator</em>.
+ * The guarded delegator is a method handle which delegates to one of the old method handles.
+ * The state of the switch point determines which of the two gets the delegation.
+ * <p>
+ * A single switch point may be used to control any number of method handles.
+ * (Indirectly, therefore, it can control any number of call sites.)
+ * This is done by using the single switch point as a factory for combining
+ * any number of guarded method handle pairs into guarded delegators.
+ * <p>
+ * When a guarded delegator is created from a guarded pair, the pair
+ * is wrapped in a new method handle {@code M},
+ * which is permanently associated with the switch point that created it.
+ * Each pair consists of a target {@code T} and a fallback {@code F}.
+ * While the switch point is valid, invocations to {@code M} are delegated to {@code T}.
+ * After it is invalidated, invocations are delegated to {@code F}.
+ * <p>
+ * Invalidation is global and immediate, as if the switch point contained a
+ * volatile boolean variable consulted on every call to {@code M}.
+ * The invalidation is also permanent, which means the switch point
+ * can change state only once.
+ * The switch point will always delegate to {@code F} after being invalidated.
+ * At that point {@code guardWithTest} may ignore {@code T} and return {@code F}.
+ * <p>
+ * Here is an example of a switch point in action:
+ * <blockquote><pre>
+MethodType MT_str2 = MethodType.methodType(String.class, String.class);
+MethodHandle MH_strcat = MethodHandles.lookup()
+    .findVirtual(String.class, "concat", MT_str2);
+SwitchPoint spt = new SwitchPoint();
+// the following steps may be repeated to re-use the same switch point:
+MethodHandle worker1 = strcat;
+MethodHandle worker2 = MethodHandles.permuteArguments(strcat, MT_str2, 1, 0);
+MethodHandle worker = spt.guardWithTest(worker1, worker2);
+assertEquals("method", (String) worker.invokeExact("met", "hod"));
+SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
+assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
+ * </pre></blockquote>
+ * <p style="font-size:smaller;">
+ * <em>Discussion:</em>
+ * Switch points are useful without subclassing.  They may also be subclassed.
+ * This may be useful in order to associate application-specific invalidation logic
+ * with the switch point.
+ * Notice that there is no permanent association between a switch point and
+ * the method handles it produces and consumes.
+ * The garbage collector may collect method handles produced or consumed
+ * by a switch point independently of the lifetime of the switch point itself.
+ * <p style="font-size:smaller;">
+ * <em>Implementation Note:</em>
+ * A switch point behaves as if implemented on top of {@link MutableCallSite},
+ * approximately as follows:
+ * <blockquote><pre>
+public class SwitchPoint {
+  private static final MethodHandle
+    K_true  = MethodHandles.constant(boolean.class, true),
+    K_false = MethodHandles.constant(boolean.class, false);
+  private final MutableCallSite mcs;
+  private final MethodHandle mcsInvoker;
+  public SwitchPoint() {
+    this.mcs = new MutableCallSite(K_true);
+    this.mcsInvoker = mcs.dynamicInvoker();
+  }
+  public MethodHandle guardWithTest(
+                MethodHandle target, MethodHandle fallback) {
+    // Note:  mcsInvoker is of type ()boolean.
+    // Target and fallback may take any arguments, but must have the same type.
+    return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
+  }
+  public static void invalidateAll(SwitchPoint[] spts) {
+    List&lt;MutableCallSite&gt; mcss = new ArrayList&lt;&gt;();
+    for (SwitchPoint spt : spts)  mcss.add(spt.mcs);
+    for (MutableCallSite mcs : mcss)  mcs.setTarget(K_false);
+    MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
+  }
+}
+ * </pre></blockquote>
+ * @author Remi Forax, JSR 292 EG
+ */
+public class SwitchPoint {
+    private static final MethodHandle
+        K_true  = MethodHandles.constant(boolean.class, true),
+        K_false = MethodHandles.constant(boolean.class, false);
+
+    private final MutableCallSite mcs;
+    private final MethodHandle mcsInvoker;
+
+    /**
+     * Creates a new switch point.
+     */
+    public SwitchPoint() {
+        this.mcs = new MutableCallSite(K_true);
+        this.mcsInvoker = mcs.dynamicInvoker();
+    }
+
+    /**
+     * Returns a method handle which always delegates either to the target or the fallback.
+     * The method handle will delegate to the target exactly as long as the switch point is valid.
+     * After that, it will permanently delegate to the fallback.
+     * <p>
+     * The target and fallback must be of exactly the same method type,
+     * and the resulting combined method handle will also be of this type.
+     *
+     * @param target the method handle selected by the switch point as long as it is valid
+     * @param fallback the method handle selected by the switch point after it is invalidated
+     * @return a combined method handle which always calls either the target or fallback
+     * @throws NullPointerException if either argument is null
+     * @see MethodHandles#guardWithTest
+     */
+    public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) {
+        if (mcs.getTarget() == K_false)
+            return fallback;  // already invalid
+        return MethodHandles.guardWithTest(mcsInvoker, target, fallback);
+    }
+
+    /**
+     * Sets all of the given switch points into the invalid state.
+     * After this call executes, no thread will observe any of the
+     * switch points to be in a valid state.
+     * <p>
+     * This operation is likely to be expensive and should be used sparingly.
+     * If possible, it should be buffered for batch processing on sets of switch points.
+     * <p>
+     * If {@code switchPoints} contains a null element,
+     * a {@code NullPointerException} will be raised.
+     * In this case, some non-null elements in the array may be
+     * processed before the method returns abnormally.
+     * Which elements these are (if any) is implementation-dependent.
+     *
+     * <p style="font-size:smaller;">
+     * <em>Discussion:</em>
+     * For performance reasons, {@code invalidateAll} is not a virtual method
+     * on a single switch point, but rather applies to a set of switch points.
+     * Some implementations may incur a large fixed overhead cost
+     * for processing one or more invalidation operations,
+     * but a small incremental cost for each additional invalidation.
+     * In any case, this operation is likely to be costly, since
+     * other threads may have to be somehow interrupted
+     * in order to make them notice the updated switch point state.
+     * However, it may be observed that a single call to invalidate
+     * several switch points has the same formal effect as many calls,
+     * each on just one of the switch points.
+     *
+     * <p style="font-size:smaller;">
+     * <em>Implementation Note:</em>
+     * Simple implementations of {@code SwitchPoint} may use
+     * a private {@link MutableCallSite} to publish the state of a switch point.
+     * In such an implementation, the {@code invalidateAll} method can
+     * simply change the call site's target, and issue one call to
+     * {@linkplain MutableCallSite#syncAll synchronize} all the
+     * private call sites.
+     *
+     * @param switchPoints an array of call sites to be synchronized
+     * @throws NullPointerException if the {@code switchPoints} array reference is null
+     *                              or the array contains a null
+     */
+    public static void invalidateAll(SwitchPoint[] switchPoints) {
+        if (switchPoints.length == 0)  return;
+        MutableCallSite[] sites = new MutableCallSite[switchPoints.length];
+        for (int i = 0; i < switchPoints.length; i++) {
+            SwitchPoint spt = switchPoints[i];
+            if (spt == null)  break;  // MSC.syncAll will trigger a NPE
+            sites[i] = spt.mcs;
+            spt.mcs.setTarget(K_false);
+        }
+        MutableCallSite.syncAll(sites);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/ToGeneric.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,1062 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Adapters which mediate between incoming calls which are not generic
+ * and outgoing calls which are.  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
+ * only Object arguments.  A non-generic call therefore features
+ * primitives and/or reference types other than Object.
+ * An adapter has types for its incoming and outgoing calls.
+ * The incoming call type is simply determined by the adapter's type
+ * (the MethodType it presents to callers).  The outgoing call type
+ * is determined by the adapter's target (a MethodHandle that the adapter
+ * 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.)
+ * @author jrose
+ */
+class ToGeneric {
+    // type for the incoming call (may be erased)
+    private final MethodType entryType;
+    // incoming type with primitives moved to the end and turned to int/long
+    private final MethodType rawEntryType;
+    // adapter for the erased type
+    private final Adapter adapter;
+    // entry point for adapter (Adapter mh, a...) => ...
+    private final MethodHandle entryPoint;
+    // permutation of arguments for primsAtEndType
+    private final int[] primsAtEndOrder;
+    // optional final argument list conversions (at least, invokes the target)
+    private final MethodHandle invoker;
+    // conversion which unboxes a primitive return value
+    private final MethodHandle returnConversion;
+
+    /** 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) {
+        assert(entryType.erase() == entryType); // for now
+        // incoming call will first "forget" all reference types except Object
+        this.entryType = entryType;
+        MethodHandle invoker0 = entryType.generic().invokers().exactInvoker();
+        MethodType rawEntryTypeInit;
+        Adapter ad = findAdapter(rawEntryTypeInit = entryType);
+        if (ad != null) {
+            // Immediate hit to exactly the adapter we want,
+            // with no monkeying around with primitive types.
+            this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
+            this.rawEntryType = rawEntryTypeInit;
+            this.adapter = ad;
+            this.entryPoint = ad.prototypeEntryPoint();
+            this.primsAtEndOrder = null;
+            this.invoker = invoker0;
+            return;
+        }
+
+        // next, it will reorder primitives after references
+        MethodType primsAtEnd = entryType.form().primsAtEnd();
+        // at the same time, it will "forget" all primitive types except int/long
+        this.primsAtEndOrder = MethodTypeForm.primsAtEndOrder(entryType);
+        if (primsAtEndOrder != null) {
+            // reordering is required; build on top of a simpler ToGeneric
+            ToGeneric va2 = ToGeneric.of(primsAtEnd);
+            this.adapter = va2.adapter;
+            if (true) throw new UnsupportedOperationException("NYI: primitive parameters must follow references; entryType = "+entryType);
+            this.entryPoint = MethodHandleImpl.convertArguments(
+                    va2.entryPoint, primsAtEnd, entryType, primsAtEndOrder);
+            // example: for entryType of (int,Object,Object), the reordered
+            // type is (Object,Object,int) and the order is {1,2,0},
+            // and putPAE is (mh,int0,obj1,obj2) => mh.invokeExact(obj1,obj2,int0)
+            return;
+        }
+
+        // after any needed argument reordering, it will reinterpret
+        // primitive arguments according to their "raw" types int/long
+        MethodType intsAtEnd = primsAtEnd.form().primsAsInts();
+        ad = findAdapter(rawEntryTypeInit = intsAtEnd);
+        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 = primsAtEnd.form().primsAsLongs();
+            ad = findAdapter(rawEntryTypeInit = longsAtEnd);
+            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 = MethodHandleImpl.convertArguments(
+                                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();
+            }
+        }
+        MethodType tepType = entryType.insertParameterTypes(0, ad.getClass());
+        this.entryPoint =
+            AdapterMethodHandle.makeRetypeRaw(tepType, rawEntryPoint);
+        if (this.entryPoint == null)
+            throw new UnsupportedOperationException("cannot retype to "+entryType
+                    +" from "+rawEntryPoint.type().dropParameterTypes(0, 1));
+        this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
+        this.rawEntryType = rawEntryTypeInit;
+        this.adapter = ad;
+        this.invoker = makeRawArgumentFilter(invoker0, rawEntryTypeInit, entryType);
+    }
+
+    /** A generic argument list will be created by a call of type 'raw'.
+     *  The values need to be reboxed for to match 'cooked'.
+     *  Do this on the fly.
+     */
+    // TO DO: Use a generic argument converter in a different file
+    static MethodHandle makeRawArgumentFilter(MethodHandle invoker,
+            MethodType raw, MethodType cooked) {
+        MethodHandle filteredInvoker = null;
+        for (int i = 0, nargs = raw.parameterCount(); i < nargs; i++) {
+            Class<?> src = raw.parameterType(i);
+            Class<?> dst = cooked.parameterType(i);
+            if (src == dst)  continue;
+            assert(src.isPrimitive() && dst.isPrimitive());
+            if (filteredInvoker == null) {
+                filteredInvoker =
+                        AdapterMethodHandle.makeCheckCast(
+                            invoker.type().generic(), invoker, 0, MethodHandle.class);
+                if (filteredInvoker == null)  throw new UnsupportedOperationException("NYI");
+            }
+            MethodHandle reboxer = ValueConversions.rebox(dst, false);
+            filteredInvoker = FilterGeneric.makeArgumentFilter(1+i, reboxer, filteredInvoker);
+            if (filteredInvoker == null)  throw new InternalError();
+        }
+        if (filteredInvoker == null)  return invoker;
+        return AdapterMethodHandle.makeRetypeOnly(invoker.type(), filteredInvoker);
+    }
+
+    /**
+     * Caller will be expecting a result from a call to {@code type},
+     * while the internal adapter entry point is rawEntryType.
+     * Also, the internal target method will be returning a boxed value,
+     * as an untyped object.
+     * <p>
+     * Produce a value converter which will be typed to convert from
+     * {@code Object} to the return value of {@code rawEntryType}, and will
+     * in fact ensure that the value is compatible with the return type of
+     * {@code type}.
+     */
+    private static MethodHandle computeReturnConversion(
+            MethodType type, MethodType rawEntryType, boolean mustCast) {
+        Class<?> tret = type.returnType();
+        Class<?> rret = rawEntryType.returnType();
+        if (mustCast || !tret.isPrimitive()) {
+            assert(!tret.isPrimitive());
+            assert(!rret.isPrimitive());
+            if (rret == Object.class && !mustCast)
+                return null;
+            return ValueConversions.cast(tret, false);
+        } else if (tret == rret) {
+            return ValueConversions.unbox(tret, false);
+        } else {
+            assert(rret.isPrimitive());
+            assert(tret == double.class ? rret == long.class : rret == int.class);
+            return ValueConversions.unboxRaw(tret, false);
+        }
+    }
+
+    Adapter makeInstance(MethodType type, MethodHandle genericTarget) {
+        genericTarget.getClass();  // check for NPE
+        MethodHandle convert = returnConversion;
+        if (primsAtEndOrder != null)
+            // reorder arguments passed to genericTarget, if primsAtEndOrder
+            throw new UnsupportedOperationException("NYI");
+        if (type == entryType) {
+            if (convert == null)  convert = ValueConversions.identity();
+            return adapter.makeInstance(entryPoint, invoker, convert, genericTarget);
+        }
+        // my erased-type is not exactly the same as the desired type
+        assert(type.erase() == entryType);  // else we are busted
+        if (convert == null)
+            convert = computeReturnConversion(type, rawEntryType, true);
+        // retype erased reference arguments (the cast makes it safe to do this)
+        MethodType tepType = type.insertParameterTypes(0, adapter.getClass());
+        MethodHandle typedEntryPoint =
+            AdapterMethodHandle.makeRetypeRaw(tepType, entryPoint);
+        return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget);
+    }
+
+    /** Build an adapter of the given type, which invokes genericTarget
+     *  on the incoming arguments, after boxing as necessary.
+     *  The return value is unboxed if necessary.
+     * @param type  the required type of the
+     * @param genericTarget the target, which must accept and return only Object values
+     * @return an adapter method handle
+     */
+    public static MethodHandle make(MethodType type, MethodHandle genericTarget) {
+        MethodType gtype = genericTarget.type();
+        if (type.generic() != gtype)
+            throw newIllegalArgumentException("type must be generic");
+        if (type == gtype)  return genericTarget;
+        return ToGeneric.of(type).makeInstance(type, genericTarget);
+    }
+
+    /** Return the adapter information for this type's erasure. */
+    static ToGeneric of(MethodType type) {
+        MethodTypeForm form = type.form();
+        ToGeneric toGen = form.toGeneric;
+        if (toGen == null)
+            form.toGeneric = toGen = new ToGeneric(form.erasedType());
+        return toGen;
+    }
+
+    public String toString() {
+        return "ToGeneric"+entryType
+                +(primsAtEndOrder!=null?"[reorder]":"");
+    }
+
+    /* Create an adapter for the given incoming call type. */
+    static Adapter findAdapter(MethodType entryPointType) {
+        MethodTypeForm form = entryPointType.form();
+        Class<?> rtype = entryPointType.returnType();
+        int argc = form.parameterCount();
+        int lac = form.longPrimitiveParameterCount();
+        int iac = form.primitiveParameterCount() - lac;
+        String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
+        String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
+        String iname0 = "invoke_"+rawReturn;
+        String iname1 = "invoke";
+        String[] inames = { iname0, iname1 };
+        String cname0 = rawReturn + argc;
+        String cname1 = "A"       + argc;
+        String[] cnames = { cname1, cname1+intsAndLongs, cname0, cname0+intsAndLongs };
+        // e.g., D5I2, D5, L5I2, L5
+        for (String cname : cnames) {
+            Class<? extends Adapter> acls = Adapter.findSubClass(cname);
+            if (acls == null)  continue;
+            // see if it has the required invoke method
+            for (String iname : inames) {
+                MethodHandle entryPoint = null;
+                try {
+                    entryPoint = IMPL_LOOKUP.
+                                    findSpecial(acls, iname, entryPointType, acls);
+                } catch (ReflectiveOperationException ex) {
+                }
+                if (entryPoint == null)  continue;
+                Constructor<? extends Adapter> ctor = null;
+                try {
+                    // Prototype builder:
+                    ctor = acls.getDeclaredConstructor(MethodHandle.class);
+                } catch (NoSuchMethodException ex) {
+                } catch (SecurityException ex) {
+                }
+                if (ctor == null)  continue;
+                try {
+                    return ctor.newInstance(entryPoint);
+                } 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 entryPointType) {
+        throw new UnsupportedOperationException("NYI");
+    }
+
+    /**
+     * The invoke method takes some particular but unconstrained spread
+     * of raw argument types, and returns a raw return type (in L/I/J/F/D).
+     * Internally, it converts the incoming arguments uniformly into objects.
+     * This series of objects is then passed to the {@code target} method,
+     * which returns a result object.  This result is finally converted,
+     * via another method handle {@code convert}, which is responsible for
+     * converting the object result into the raw return value.
+     */
+    static abstract class Adapter extends BoundMethodHandle {
+        /*
+         * class X<<R,A...>> extends Adapter {
+         *   Object...=>Object target;
+         *   Object=>R convert;
+         *   R invoke(A... a...) = convert(invoker(target, a...)))
+         * }
+         */
+        protected final MethodHandle invoker;  // (MH, Object...) -> Object
+        protected final MethodHandle target;   // Object... -> Object
+        protected final MethodHandle convert;  // Object -> R
+
+        @Override
+        public String toString() {
+            return target == null ? "prototype:"+convert : addTypeString(target, this);
+        }
+
+        protected boolean isPrototype() { return target == null; }
+        /* Prototype constructor. */
+        protected Adapter(MethodHandle entryPoint) {
+            super(entryPoint);
+            this.invoker = null;
+            this.convert = entryPoint;
+            this.target = null;
+            assert(isPrototype());
+        }
+        protected MethodHandle prototypeEntryPoint() {
+            if (!isPrototype())  throw new InternalError();
+            return convert;
+        }
+
+        protected Adapter(MethodHandle entryPoint, MethodHandle invoker, MethodHandle convert, MethodHandle target) {
+            super(entryPoint);
+            this.invoker = invoker;
+            this.convert = convert;
+            this.target = target;
+        }
+
+        /** Make a copy of self, with new fields. */
+        protected abstract Adapter makeInstance(MethodHandle entryPoint,
+                MethodHandle invoker, MethodHandle convert, MethodHandle target);
+        // { return new ThisType(entryPoint, convert, target); }
+
+        // Code to run when the arguments (<= 4) have all been boxed.
+        protected Object target()               throws Throwable { return invoker.invokeExact(target); }
+        protected Object target(Object a0)      throws Throwable { return invoker.invokeExact(target, a0); }
+        protected Object target(Object a0, Object a1)
+                                                throws Throwable { return invoker.invokeExact(target, a0, a1); }
+        protected Object target(Object a0, Object a1, Object a2)
+                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2); }
+        protected Object target(Object a0, Object a1, Object a2, Object a3)
+                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); }
+        /*
+        protected Object target_0(Object... av) throws Throwable { return invoker.invokeExact(target, av); }
+        protected Object target_1(Object a0, Object... av)
+                                                throws Throwable { return invoker.invokeExact(target, a0, (Object)av); }
+        protected Object target_2(Object a0, Object a1, Object... av)
+                                                throws Throwable { return invoker.invokeExact(target, a0, a1, (Object)av); }
+        protected Object target_3(Object a0, Object a1, Object a2, Object... av)
+                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2, (Object)av); }
+        protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av)
+                                                throws Throwable { return invoker.invokeExact(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) throws Throwable { return (Object)convert.invokeExact(res); }
+        protected int    return_I(Object res) throws Throwable { return (int)   convert.invokeExact(res); }
+        protected long   return_J(Object res) throws Throwable { return (long)  convert.invokeExact(res); }
+        protected float  return_F(Object res) throws Throwable { return (float) convert.invokeExact(res); }
+        protected double return_D(Object res) throws Throwable { return (double)convert.invokeExact(res); }
+
+        static private final String CLASS_PREFIX; // "java.lang.invoke.ToGeneric$"
+        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 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)   throws Throwable { return invoker.invokeExact(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)); }
+    }
+    // */
+
+/*
+: SHELL; n=ToGeneric; 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[] TYPES = { "Object", "int   ", "long  ", "float ", "double" };
+    static String[] TCHARS = { "L",     "I",      "J",      "F",      "D",     "A" };
+    static String[][] TEMPLATES = { {
+        "@for@ arity=0..3   rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
+        "@for@ arity=4..4   rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
+        "@for@ arity=5..5   rcat<=2 nrefs<=99 nints<=99 nlongs<=99",
+        "@for@ arity=6..10  rcat<=2 nrefs<=99 nints=0   nlongs<=99",
+        "    //@each-cat@",
+        "    static class @cat@ extends Adapter {",
+        "        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@)   throws Throwable { return invoker.invokeExact(target@comma@@av@); }",
+        "        //@each-Tv@",
+        "        protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
+        "        //@end-Tv@",
+        "        //@each-Tv@",
+        "        //@each-R@",
+        "        protected @R@ invoke_@Rc@(@Tvav@) throws Throwable { return return_@Rc@(target@cat@(@av@)); }",
+        "        //@end-R@",
+        "        //@end-Tv@",
+        "    }",
+    } };
+    enum VAR {
+        cat, R, Rc, Tv, av, comma, Tvav, Ovav;
+        public final String pattern = "@"+toString().replace('_','.')+"@";
+        public String binding;
+        static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
+            int nargs = nrefs + nints + nlongs;
+            if (topLevel)
+                VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
+            VAR.R.binding = TYPES[rcat];
+            VAR.Rc.binding = TCHARS[rcat];
+            String[] Tv = new String[nargs];
+            String[] av = new String[nargs];
+            String[] Tvav = new String[nargs];
+            String[] Ovav = new String[nargs];
+            for (int i = 0; i < nargs; i++) {
+                int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
+                Tv[i] = TYPES[tcat];
+                av[i] = arg(i);
+                Tvav[i] = param(Tv[i], av[i]);
+                Ovav[i] = param("Object", av[i]);
+            }
+            VAR.Tv.binding = comma(Tv);
+            VAR.av.binding = comma(av);
+            VAR.comma.binding = (av.length == 0 ? "" : ", ");
+            VAR.Tvav.binding = comma(Tvav);
+            VAR.Ovav.binding = comma(Ovav);
+        }
+        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 sep, String[] v) {
+            if (v.length == 0)  return "";
+            String res = sep+v[0];
+            for (int i = 1; i < v.length; i++)  res += ", "+v[i];
+            return res;
+        }
+        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, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
+    static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
+    static HashSet<String> done = new HashSet<String>();
+    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++]);
+        MAX_RCAT  = Integer.valueOf(params[pcur++]);
+        MAX_REFS  = Integer.valueOf(params[pcur++]);
+        MAX_INTS  = Integer.valueOf(params[pcur++]);
+        MAX_LONGS = Integer.valueOf(params[pcur++]);
+        if (pcur != params.length)  throw new RuntimeException("bad extra param: "+forLine);
+        if (MAX_RCAT >= TYPES.length)  MAX_RCAT = TYPES.length - 1;
+        ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
+        ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
+        for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
+            for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
+                expandTemplate(template, true, rcat, nargs, 0, 0);
+                if (ALL_ARG_TYPES)  break;
+                expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
+                if (ALL_RETURN_TYPES)  break;
+            }
+        }
+    }
+    static String catstr(int rcat, int nrefs, int nints, int nlongs) {
+        int nargs = nrefs + nints + nlongs;
+        String cat = TCHARS[rcat] + nargs;
+        if (!ALL_ARG_TYPES)  cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
+        return cat;
+    }
+    static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
+        for (int isLong = 0; isLong <= 1; isLong++) {
+            for (int nprims = 1; nprims <= nargs; nprims++) {
+                int nrefs = nargs - nprims;
+                int nints = ((1-isLong) * nprims);
+                int nlongs = (isLong * nprims);
+                expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
+            }
+        }
+    }
+    static void expandTemplate(String[] template, boolean topLevel,
+                               int rcat, int nrefs, int nints, int nlongs) {
+        int nargs = nrefs + nints + nlongs;
+        if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS)  return;
+        VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+        if (topLevel && !done.add(VAR.cat.binding)) {
+            System.out.println("    //repeat "+VAR.cat.binding);
+            return;
+        }
+        for (int i = 0; i < template.length; i++) {
+            String line = template[i];
+            if (line.endsWith("@each-cat@")) {
+                // ignore
+            } else if (line.endsWith("@each-R@")) {
+                int blockEnd = indexAfter(template, i, "@end-R@");
+                String[] block = stringsIn(template, i+1, blockEnd-1);
+                for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
+                    expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
+                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+                i = blockEnd-1; continue;
+            } else if (line.endsWith("@each-Tv@")) {
+                int blockEnd = indexAfter(template, i, "@end-Tv@");
+                String[] block = stringsIn(template, i+1, blockEnd-1);
+                expandTemplate(block, false, rcat, nrefs, nints, nlongs);
+                expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
+                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+                i = blockEnd-1; continue;
+            } else {
+                System.out.println(VAR.transform(line));
+            }
+        }
+    }
+}
+//}}} */
+//params=[0, 3, 4, 99, 99, 99]
+    static class A0 extends Adapter {
+        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()   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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, 4, 4, 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)   throws Throwable { return invoker.invokeExact(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 float  invoke_F(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+        protected double invoke_D(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_D(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 float  invoke_F(Object a0, Object a1, Object a2, int    a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+        protected double invoke_D(Object a0, Object a1, Object a2, int    a3) throws Throwable { return return_D(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 float  invoke_F(Object a0, Object a1, int    a2, int    a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+        protected double invoke_D(Object a0, Object a1, int    a2, int    a3) throws Throwable { return return_D(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 float  invoke_F(Object a0, int    a1, int    a2, int    a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+        protected double invoke_D(Object a0, int    a1, int    a2, int    a3) throws Throwable { return return_D(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 float  invoke_F(int    a0, int    a1, int    a2, int    a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+        protected double invoke_D(int    a0, int    a1, int    a2, int    a3) throws Throwable { return return_D(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 float  invoke_F(Object a0, Object a1, Object a2, long   a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+        protected double invoke_D(Object a0, Object a1, Object a2, long   a3) throws Throwable { return return_D(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 float  invoke_F(Object a0, Object a1, long   a2, long   a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+        protected double invoke_D(Object a0, Object a1, long   a2, long   a3) throws Throwable { return return_D(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 float  invoke_F(Object a0, long   a1, long   a2, long   a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+        protected double invoke_D(Object a0, long   a1, long   a2, long   a3) throws Throwable { return return_D(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)); }
+        protected float  invoke_F(long   a0, long   a1, long   a2, long   a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+        protected double invoke_D(long   a0, long   a1, long   a2, long   a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+    }
+//params=[5, 5, 2, 99, 99, 99]
+    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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)); }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/VolatileCallSite.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
+ * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates
+ * to its call site target immediately, even if the update occurs in another thread.
+ * There may be a performance penalty for such tight coupling between threads.
+ * <p>
+ * Unlike {@code MutableCallSite}, there is no
+ * {@linkplain MutableCallSite#syncAll syncAll operation} on volatile
+ * call sites, since every write to a volatile variable is implicitly
+ * synchronized with reader threads.
+ * <p>
+ * In other respects, a {@code VolatileCallSite} is interchangeable
+ * with {@code MutableCallSite}.
+ * @see MutableCallSite
+ * @author John Rose, JSR 292 EG
+ */
+public class VolatileCallSite extends CallSite {
+    /**
+     * Creates a call site with a volatile binding to its target.
+     * The initial target is set to a method handle
+     * of the given type which will throw an {@code IllegalStateException} if called.
+     * @param type the method type that this call site will have
+     * @throws NullPointerException if the proposed type is null
+     */
+    public VolatileCallSite(MethodType type) {
+        super(type);
+    }
+
+    /**
+     * Creates a call site with a volatile binding to its target.
+     * The target is set to the given value.
+     * @param target the method handle that will be the initial target of the call site
+     * @throws NullPointerException if the proposed target is null
+     */
+    public VolatileCallSite(MethodHandle target) {
+        super(target);
+    }
+
+    /**
+     * Returns the target method of the call site, which behaves
+     * like a {@code volatile} field of the {@code VolatileCallSite}.
+     * <p>
+     * The interactions of {@code getTarget} with memory are the same
+     * as of a read from a {@code volatile} field.
+     * <p>
+     * In particular, the current thread is required to issue a fresh
+     * read of the target from memory, and must not fail to see
+     * a recent update to the target by another thread.
+     *
+     * @return the linkage state of this call site, a method handle which can change over time
+     * @see #setTarget
+     */
+    @Override public final MethodHandle getTarget() {
+        return getTargetVolatile();
+    }
+
+    /**
+     * Updates the target method of this call site, as a volatile variable.
+     * The type of the new target must agree with the type of the old target.
+     * <p>
+     * The interactions with memory are the same as of a write to a volatile field.
+     * In particular, any threads is guaranteed to see the updated target
+     * the next time it calls {@code getTarget}.
+     * @param newTarget the new target
+     * @throws NullPointerException if the proposed new target is null
+     * @throws WrongMethodTypeException if the proposed new target
+     *         has a method type that differs from the previous target
+     * @see #getTarget
+     */
+    @Override public void setTarget(MethodHandle newTarget) {
+        checkTargetChange(getTargetVolatile(), newTarget);
+        setTargetVolatile(newTarget);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public final MethodHandle dynamicInvoker() {
+        return makeDynamicInvoker();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * Thrown to indicate that code has attempted to call a method handle
+ * via the wrong method type.  As with the bytecode representation of
+ * normal Java method calls, method handle calls are strongly typed
+ * to a specific type descriptor associated with a call site.
+ * <p>
+ * This exception may also be thrown when two method handles are
+ * composed, and the system detects that their types cannot be
+ * matched up correctly.  This amounts to an early evaluation
+ * of the type mismatch, at method handle construction time,
+ * instead of when the mismatched method handle is called.
+ *
+ * @author John Rose, JSR 292 EG
+ * @since 1.7
+ */
+public class WrongMethodTypeException extends RuntimeException {
+    private static final long serialVersionUID = 292L;
+
+    /**
+     * Constructs a {@code WrongMethodTypeException} with no detail message.
+     */
+    public WrongMethodTypeException() {
+        super();
+    }
+
+    /**
+     * Constructs a {@code WrongMethodTypeException} with the specified
+     * detail message.
+     *
+     * @param s the detail message.
+     */
+    public WrongMethodTypeException(String s) {
+        super(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/package-info.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * The {@code java.lang.invoke} package contains dynamic language support provided directly by
+ * the Java core class libraries and virtual machine.
+ *
+ * <p>
+ * Certain types in this package have special relations to dynamic
+ * language support in the virtual machine:
+ * <ul>
+ * <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
+ * <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
+ * which can be linked regardless of their type descriptor.
+ * Normally, method linkage requires exact matching of type descriptors.
+ * </li>
+ *
+ * <li>The JVM bytecode format supports immediate constants of
+ * the classes {@link java.lang.invoke.MethodHandle MethodHandle} and {@link java.lang.invoke.MethodType MethodType}.
+ * </li>
+ * </ul>
+ *
+ * <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2>
+ * <em>The following low-level information is presented here as a preview of
+ * changes being made to the Java Virtual Machine specification for JSR 292.
+ * This information will be incorporated in a future version of the JVM specification.</em>
+ *
+ * <h3><a name="indyinsn"></a>{@code invokedynamic} instruction format</h3>
+ * In bytecode, an {@code invokedynamic} instruction is formatted as five bytes.
+ * The first byte is the opcode 186 (hexadecimal {@code BA}).
+ * The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
+ * The final two bytes are reserved for future use and required to be zero.
+ * The constant pool reference of an {@code invokedynamic} instruction is to a entry
+ * with tag {@code CONSTANT_InvokeDynamic} (decimal 18).  See below for its format.
+ * The entry specifies the following information:
+ * <ul>
+ * <li>a bootstrap method (a {@link java.lang.invoke.MethodHandle MethodHandle} constant)</li>
+ * <li>the dynamic invocation name (a UTF8 string)</li>
+ * <li>the argument and return types of the call (encoded as a type descriptor in a UTF8 string)</li>
+ * <li>optionally, a sequence of additional <em>static arguments</em> to the bootstrap method ({@code ldc}-type constants)</li>
+ * </ul>
+ * <p>
+ * Each instance of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
+ * Multiple instances of an {@code invokedynamic} instruction can share a single
+ * {@code CONSTANT_InvokeDynamic} entry.
+ * In any case, distinct call sites always have distinct linkage state.
+ * <p>
+ * A dynamic call site is originally in an unlinked state.  In this state, there is
+ * no target method for the call site to invoke.
+ * A dynamic call site is linked by means of a bootstrap method,
+ * as <a href="#bsm">described below</a>.
+ *
+ * <h3><a name="indycon"></a>constant pool entries for {@code invokedynamic} instructions</h3>
+ * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
+ * it must contain exactly four more bytes after the tag.
+ * These bytes are interpreted as two 16-bit indexes, in the usual {@code u2} format.
+ * The first pair of bytes after the tag must be an index into a side table called the
+ * <em>bootstrap method table</em>, which is stored in the {@code BootstrapMethods}
+ * attribute as <a href="#bsmattr">described below</a>.
+ * The second pair of bytes must be an index to a {@code CONSTANT_NameAndType}.
+ * <p>
+ * The first index specifies a bootstrap method used by the associated dynamic call sites.
+ * The second index specifies the method name, argument types, and return type of the dynamic call site.
+ * The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
+ * except that the bootstrap method specifier reference replaces
+ * the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
+ *
+ * <h3><a name="mtcon"></a>constant pool entries for {@linkplain java.lang.invoke.MethodType method types}</h3>
+ * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
+ * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
+ * entry which represents a method type descriptor.
+ * <p>
+ * The JVM will ensure that on first
+ * execution of an {@code ldc} instruction for this entry, a {@link java.lang.invoke.MethodType MethodType}
+ * will be created which represents the type descriptor.
+ * Any classes mentioned in the {@code MethodType} will be loaded if necessary,
+ * but not initialized.
+ * Access checking and error reporting is performed exactly as it is for
+ * references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
+ *
+ * <h3><a name="mhcon"></a>constant pool entries for {@linkplain java.lang.invoke.MethodHandle method handles}</h3>
+ * If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
+ * it must contain exactly three more bytes.  The first byte after the tag is a subtag
+ * value which must be in the range 1 through 9, and the last two must be an index to a
+ * {@code CONSTANT_Fieldref}, {@code CONSTANT_Methodref}, or
+ * {@code CONSTANT_InterfaceMethodref} entry which represents a field or method
+ * for which a method handle is to be created.
+ * Furthermore, the subtag value and the type of the constant index value
+ * must agree according to the table below.
+ * <p>
+ * The JVM will ensure that on first execution of an {@code ldc} instruction
+ * for this entry, a {@link java.lang.invoke.MethodHandle MethodHandle} will be created which represents
+ * the field or method reference, according to the specific mode implied by the subtag.
+ * <p>
+ * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
+ * the {@code Class} or {@code MethodType} object which reifies the field or method's
+ * type is created.  Any classes mentioned in this reification will be loaded if necessary,
+ * but not initialized, and access checking and error reporting performed as usual.
+ * <p>
+ * Unlike the reflective {@code Lookup} API, there are no security manager calls made
+ * when these constants are resolved.
+ * <p>
+ * The method handle itself will have a type and behavior determined by the subtag as follows:
+ * <code>
+ * <table border=1 cellpadding=5 summary="CONSTANT_MethodHandle subtypes">
+ * <tr><th>N</th><th>subtag name</th><th>member</th><th>MH type</th><th>bytecode behavior</th><th>lookup expression</th></tr>
+ * <tr><td>1</td><td>REF_getField</td><td>C.f:T</td><td>(C)T</td><td>getfield C.f:T</td>
+ *               <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter findGetter(C.class,"f",T.class)}</td></tr>
+ * <tr><td>2</td><td>REF_getStatic</td><td>C.f:T</td><td>(&nbsp;)T</td><td>getstatic C.f:T</td>
+ *               <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter findStaticGetter(C.class,"f",T.class)}</td></tr>
+ * <tr><td>3</td><td>REF_putField</td><td>C.f:T</td><td>(C,T)void</td><td>putfield C.f:T</td>
+ *               <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter findSetter(C.class,"f",T.class)}</td></tr>
+ * <tr><td>4</td><td>REF_putStatic</td><td>C.f:T</td><td>(T)void</td><td>putstatic C.f:T</td>
+ *               <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter findStaticSetter(C.class,"f",T.class)}</td></tr>
+ * <tr><td>5</td><td>REF_invokeVirtual</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokevirtual C.m(A*)T</td>
+ *               <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
+ * <tr><td>6</td><td>REF_invokeStatic</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokestatic C.m(A*)T</td>
+ *               <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic findStatic(C.class,"m",MT)}</td></tr>
+ * <tr><td>7</td><td>REF_invokeSpecial</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokespecial C.m(A*)T</td>
+ *               <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial findSpecial(C.class,"m",MT,this.class)}</td></tr>
+ * <tr><td>8</td><td>REF_newInvokeSpecial</td><td>C.&lt;init&gt;(A*)void</td><td>(A*)C</td><td>new C; dup; invokespecial C.&lt;init&gt;(A*)void</td>
+ *               <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor findConstructor(C.class,MT)}</td></tr>
+ * <tr><td>9</td><td>REF_invokeInterface</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokeinterface C.m(A*)T</td>
+ *               <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
+ * </table>
+ * </code>
+ * Here, the type {@code C} is taken from the {@code CONSTANT_Class} reference associated
+ * with the {@code CONSTANT_NameAndType} descriptor.
+ * The field name {@code f} or method name {@code m} is taken from the {@code CONSTANT_NameAndType}
+ * as is the result type {@code T} and (in the case of a method or constructor) the argument type sequence
+ * {@code A*}.
+ * <p>
+ * Each method handle constant has an equivalent instruction sequence called its <em>bytecode behavior</em>.
+ * In general, creating a method handle constant can be done in exactly the same circumstances that
+ * the JVM would successfully resolve the symbolic references in the bytecode behavior.
+ * Also, the type of a method handle constant is such that a valid {@code invokeExact} call
+ * on the method handle has exactly the same JVM stack effects as the <em>bytecode behavior</em>.
+ * Finally, calling a method handle constant on a valid set of arguments has exactly the same effect
+ * and returns the same result (if any) as the corresponding <em>bytecode behavior</em>.
+ * <p>
+ * Each method handle constant also has an equivalent reflective <em>lookup expression</em>,
+ * which is a query to a method in {@link java.lang.invoke.MethodHandles.Lookup}.
+ * In the example lookup method expression given in the table above, the name {@code MT}
+ * stands for a {@code MethodType} built from {@code T} and the sequence of argument types {@code A*}.
+ * (Note that the type {@code C} is not prepended to the query type {@code MT} even if the member is non-static.)
+ * In the case of {@code findSpecial}, the name {@code this.class} refers to the class containing
+ * the bytecodes.
+ * <p>
+ * The special name {@code <clinit>} is not allowed.
+ * The special name {@code <init>} is not allowed except for subtag 8 as shown.
+ * <p>
+ * The JVM verifier and linker apply the same access checks and restrictions for these references as for the hypothetical
+ * bytecode instructions specified in the last column of the table.
+ * A method handle constant will successfully resolve to a method handle if the symbolic references
+ * of the corresponding bytecode instruction(s) would also resolve successfully.
+ * Otherwise, an attempt to resolve the constant will throw equivalent linkage errors.
+ * In particular, method handles to
+ * private and protected members can be created in exactly those classes for which the corresponding
+ * normal accesses are legal.
+ * <p>
+ * A constant may refer to a method or constructor with the {@code varargs}
+ * bit (hexadecimal {@code 0x0080}) set in its modifier bitmask.
+ * The method handle constant produced for such a method behaves as if
+ * it were created by {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector}.
+ * In other words, the constant method handle will exhibit variable arity,
+ * when invoked via {@code invokeGeneric}.
+ * On the other hand, its behavior with respect to {@code invokeExact} will be the same
+ * as if the {@code varargs} bit were not set.
+ * <p>
+ * Although the {@code CONSTANT_MethodHandle} and {@code CONSTANT_MethodType} constant types
+ * resolve class names, they do not force class initialization.
+ * Method handle constants for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
+ * may force class initialization on their first invocation, just like the corresponding bytecodes.
+ * <p>
+ * The rules of section 5.4.3 of the
+ * <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#73492">JVM Specification</a>
+ * apply to the resolution of {@code CONSTANT_MethodType}, {@code CONSTANT_MethodHandle},
+ * and {@code CONSTANT_InvokeDynamic} constants,
+ * by the execution of {@code invokedynamic} and {@code ldc} instructions.
+ * (Roughly speaking, this means that every use of a constant pool entry
+ * must lead to the same outcome.
+ * If the resolution succeeds, the same object reference is produced
+ * by every subsequent execution of the same instruction.
+ * If the resolution of the constant causes an error to occur,
+ * the same error will be re-thrown on every subsequent attempt
+ * to use this particular constant.)
+ * <p>
+ * Constants created by the resolution of these constant pool types are not necessarily
+ * interned.  Except for {@code CONSTANT_Class} and {@code CONSTANT_String} entries,
+ * two distinct constant pool entries might not resolve to the same reference
+ * even if they contain the same symbolic reference.
+ *
+ * <h2><a name="bsm"></a>Bootstrap Methods</h2>
+ * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
+ * the call site must first be <em>linked</em>.
+ * Linking is accomplished by calling a <em>bootstrap method</em>
+ * which is given the static information content of the call site,
+ * and which must produce a {@link java.lang.invoke.MethodHandle method handle}
+ * that gives the behavior of the call site.
+ * <p>
+ * Each {@code invokedynamic} instruction statically specifies its own
+ * bootstrap method as a constant pool reference.
+ * The constant pool reference also specifies the call site's name and type descriptor,
+ * just like {@code invokevirtual} and the other invoke instructions.
+ * <p>
+ * Linking starts with resolving the constant pool entry for the
+ * bootstrap method, and resolving a {@link java.lang.invoke.MethodType MethodType} object for
+ * the type descriptor of the dynamic call site.
+ * This resolution process may trigger class loading.
+ * It may therefore throw an error if a class fails to load.
+ * This error becomes the abnormal termination of the dynamic
+ * call site execution.
+ * Linkage does not trigger class initialization.
+ * <p>
+ * Next, the bootstrap method call is started, with at least four values being stacked:
+ * <ul>
+ * <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
+ * <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em> in which dynamic call site occurs </li>
+ * <li>a {@code String}, the method name mentioned in the call site </li>
+ * <li>a {@code MethodType}, the resolved type descriptor of the call </li>
+ * <li>optionally, one or more <a href="#args">additional static arguments</a> </li>
+ * </ul>
+ * The method handle is then applied to the other values as if by
+ * {@link java.lang.invoke.MethodHandle#invokeGeneric invokeGeneric}.
+ * The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass).
+ * The type of the call site's target must be exactly equal to the type
+ * derived from the dynamic call site's type descriptor and passed to
+ * the bootstrap method.
+ * The call site then becomes permanently linked to the dynamic call site.
+ * <p>
+ * As long as each bootstrap method can be correctly invoked
+ * by <code>invokeGeneric</code>, its detailed type is arbitrary.
+ * For example, the first argument could be {@code Object}
+ * instead of {@code MethodHandles.Lookup}, and the return type
+ * could also be {@code Object} instead of {@code CallSite}.
+ * (Note that the types and number of the stacked arguments limit
+ * the legal kinds of bootstrap methods to appropriately typed
+ * static methods and constructors of {@code CallSite} subclasses.)
+ * <p>
+ * After resolution, the linkage process may fail in a variety of ways.
+ * All failures are reported by a {@link java.lang.BootstrapMethodError BootstrapMethodError},
+ * which is thrown as the abnormal termination of the dynamic call
+ * site execution.
+ * The following circumstances will cause this:
+ * <ul>
+ * <li>the index to the bootstrap method specifier is out of range </li>
+ * <li>the bootstrap method cannot be resolved </li>
+ * <li>the {@code MethodType} to pass to the bootstrap method cannot be resolved </li>
+ * <li>a static argument to the bootstrap method cannot be resolved
+ *     (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType},
+ *     or {@code CONSTANT_MethodHandle} argument cannot be linked) </li>
+ * <li>the bootstrap method has the wrong arity,
+ *     causing {@code invokeGeneric} to throw {@code WrongMethodTypeException} </li>
+ * <li>the bootstrap method has a wrong argument or return type </li>
+ * <li>the bootstrap method invocation completes abnormally </li>
+ * <li>the result from the bootstrap invocation is not a reference to
+ *     an object of type {@link java.lang.invoke.CallSite CallSite} </li>
+ * <li>the target of the {@code CallSite} does not have a target of
+ *     the expected {@code MethodType} </li>
+ * </ul>
+ *
+ * <h3><a name="linktime"></a>timing of linkage</h3>
+ * A dynamic call site is linked just before its first execution.
+ * The bootstrap method call implementing the linkage occurs within
+ * a thread that is attempting a first execution.
+ * <p>
+ * If there are several such threads, the bootstrap method may be
+ * invoked in several threads concurrently.
+ * Therefore, bootstrap methods which access global application
+ * data must take the usual precautions against race conditions.
+ * In any case, every {@code invokedynamic} instruction is either
+ * unlinked or linked to a unique {@code CallSite} object.
+ * <p>
+ * In an application which requires dynamic call sites with individually
+ * mutable behaviors, their bootstrap methods should produce distinct
+ * {@link java.lang.invoke.CallSite CallSite} objects, one for each linkage request.
+ * Alternatively, an application can link a single {@code CallSite} object
+ * to several {@code invokedynamic} instructions, in which case
+ * a change to the target method will become visible at each of
+ * the instructions.
+ * <p>
+ * If several threads simultaneously execute a bootstrap method for a single dynamic
+ * call site, the JVM must choose one {@code CallSite} object and install it visibly to
+ * all threads.  Any other bootstrap method calls are allowed to complete, but their
+ * results are ignored, and their dynamic call site invocations proceed with the originally
+ * chosen target object.
+ *
+ * <p style="font-size:smaller;">
+ * <em>Discussion:</em>
+ * These rules do not enable the JVM to duplicate dynamic call sites,
+ * or to issue &ldquo;causeless&rdquo; bootstrap method calls.
+ * Every dynamic call site transitions at most once from unlinked to linked,
+ * just before its first invocation.
+ * There is no way to undo the effect of a completed bootstrap method call.
+ *
+ * <h3><a name="bsmattr">the {@code BootstrapMethods} attribute </h3>
+ * Each {@code CONSTANT_InvokeDynamic} entry contains an index which references
+ * a bootstrap method specifier; all such specifiers are contained in a separate array.
+ * This array is defined by a class attribute named {@code BootstrapMethods}.
+ * The body of this attribute consists of a sequence of byte pairs, all interpreted as
+ * as 16-bit counts or constant pool indexes, in the {@code u2} format.
+ * The attribute body starts with a count of bootstrap method specifiers,
+ * which is immediately followed by the sequence of specifiers.
+ * <p>
+ * Each bootstrap method specifier contains an index to a
+ * {@code CONSTANT_MethodHandle} constant, which is the bootstrap
+ * method itself.
+ * This is followed by a count, and then a sequence (perhaps empty) of
+ * indexes to <a href="#args">additional static arguments</a>
+ * for the bootstrap method.
+ * <p>
+ * During class loading, the verifier must check the structure of the
+ * {@code BootstrapMethods} attribute.  In particular, each constant
+ * pool index must be of the correct type.  A bootstrap method index
+ * must refer to a {@code CONSTANT_MethodHandle} (tag 15).
+ * Every other index must refer to a valid operand of an
+ * {@code ldc_w} or {@code ldc2_w} instruction (tag 3..8 or 15..16).
+ *
+ * <h3><a name="args">static arguments to the bootstrap method</h3>
+ * An {@code invokedynamic} instruction specifies at least three arguments
+ * to pass to its bootstrap method:
+ * The caller class (expressed as a {@link java.lang.invoke.MethodHandles.Lookup Lookup object},
+ * the name (extracted from the {@code CONSTANT_NameAndType} entry),
+ * and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
+ * The {@code invokedynamic} instruction may specify additional metadata values
+ * to pass to its bootstrap method.
+ * Collectively, these values are called <em>static arguments</em> to the
+ * {@code invokedynamic} instruction, because they are used once at link
+ * time to determine the instruction's behavior on subsequent sets of
+ * <em>dynamic arguments</em>.
+ * <p>
+ * Static arguments are used to communicate application-specific meta-data
+ * to the bootstrap method.
+ * Drawn from the constant pool, they may include references to classes, method handles,
+ * strings, or numeric data that may be relevant to the task of linking that particular call site.
+ * <p>
+ * Static arguments are specified constant pool indexes stored in the {@code BootstrapMethods} attribute.
+ * Before the bootstrap method is invoked, each index is used to compute an {@code Object}
+ * reference to the indexed value in the constant pool.
+ * The valid constant pool entries are listed in this table:
+ * <code>
+ * <table border=1 cellpadding=5 summary="Static argument types">
+ * <tr><th>entry type</th><th>argument type</th><th>argument value</th></tr>
+ * <tr><td>CONSTANT_String</td><td><code>java.lang.String</code></td><td>the indexed string literal</td></tr>
+ * <tr><td>CONSTANT_Class</td><td><code>java.lang.Class</code></td><td>the indexed class, resolved</td></tr>
+ * <tr><td>CONSTANT_Integer</td><td><code>java.lang.Integer</code></td><td>the indexed int value</td></tr>
+ * <tr><td>CONSTANT_Long</td><td><code>java.lang.Long</code></td><td>the indexed long value</td></tr>
+ * <tr><td>CONSTANT_Float</td><td><code>java.lang.Float</code></td><td>the indexed float value</td></tr>
+ * <tr><td>CONSTANT_Double</td><td><code>java.lang.Double</code></td><td>the indexed double value</td></tr>
+ * <tr><td>CONSTANT_MethodHandle</td><td><code>java.lang.invoke.MethodHandle</code></td><td>the indexed method handle constant</td></tr>
+ * <tr><td>CONSTANT_MethodType</td><td><code>java.lang.invoke.MethodType</code></td><td>the indexed method type constant</td></tr>
+ * </table>
+ * </code>
+ * <p>
+ * If a given {@code invokedynamic} instruction specifies no static arguments,
+ * the instruction's bootstrap method will be invoked on three arguments,
+ * conveying the instruction's caller class, name, and method type.
+ * If the {@code invokedynamic} instruction specifies one or more static arguments,
+ * those values will be passed as additional arguments to the method handle.
+ * (Note that because there is a limit of 255 arguments to any method,
+ * at most 252 extra arguments can be supplied.)
+ * The bootstrap method will be invoked as if by either {@code invokeGeneric}
+ * or {@code invokeWithArguments}.  (There is no way to tell the difference.)
+ * <p>
+ * The normal argument conversion rules for {@code invokeGeneric} apply to all stacked arguments.
+ * For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion.
+ * If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set),
+ * then some or all of the arguments specified here may be collected into a trailing array parameter.
+ * (This is not a special rule, but rather a useful consequence of the interaction
+ * between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
+ * and the {@code java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
+ * <p>
+ * Given these rules, here are examples of legal bootstrap method declarations,
+ * given various numbers {@code N} of extra arguments.
+ * The first rows (marked {@code *}) will work for any number of extra arguments.
+ * <code>
+ * <table border=1 cellpadding=5 summary="Static argument types">
+ * <tr><th>N</th><th>sample bootstrap method</th></tr>
+ * <tr><td>*</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
+ * <tr><td>*</td><td><code>CallSite bootstrap(Object... args)</code></td></tr>
+ * <tr><td>*</td><td><code>CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)</code></td></tr>
+ * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type)</code></td></tr>
+ * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, Object... nameAndType)</code></td></tr>
+ * <tr><td>1</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)</code></td></tr>
+ * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
+ * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)</code></td></tr>
+ * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)</code></td></tr>
+ * </table>
+ * </code>
+ * The last example assumes that the extra arguments are of type
+ * {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively.
+ * The second-to-last example assumes that all extra arguments are of type
+ * {@code CONSTANT_String}.
+ * The other examples work with all types of extra arguments.
+ * <p>
+ * As noted above, the actual method type of the bootstrap method can vary.
+ * For example, the fourth argument could be {@code MethodHandle},
+ * if that is the type of the corresponding constant in
+ * the {@code CONSTANT_InvokeDynamic} entry.
+ * In that case, the {@code invokeGeneric} call will pass the extra method handle
+ * constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric}
+ * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
+ * (If a string constant were passed instead, by badly generated code, that cast would then fail,
+ * resulting in a {@code BootstrapMethodError}.)
+ * <p>
+ * Extra bootstrap method arguments are intended to allow language implementors
+ * to safely and compactly encode metadata.
+ * In principle, the name and extra arguments are redundant,
+ * since each call site could be given its own unique bootstrap method.
+ * Such a practice is likely to produce large class files and constant pools.
+ *
+ * <h2><a name="structs"></a>Structure Summary</h2>
+ * <blockquote><pre>// summary of constant and attribute structures
+struct CONSTANT_MethodHandle_info {
+  u1 tag = 15;
+  u1 reference_kind;       // 1..8 (one of REF_invokeVirtual, etc.)
+  u2 reference_index;      // index to CONSTANT_Fieldref or *Methodref
+}
+struct CONSTANT_MethodType_info {
+  u1 tag = 16;
+  u2 descriptor_index;    // index to CONSTANT_Utf8, as in NameAndType
+}
+struct CONSTANT_InvokeDynamic_info {
+  u1 tag = 18;
+  u2 bootstrap_method_attr_index;  // index into BootstrapMethods_attr
+  u2 name_and_type_index;          // index to CONSTANT_NameAndType, as in Methodref
+}
+struct BootstrapMethods_attr {
+ u2 name;  // CONSTANT_Utf8 = "BootstrapMethods"
+ u4 size;
+ u2 bootstrap_method_count;
+ struct bootstrap_method_specifier {
+   u2 bootstrap_method_ref;  // index to CONSTANT_MethodHandle
+   u2 bootstrap_argument_count;
+   u2 bootstrap_arguments[bootstrap_argument_count];  // constant pool indexes
+ } bootstrap_methods[bootstrap_method_count];
+}
+ * </pre></blockquote>
+ *
+ * @author John Rose, JSR 292 EG
+ * @since 1.7
+ */
+
+package java.lang.invoke;
--- a/jdk/src/share/classes/sun/dyn/Access.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import sun.reflect.Reflection;
-
-/**
- * Access control to this package.
- * Classes in other packages can attempt to acquire the access token,
- * but will fail if they are not recognized as friends.
- * Certain methods in this package, although public, require a non-null
- * access token in order to proceed; they act like package-private methods.
- * @author jrose
- */
-
-public class Access {
-
-    private Access() { }
-
-    /**
-     * The heart of this pattern:  The list of classes which are
-     * permitted to acquire the access token, and become honorary
-     * members of this package.
-     */
-    private static final String[] FRIENDS = {
-        "java.dyn.", "sun.dyn."
-    };
-
-    /**
-     * The following object is NOT public.  That's the point of the pattern.
-     * It is package-private, so that any member of this package
-     * can acquire the access token, and give it away to trusted friends.
-     */
-    static final Access TOKEN = new Access();
-
-    /**
-     * @return Access.TOKEN, if the caller is a friend of this package
-     */
-    public static Access getToken() {
-        Class<?> callc = Reflection.getCallerClass(2);
-        if (isFriend(callc))
-            return TOKEN;
-        else
-            throw new IllegalAccessError("bad caller: " + callc);
-    }
-
-    /** Is the given name the name of a class which could be our friend? */
-    public static boolean isFriendName(String name) {
-        for (String friend : FRIENDS) {
-            if (name.startsWith(friend))
-                return true;
-        }
-        return false;
-    }
-
-    /** Is the given class a friend?  True if {@link #isFriendName},
-     *  and the given class also shares a class loader with us.
-     */
-    public static boolean isFriend(Class<?> c) {
-        return isFriendName(c.getName()) && c.getClassLoader() == CLASS_LOADER;
-    }
-
-    private static final ClassLoader CLASS_LOADER = Access.class.getClassLoader();
-
-    /**
-     * Throw an IllegalAccessError if the caller does not possess
-     * the Access.TOKEN.
-     * @param must be Access.TOKEN
-     */
-    public static void check(Access token) {
-        if (token == null)
-            fail();
-        // else it must be the unique Access.TOKEN
-        assert(token == Access.TOKEN);
-    }
-    private static void fail() {
-        final int CALLER_DEPTH = 3;
-        // 0: Reflection.getCC, 1: this.fail, 2: Access.*, 3: caller
-        Class<?> callc = Reflection.getCallerClass(CALLER_DEPTH);
-        throw new IllegalAccessError("bad caller: " + callc);
-    }
-
-    static {
-        //sun.reflect.Reflection.registerMethodsToFilter(MH.class, "getToken");
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,974 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import sun.dyn.util.VerifyType;
-import sun.dyn.util.Wrapper;
-import java.dyn.*;
-import java.util.Arrays;
-import static sun.dyn.MethodHandleNatives.Constants.*;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-
-/**
- * This method handle performs simple conversion or checking of a single argument.
- * @author jrose
- */
-public class AdapterMethodHandle extends BoundMethodHandle {
-
-    //MethodHandle vmtarget;   // next AMH or BMH in chain or final DMH
-    //Object       argument;   // parameter to the conversion if needed
-    //int          vmargslot;  // which argument slot is affected
-    private final int conversion;  // the type of conversion: RETYPE_ONLY, etc.
-
-    // Constructors in this class *must* be package scoped or private.
-    private AdapterMethodHandle(MethodHandle target, MethodType newType,
-                long conv, Object convArg) {
-        super(newType, convArg, newType.parameterSlotDepth(1+convArgPos(conv)));
-        this.conversion = convCode(conv);
-        if (MethodHandleNatives.JVM_SUPPORT) {
-            // JVM might update VM-specific bits of conversion (ignore)
-            MethodHandleNatives.init(this, target, convArgPos(conv));
-        }
-    }
-    private AdapterMethodHandle(MethodHandle target, MethodType newType,
-                long conv) {
-        this(target, newType, conv, null);
-    }
-
-    private static final Access IMPL_TOKEN = Access.getToken();
-
-    // TO DO:  When adapting another MH with a null conversion, clone
-    // the target and change its type, instead of adding another layer.
-
-    /** Can a JVM-level adapter directly implement the proposed
-     *  argument conversions, as if by MethodHandles.convertArguments?
-     */
-    public static boolean canPairwiseConvert(MethodType newType, MethodType oldType) {
-        // same number of args, of course
-        int len = newType.parameterCount();
-        if (len != oldType.parameterCount())
-            return false;
-
-        // Check return type.  (Not much can be done with it.)
-        Class<?> exp = newType.returnType();
-        Class<?> ret = oldType.returnType();
-        if (!VerifyType.isNullConversion(ret, exp))
-            return false;
-
-        // Check args pairwise.
-        for (int i = 0; i < len; i++) {
-            Class<?> src = newType.parameterType(i); // source type
-            Class<?> dst = oldType.parameterType(i); // destination type
-            if (!canConvertArgument(src, dst))
-                return false;
-        }
-
-        return true;
-    }
-
-    /** Can a JVM-level adapter directly implement the proposed
-     *  argument conversion, as if by MethodHandles.convertArguments?
-     */
-    public static boolean canConvertArgument(Class<?> src, Class<?> dst) {
-        // ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
-        // so we don't need to repeat so much decision making.
-        if (VerifyType.isNullConversion(src, dst)) {
-            return true;
-        } else if (src.isPrimitive()) {
-            if (dst.isPrimitive())
-                return canPrimCast(src, dst);
-            else
-                return canBoxArgument(src, dst);
-        } else {
-            if (dst.isPrimitive())
-                return canUnboxArgument(src, dst);
-            else
-                return true;  // any two refs can be interconverted
-        }
-    }
-
-    /**
-     * Create a JVM-level adapter method handle to conform the given method
-     * handle to the similar newType, using only pairwise argument conversions.
-     * For each argument, convert incoming argument to the exact type needed.
-     * Only null conversions are allowed on the return value (until
-     * the JVM supports ricochet adapters).
-     * The argument conversions allowed are casting, unboxing,
-     * integral widening or narrowing, and floating point widening or narrowing.
-     * @param token access check
-     * @param newType required call type
-     * @param target original method handle
-     * @return an adapter to the original handle with the desired new type,
-     *          or the original target if the types are already identical
-     *          or null if the adaptation cannot be made
-     */
-    public static MethodHandle makePairwiseConvert(Access token,
-                MethodType newType, MethodHandle target) {
-        Access.check(token);
-        MethodType oldType = target.type();
-        if (newType == oldType)  return target;
-
-        if (!canPairwiseConvert(newType, oldType))
-            return null;
-        // (after this point, it is an assertion error to fail to convert)
-
-        // Find last non-trivial conversion (if any).
-        int lastConv = newType.parameterCount()-1;
-        while (lastConv >= 0) {
-            Class<?> src = newType.parameterType(lastConv); // source type
-            Class<?> dst = oldType.parameterType(lastConv); // destination type
-            if (VerifyType.isNullConversion(src, dst)) {
-                --lastConv;
-            } else {
-                break;
-            }
-        }
-        // Now build a chain of one or more adapters.
-        MethodHandle adapter = target;
-        MethodType midType = oldType.changeReturnType(newType.returnType());
-        for (int i = 0; i <= lastConv; i++) {
-            Class<?> src = newType.parameterType(i); // source type
-            Class<?> dst = midType.parameterType(i); // destination type
-            if (VerifyType.isNullConversion(src, dst)) {
-                // do nothing: difference is trivial
-                continue;
-            }
-            // Work the current type backward toward the desired caller type:
-            if (i != lastConv) {
-                midType = midType.changeParameterType(i, src);
-            } else {
-                // When doing the last (or only) real conversion,
-                // force all remaining null conversions to happen also.
-                assert(VerifyType.isNullConversion(newType, midType.changeParameterType(i, src)));
-                midType = newType;
-            }
-
-            // Tricky case analysis follows.
-            // It parallels canConvertArgument() above.
-            if (src.isPrimitive()) {
-                if (dst.isPrimitive()) {
-                    adapter = makePrimCast(token, midType, adapter, i, dst);
-                } else {
-                    adapter = makeBoxArgument(token, midType, adapter, i, dst);
-                }
-            } else {
-                if (dst.isPrimitive()) {
-                    // Caller has boxed a primitive.  Unbox it for the target.
-                    // The box type must correspond exactly to the primitive type.
-                    // This is simpler than the powerful set of widening
-                    // conversions supported by reflect.Method.invoke.
-                    // Those conversions require a big nest of if/then/else logic,
-                    // which we prefer to make a user responsibility.
-                    adapter = makeUnboxArgument(token, midType, adapter, i, dst);
-                } else {
-                    // Simple reference conversion.
-                    // Note:  Do not check for a class hierarchy relation
-                    // between src and dst.  In all cases a 'null' argument
-                    // will pass the cast conversion.
-                    adapter = makeCheckCast(token, midType, adapter, i, dst);
-                }
-            }
-            assert(adapter != null);
-            assert(adapter.type() == midType);
-        }
-        if (adapter.type() != newType) {
-            // Only trivial conversions remain.
-            adapter = makeRetypeOnly(IMPL_TOKEN, newType, adapter);
-            assert(adapter != null);
-            // Actually, that's because there were no non-trivial ones:
-            assert(lastConv == -1);
-        }
-        assert(adapter.type() == newType);
-        return adapter;
-    }
-
-    /**
-     * Create a JVM-level adapter method handle to permute the arguments
-     * of the given method.
-     * @param token access check
-     * @param newType required call type
-     * @param target original method handle
-     * @param argumentMap for each target argument, position of its source in newType
-     * @return an adapter to the original handle with the desired new type,
-     *          or the original target if the types are already identical
-     *          and the permutation is null
-     * @throws IllegalArgumentException if the adaptation cannot be made
-     *          directly by a JVM-level adapter, without help from Java code
-     */
-    public static MethodHandle makePermutation(Access token,
-                MethodType newType, MethodHandle target,
-                int[] argumentMap) {
-        MethodType oldType = target.type();
-        boolean nullPermutation = true;
-        for (int i = 0; i < argumentMap.length; i++) {
-            int pos = argumentMap[i];
-            if (pos != i)
-                nullPermutation = false;
-            if (pos < 0 || pos >= newType.parameterCount()) {
-                argumentMap = new int[0]; break;
-            }
-        }
-        if (argumentMap.length != oldType.parameterCount())
-            throw newIllegalArgumentException("bad permutation: "+Arrays.toString(argumentMap));
-        if (nullPermutation) {
-            MethodHandle res = makePairwiseConvert(token, newType, target);
-            // well, that was easy
-            if (res == null)
-                throw newIllegalArgumentException("cannot convert pairwise: "+newType);
-            return res;
-        }
-
-        // Check return type.  (Not much can be done with it.)
-        Class<?> exp = newType.returnType();
-        Class<?> ret = oldType.returnType();
-        if (!VerifyType.isNullConversion(ret, exp))
-            throw newIllegalArgumentException("bad return conversion for "+newType);
-
-        // See if the argument types match up.
-        for (int i = 0; i < argumentMap.length; i++) {
-            int j = argumentMap[i];
-            Class<?> src = newType.parameterType(j);
-            Class<?> dst = oldType.parameterType(i);
-            if (!VerifyType.isNullConversion(src, dst))
-                throw newIllegalArgumentException("bad argument #"+j+" conversion for "+newType);
-        }
-
-        // Now figure out a nice mix of SWAP, ROT, DUP, and DROP adapters.
-        // A workable greedy algorithm is as follows:
-        // Drop unused outgoing arguments (right to left: shallowest first).
-        // Duplicate doubly-used outgoing arguments (left to right: deepest first).
-        // Then the remaining problem is a true argument permutation.
-        // Marshal the outgoing arguments as required from left to right.
-        // That is, find the deepest outgoing stack position that does not yet
-        // have the correct argument value, and correct at least that position
-        // by swapping or rotating in the misplaced value (from a shallower place).
-        // If the misplaced value is followed by one or more consecutive values
-        // (also misplaced)  issue a rotation which brings as many as possible
-        // into position.  Otherwise make progress with either a swap or a
-        // rotation.  Prefer the swap as cheaper, but do not use it if it
-        // breaks a slot pair.  Prefer the rotation over the swap if it would
-        // preserve more consecutive values shallower than the target position.
-        // When more than one rotation will work (because the required value
-        // is already adjacent to the target position), then use a rotation
-        // which moves the old value in the target position adjacent to
-        // one of its consecutive values.  Also, prefer shorter rotation
-        // spans, since they use fewer memory cycles for shuffling.
-
-        throw new UnsupportedOperationException("NYI");
-    }
-
-    private static byte basicType(Class<?> type) {
-        if (type == null)  return T_VOID;
-        switch (Wrapper.forBasicType(type)) {
-            case BOOLEAN:  return T_BOOLEAN;
-            case CHAR:     return T_CHAR;
-            case FLOAT:    return T_FLOAT;
-            case DOUBLE:   return T_DOUBLE;
-            case BYTE:     return T_BYTE;
-            case SHORT:    return T_SHORT;
-            case INT:      return T_INT;
-            case LONG:     return T_LONG;
-            case OBJECT:   return T_OBJECT;
-            case VOID:     return T_VOID;
-        }
-        return 99; // T_ILLEGAL or some such
-    }
-
-    /** Number of stack slots for the given type.
-     *  Two for T_DOUBLE and T_FLOAT, one for the rest.
-     */
-    private static int type2size(int type) {
-        assert(type >= T_BOOLEAN && type <= T_OBJECT);
-        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. */
-    private static long makeConv(int convOp, int argnum, int src, int dest) {
-        assert(src  == (src  & 0xF));
-        assert(dest == (dest & 0xF));
-        assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF);
-        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 |
-                insertStackMove(stackMove)
-                );
-    }
-    private static long makeConv(int convOp, int argnum, int stackMove) {
-        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;
-        return ((long) argnum << 32 |
-                (long) convOp << CONV_OP_SHIFT |
-                (int)  src    << CONV_SRC_TYPE_SHIFT |
-                (int)  dest   << CONV_DEST_TYPE_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 || 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;
-    }
-    private static int convArgPos(long conv) {
-        return (int)(conv >>> 32);
-    }
-    private static boolean convOpSupported(int convOp) {
-        assert(convOp >= 0 && convOp <= CONV_OP_LIMIT);
-        return ((1<<convOp) & MethodHandleNatives.CONV_OP_IMPLEMENTED_MASK) != 0;
-    }
-
-    /** One of OP_RETYPE_ONLY, etc. */
-    int conversionOp() { return (conversion & CONV_OP_MASK) >> CONV_OP_SHIFT; }
-
-    /* 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.
-     * Trivial differences are those which could be ignored by the JVM
-     * without subverting the verifier.  Otherwise, adaptable differences
-     * are ones for which we could create an adapter to make the type change.
-     * Return zero if there are no differences (other than trivial ones).
-     * Return 1+N if N is the only adaptable argument difference.
-     * Return the -2-N where N is the first of several adaptable
-     * argument differences.
-     * Return -1 if there there are differences which are not adaptable.
-     */
-    private static int diffTypes(MethodType adapterType,
-                                 MethodType targetType,
-                                 boolean raw) {
-        int diff;
-        diff = diffReturnTypes(adapterType, targetType, raw);
-        if (diff != 0)  return diff;
-        int nargs = adapterType.parameterCount();
-        if (nargs != targetType.parameterCount())
-            return -1;
-        diff = diffParamTypes(adapterType, 0, targetType, 0, nargs, raw);
-        //System.out.println("diff "+adapterType);
-        //System.out.println("  "+diff+" "+targetType);
-        return diff;
-    }
-    private static int diffReturnTypes(MethodType adapterType,
-                                       MethodType targetType,
-                                       boolean raw) {
-        Class<?> src = targetType.returnType();
-        Class<?> dst = adapterType.returnType();
-        if ((!raw
-             ? VerifyType.canPassUnchecked(src, dst)
-             : VerifyType.canPassRaw(src, dst)
-             ) > 0)
-            return 0;  // no significant difference
-        if (raw && !src.isPrimitive() && !dst.isPrimitive())
-            return 0;  // can force a reference return (very carefully!)
-        //if (false)  return 1;  // never adaptable!
-        return -1;  // some significant difference
-    }
-    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(astart+i);
-            Class<?> dest = targetType.parameterType(tstart+i);
-            if ((!raw
-                 ? VerifyType.canPassUnchecked(src, dest)
-                 : VerifyType.canPassRaw(src, dest)
-                ) <= 0) {
-                // found a difference; is it the only one so far?
-                if (res != 0)
-                    return -1-res; // return -2-i for prev. i
-                res = 1+i;
-            }
-        }
-        return res;
-    }
-
-    /** Can a retyping adapter (alone) validly convert the target to newType? */
-    public static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
-        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
-     *  conversions between float/int and double/long, and to perform unchecked
-     *  reference conversions on return.  This last feature requires that the
-     *  caller be trusted, and perform explicit cast conversions on return values.
-     */
-    public static boolean canRetypeRaw(MethodType newType, MethodType targetType) {
-        return canRetype(newType, targetType, true);
-    }
-    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(raw || (diff == 0) == VerifyType.isNullConversion(newType, targetType));
-        return diff == 0;
-    }
-
-    /** Factory method:  Performs no conversions; simply retypes the adapter.
-     *  Allows unchecked argument conversions pairwise, if they are safe.
-     *  Returns null if not possible.
-     */
-    public static MethodHandle makeRetypeOnly(Access token,
-                MethodType newType, MethodHandle target) {
-        return makeRetype(token, newType, target, false);
-    }
-    public static MethodHandle makeRetypeRaw(Access token,
-                MethodType newType, MethodHandle target) {
-        return makeRetype(token, newType, target, true);
-    }
-    static MethodHandle makeRetype(Access token,
-                MethodType newType, MethodHandle target, boolean raw) {
-        Access.check(token);
-        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(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY));
-    }
-
-    static MethodHandle makeVarargsCollector(Access token,
-                MethodHandle target, Class<?> arrayType) {
-        Access.check(token);
-        return new AsVarargsCollector(target, arrayType);
-    }
-
-    static class AsVarargsCollector extends AdapterMethodHandle {
-        final MethodHandle target;
-        final Class<?> arrayType;
-        MethodHandle cache;
-
-        AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
-            super(target, target.type(), makeConv(OP_RETYPE_ONLY));
-            this.target = target;
-            this.arrayType = arrayType;
-            this.cache = target.asCollector(arrayType, 0);
-        }
-
-        @Override
-        public boolean isVarargsCollector() {
-            return true;
-        }
-
-        @Override
-        public MethodHandle asType(MethodType newType) {
-            MethodType type = this.type();
-            int collectArg = type.parameterCount() - 1;
-            int newArity = newType.parameterCount();
-            if (newArity == collectArg+1 &&
-                type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
-                // if arity and trailing parameter are compatible, do normal thing
-                return super.asType(newType);
-            }
-            // check cache
-            if (cache.type().parameterCount() == newArity)
-                return cache.asType(newType);
-            // build and cache a collector
-            int arrayLength = newArity - collectArg;
-            MethodHandle collector;
-            try {
-                collector = target.asCollector(arrayType, arrayLength);
-            } catch (IllegalArgumentException ex) {
-                throw new WrongMethodTypeException("cannot build collector");
-            }
-            cache = collector;
-            return collector.asType(newType);
-        }
-
-        public MethodHandle asVarargsCollector(Class<?> arrayType) {
-            MethodType type = this.type();
-            if (type.parameterType(type.parameterCount()-1) == arrayType)
-                return this;
-            return super.asVarargsCollector(arrayType);
-        }
-    }
-
-    /** Can a checkcast adapter validly convert the target to newType?
-     *  The JVM supports all kind of reference casts, even silly ones.
-     */
-    public static boolean canCheckCast(MethodType newType, MethodType targetType,
-                int arg, Class<?> castType) {
-        if (!convOpSupported(OP_CHECK_CAST))  return false;
-        Class<?> src = newType.parameterType(arg);
-        Class<?> dst = targetType.parameterType(arg);
-        if (!canCheckCast(src, castType)
-                || !VerifyType.isNullConversion(castType, dst))
-            return false;
-        int diff = diffTypes(newType, targetType, false);
-        return (diff == arg+1);  // arg is sole non-trivial diff
-    }
-    /** Can an primitive conversion adapter validly convert src to dst? */
-    public static boolean canCheckCast(Class<?> src, Class<?> dst) {
-        return (!src.isPrimitive() && !dst.isPrimitive());
-    }
-
-    /** Factory method:  Forces a cast at the given argument.
-     *  The castType is the target of the cast, and can be any type
-     *  with a null conversion to the corresponding target parameter.
-     *  Return null if this cannot be done.
-     */
-    public static MethodHandle makeCheckCast(Access token,
-                MethodType newType, MethodHandle target,
-                int arg, Class<?> castType) {
-        Access.check(token);
-        if (!canCheckCast(newType, target.type(), arg, castType))
-            return null;
-        long conv = makeConv(OP_CHECK_CAST, arg, T_OBJECT, T_OBJECT);
-        return new AdapterMethodHandle(target, newType, conv, castType);
-    }
-
-    /** Can an primitive conversion adapter validly convert the target to newType?
-     *  The JVM currently supports all conversions except those between
-     *  floating and integral types.
-     */
-    public static boolean canPrimCast(MethodType newType, MethodType targetType,
-                int arg, Class<?> convType) {
-        if (!convOpSupported(OP_PRIM_TO_PRIM))  return false;
-        Class<?> src = newType.parameterType(arg);
-        Class<?> dst = targetType.parameterType(arg);
-        if (!canPrimCast(src, convType)
-                || !VerifyType.isNullConversion(convType, dst))
-            return false;
-        int diff = diffTypes(newType, targetType, false);
-        return (diff == arg+1);  // arg is sole non-trivial diff
-    }
-    /** Can an primitive conversion adapter validly convert src to dst? */
-    public static boolean canPrimCast(Class<?> src, Class<?> dst) {
-        if (src == dst || !src.isPrimitive() || !dst.isPrimitive()) {
-            return false;
-        } else if (Wrapper.forPrimitiveType(dst).isFloating()) {
-            // both must be floating types
-            return Wrapper.forPrimitiveType(src).isFloating();
-        } else {
-            // both are integral, and all combinations work fine
-            assert(Wrapper.forPrimitiveType(src).isIntegral() &&
-                   Wrapper.forPrimitiveType(dst).isIntegral());
-            return true;
-        }
-    }
-
-    /** Factory method:  Truncate the given argument with zero or sign extension,
-     *  and/or convert between single and doubleword versions of integer or float.
-     *  The convType is the target of the conversion, and can be any type
-     *  with a null conversion to the corresponding target parameter.
-     *  Return null if this cannot be done.
-     */
-    public static MethodHandle makePrimCast(Access token,
-                MethodType newType, MethodHandle target,
-                int arg, Class<?> convType) {
-        Access.check(token);
-        MethodType oldType = target.type();
-        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);
-    }
-
-    /** Can an unboxing conversion validly convert src to dst?
-     *  The JVM currently supports all kinds of casting and unboxing.
-     *  The convType is the unboxed type; it can be either a primitive or wrapper.
-     */
-    public static boolean canUnboxArgument(MethodType newType, MethodType targetType,
-                int arg, Class<?> convType) {
-        if (!convOpSupported(OP_REF_TO_PRIM))  return false;
-        Class<?> src = newType.parameterType(arg);
-        Class<?> dst = targetType.parameterType(arg);
-        Class<?> boxType = Wrapper.asWrapperType(convType);
-        convType = Wrapper.asPrimitiveType(convType);
-        if (!canCheckCast(src, boxType)
-                || boxType == convType
-                || !VerifyType.isNullConversion(convType, dst))
-            return false;
-        int diff = diffTypes(newType, targetType, false);
-        return (diff == arg+1);  // arg is sole non-trivial diff
-    }
-    /** Can an primitive unboxing adapter validly convert src to dst? */
-    public static boolean canUnboxArgument(Class<?> src, Class<?> dst) {
-        return (!src.isPrimitive() && Wrapper.asPrimitiveType(dst).isPrimitive());
-    }
-
-    /** Factory method:  Unbox the given argument.
-     *  Return null if this cannot be done.
-     */
-    public static MethodHandle makeUnboxArgument(Access token,
-                MethodType newType, MethodHandle target,
-                int arg, Class<?> convType) {
-        MethodType oldType = target.type();
-        Class<?> src = newType.parameterType(arg);
-        Class<?> dst = oldType.parameterType(arg);
-        Class<?> boxType = Wrapper.asWrapperType(convType);
-        Class<?> primType = Wrapper.asPrimitiveType(convType);
-        if (!canUnboxArgument(newType, oldType, arg, convType))
-            return null;
-        MethodType castDone = newType;
-        if (!VerifyType.isNullConversion(src, boxType))
-            castDone = newType.changeParameterType(arg, boxType);
-        long conv = makeConv(OP_REF_TO_PRIM, arg, T_OBJECT, basicType(primType));
-        MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType);
-        if (castDone == newType)
-            return adapter;
-        return makeCheckCast(token, newType, adapter, arg, boxType);
-    }
-
-    /** Can an primitive boxing adapter validly convert src to dst? */
-    public static boolean canBoxArgument(Class<?> src, Class<?> dst) {
-        if (!convOpSupported(OP_PRIM_TO_REF))  return false;
-        throw new UnsupportedOperationException("NYI");
-    }
-
-    /** Factory method:  Unbox the given argument.
-     *  Return null if this cannot be done.
-     */
-    public static MethodHandle makeBoxArgument(Access token,
-                MethodType newType, MethodHandle target,
-                int arg, Class<?> convType) {
-        // this is difficult to do in the JVM because it must GC
-        return null;
-    }
-
-    /** Can an adapter simply drop arguments to convert the target to newType? */
-    public static boolean canDropArguments(MethodType newType, MethodType targetType,
-                int dropArgPos, int dropArgCount) {
-        if (dropArgCount == 0)
-            return canRetypeOnly(newType, targetType);
-        if (!convOpSupported(OP_DROP_ARGS))  return false;
-        if (diffReturnTypes(newType, targetType, false) != 0)
-            return false;
-        int nptypes = newType.parameterCount();
-        // parameter types must be the same up to the drop point
-        if (dropArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, dropArgPos, false) != 0)
-            return false;
-        int afterPos = dropArgPos + dropArgCount;
-        int afterCount = nptypes - afterPos;
-        if (dropArgPos < 0 || dropArgPos >= nptypes ||
-            dropArgCount < 1 || afterPos > nptypes ||
-            targetType.parameterCount() != nptypes - dropArgCount)
-            return false;
-        // parameter types after the drop point must also be the same
-        if (afterCount != 0 && diffParamTypes(newType, afterPos, targetType, dropArgPos, afterCount, false) != 0)
-            return false;
-        return true;
-    }
-
-    /** Factory method:  Drop selected arguments.
-     *  Allow unchecked retyping of remaining arguments, pairwise.
-     *  Return null if this is not possible.
-     */
-    public static MethodHandle makeDropArguments(Access token,
-                MethodType newType, MethodHandle target,
-                int dropArgPos, int dropArgCount) {
-        Access.check(token);
-        if (dropArgCount == 0)
-            return makeRetypeOnly(IMPL_TOKEN, newType, target);
-        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;
-        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 {
-            return (-1-((-1-rotateBy) % argCount)) + argCount;
-        }
-    }
-
-    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? */
-    public static boolean canSpreadArguments(MethodType newType, MethodType targetType,
-                Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
-        if (!convOpSupported(OP_SPREAD_ARGS))  return false;
-        if (diffReturnTypes(newType, targetType, false) != 0)
-            return false;
-        int nptypes = newType.parameterCount();
-        // parameter types must be the same up to the spread point
-        if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0)
-            return false;
-        int afterPos = spreadArgPos + spreadArgCount;
-        int afterCount = nptypes - (spreadArgPos + 1);
-        if (spreadArgPos < 0 || spreadArgPos >= nptypes ||
-            spreadArgCount < 0 ||
-            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)
-            return false;
-        // match the array element type to the spread arg types
-        Class<?> rawSpreadArgType = newType.parameterType(spreadArgPos);
-        if (rawSpreadArgType != spreadArgType && !canCheckCast(rawSpreadArgType, spreadArgType))
-            return false;
-        for (int i = 0; i < spreadArgCount; i++) {
-            Class<?> src = VerifyType.spreadArgElementType(spreadArgType, i);
-            Class<?> dst = targetType.parameterType(spreadArgPos + i);
-            if (src == null || !VerifyType.isNullConversion(src, dst))
-                return false;
-        }
-        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 targetType = target.type();
-        if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
-            return null;
-        // 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 MethodHandleImpl.getNameString(IMPL_TOKEN, nonAdapter((MethodHandle)vmtarget), this);
-    }
-
-    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	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-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
- * on a predetermined argument.  The JVM dispatches to the correct method
- * when the handle is created, not when it is invoked.
- * @author jrose
- */
-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.
-
-    /** 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().dropParameterTypes(0, 1));
-        // check the type now, once for all:
-        this.argument = checkReferenceArgument(argument, mh, 0);
-        this.vmargslot = this.type().parameterSlotCount();
-        if (MethodHandleNatives.JVM_SUPPORT) {
-            this.vmtarget = null;  // maybe updated by JVM
-            MethodHandleNatives.init(this, mh, 0);
-        } else {
-            this.vmtarget = mh;
-        }
-    }
-
-    /** 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.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(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 {
-            this.argument = checkReferenceArgument(argument, mh, 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
-            MethodHandleNatives.init(this, mh, argnum);
-        } else {
-            this.vmtarget = mh;
-        }
-    }
-
-    /** For the AdapterMethodHandle subclass.
-     */
-    BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
-        super(Access.TOKEN, type);
-        this.argument = argument;
-        this.vmargslot = vmargslot;
-        assert(this instanceof AdapterMethodHandle);
-    }
-
-    /** Initialize the current object as a self-bound 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.
-     */
-    protected BoundMethodHandle(Access token, MethodHandle entryPoint) {
-        super(token, entryPoint.type().dropParameterTypes(0, 1));
-        this.argument = this; // kludge; get rid of
-        this.vmargslot = this.type().parameterSlotDepth(0);
-        initTarget(entryPoint, 0);
-    }
-
-    /** Make sure the given {@code argument} can be used as {@code argnum}-th
-     *  parameter of the given method handle {@code mh}, which must be a reference.
-     *  <p>
-     *  If this fails, throw a suitable {@code WrongMethodTypeException},
-     *  which will prevent the creation of an illegally typed bound
-     *  method handle.
-     */
-    final static Object checkReferenceArgument(Object argument, MethodHandle mh, int argnum) {
-        Class<?> ptype = mh.type().parameterType(argnum);
-        if (ptype.isPrimitive()) {
-            // fail
-        } else if (argument == null) {
-            return null;
-        } else if (VerifyType.isNullReferenceConversion(argument.getClass(), ptype)) {
-            return argument;
-        }
-        throw badBoundArgumentException(argument, mh, argnum);
-    }
-
-    /** Make sure the given {@code argument} can be used as {@code argnum}-th
-     *  parameter of the given method handle {@code mh}, which must be a primitive.
-     *  <p>
-     *  If this fails, throw a suitable {@code WrongMethodTypeException},
-     *  which will prevent the creation of an illegally typed bound
-     *  method handle.
-     */
-    final static Object bindPrimitiveArgument(Object argument, MethodHandle mh, int argnum) {
-        Class<?> ptype = mh.type().parameterType(argnum);
-        Wrapper  wrap = Wrapper.forPrimitiveType(ptype);
-        Object   zero  = wrap.zero();
-        if (zero == null) {
-            // fail
-        } else if (argument == null) {
-            if (ptype != int.class && wrap.isSubwordOrInt())
-                return Integer.valueOf(0);
-            else
-                return zero;
-        } else if (VerifyType.isNullReferenceConversion(argument.getClass(), zero.getClass())) {
-            if (ptype != int.class && wrap.isSubwordOrInt())
-                return Wrapper.INT.wrap(argument);
-            else
-                return argument;
-        }
-        throw badBoundArgumentException(argument, mh, argnum);
-    }
-
-    final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) {
-        String atype = (argument == null) ? "null" : argument.getClass().toString();
-        return new WrongMethodTypeException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type());
-    }
-
-    @Override
-    public String toString() {
-        return MethodHandleImpl.addTypeString(baseName(), this);
-    }
-
-    /** Component of toString() before the type string. */
-    protected String baseName() {
-        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 noParens(super.toString()); // "invoke", probably
-            }
-            assert(mh != this);
-        }
-        return noParens(mh.toString());
-    }
-
-    private static String noParens(String str) {
-        int paren = str.indexOf('(');
-        if (paren >= 0) str = str.substring(0, paren);
-        return str;
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import static sun.dyn.MemberName.uncaughtException;
-
-/**
- * Parts of CallSite known to the JVM.
- * @author jrose
- */
-public class CallSiteImpl {
-    // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
-    static CallSite makeSite(MethodHandle bootstrapMethod,
-                             // Callee information:
-                             String name, MethodType type,
-                             // Extra arguments for BSM, if any:
-                             Object info,
-                             // Caller information:
-                             MemberName callerMethod, int callerBCI) {
-        Class<?> callerClass = callerMethod.getDeclaringClass();
-        Object caller;
-        if (bootstrapMethod.type().parameterType(0) == Class.class && TRANSITIONAL_BEFORE_PFD)
-            caller = callerClass;  // remove for PFD
-        else
-            caller = MethodHandleImpl.IMPL_LOOKUP.in(callerClass);
-        if (bootstrapMethod == null && TRANSITIONAL_BEFORE_PFD) {
-            // If there is no bootstrap method, throw IncompatibleClassChangeError.
-            // This is a valid generic error type for resolution (JLS 12.3.3).
-            throw new IncompatibleClassChangeError
-                ("Class "+callerClass.getName()+" has not declared a bootstrap method for invokedynamic");
-        }
-        CallSite site;
-        try {
-            Object binding;
-            info = maybeReBox(info);
-            if (info == null) {
-                binding = bootstrapMethod.invokeGeneric(caller, name, type);
-            } else if (!info.getClass().isArray()) {
-                binding = bootstrapMethod.invokeGeneric(caller, name, type, info);
-            } else {
-                Object[] argv = (Object[]) info;
-                if (3 + argv.length > 255)
-                    new InvokeDynamicBootstrapError("too many bootstrap method arguments");
-                MethodType bsmType = bootstrapMethod.type();
-                if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class)
-                    binding = bootstrapMethod.invokeGeneric(caller, name, type, argv);
-                else
-                    binding = MethodHandles.spreadInvoker(bsmType, 3)
-                        .invokeGeneric(bootstrapMethod, caller, name, type, argv);
-            }
-            //System.out.println("BSM for "+name+type+" => "+binding);
-            if (binding instanceof CallSite) {
-                site = (CallSite) binding;
-            } else if (binding instanceof MethodHandle && TRANSITIONAL_BEFORE_PFD) {
-                // Transitional!
-                MethodHandle target = (MethodHandle) binding;
-                site = new ConstantCallSite(target);
-            } else {
-                throw new ClassCastException("bootstrap method failed to produce a CallSite");
-            }
-            if (TRANSITIONAL_BEFORE_PFD)
-                PRIVATE_INITIALIZE_CALL_SITE.invokeExact(site, name, type,
-                                                         callerMethod, callerBCI);
-            assert(site.getTarget() != null);
-            assert(site.getTarget().type().equals(type));
-        } catch (Throwable ex) {
-            InvokeDynamicBootstrapError bex;
-            if (ex instanceof InvokeDynamicBootstrapError)
-                bex = (InvokeDynamicBootstrapError) ex;
-            else
-                bex = new InvokeDynamicBootstrapError("call site initialization exception", ex);
-            throw bex;
-        }
-        return site;
-    }
-
-    private static boolean TRANSITIONAL_BEFORE_PFD = true;  // FIXME: remove for PFD
-
-    private static Object maybeReBox(Object x) {
-        if (x instanceof Integer) {
-            int xi = (int) x;
-            if (xi == (byte) xi)
-                x = xi;  // must rebox; see JLS 5.1.7
-            return x;
-        } else if (x instanceof Object[]) {
-            Object[] xa = (Object[]) x;
-            for (int i = 0; i < xa.length; i++) {
-                if (xa[i] instanceof Integer)
-                    xa[i] = maybeReBox(xa[i]);
-            }
-            return xa;
-        } else {
-            return x;
-        }
-    }
-
-    // This method is private in CallSite because it touches private fields in CallSite.
-    // These private fields (vmmethod, vmindex) are specific to the JVM.
-    private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE;
-    static {
-        try {
-            PRIVATE_INITIALIZE_CALL_SITE =
-            !TRANSITIONAL_BEFORE_PFD ? null :
-            MethodHandleImpl.IMPL_LOOKUP.findVirtual(CallSite.class, "initializeFromJVM",
-                MethodType.methodType(void.class,
-                                      String.class, MethodType.class,
-                                      MemberName.class, int.class));
-        } catch (ReflectiveOperationException ex) {
-            throw uncaughtException(ex);
-        }
-    }
-
-    public static void setCallSiteTarget(Access token, CallSite site, MethodHandle target) {
-        Access.check(token);
-        MethodHandleNatives.setCallSiteTarget(site, target);
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/DirectMethodHandle.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import static sun.dyn.MethodHandleNatives.Constants.*;
-
-/**
- * The flavor of method handle which emulates invokespecial or invokestatic.
- * @author jrose
- */
-class DirectMethodHandle extends MethodHandle {
-    //inherited oop    vmtarget;    // methodOop or virtual class/interface oop
-    private final int  vmindex;     // method index within class or interface
-    { vmindex = VM_INDEX_UNINITIALIZED; }  // JVM may change this
-
-    // Constructors in this class *must* be package scoped or private.
-    DirectMethodHandle(MethodType mtype, MemberName m, boolean doDispatch, Class<?> lookupClass) {
-        super(Access.TOKEN, mtype);
-
-        assert(m.isMethod() || !doDispatch && m.isConstructor());
-        if (!m.isResolved())
-            throw new InternalError();
-
-        MethodHandleNatives.init(this, (Object) m, doDispatch, lookupClass);
-    }
-
-    boolean isValid() {
-        return (vmindex != VM_INDEX_UNINITIALIZED);
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4496 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import java.lang.reflect.*;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-
-/**
- * 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 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 filtering adapters
-     *  with the given generic type
-     */
-    FilterGeneric(MethodType entryType) {
-        this.entryType = entryType;
-        int tableSize = Kind.LIMIT.invokerIndex(1 + entryType.parameterCount());
-        this.adapters = new Adapter[tableSize];
-    }
-
-    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 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 makeArgumentFolder(MethodHandle combiner, MethodHandle target) {
-        int num = combiner.type().parameterCount();
-        return make(Kind.fold, num, combiner, target);
-    }
-
-    /** 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);
-    }
-
-    /** 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);
-    }
-
-    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/"+entryType;
-    }
-
-    static MethodType targetType(MethodType entryType, Kind kind, int pos, MethodType filterType) {
-        MethodType type = entryType;
-        switch (kind) {
-            case value:
-            case flyby:
-                break;  // no change
-            case fold:
-                type = type.insertParameterTypes(0, filterType.returnType());
-                break;
-            case collect:
-                type = type.dropParameterTypes(pos, type.parameterCount());
-                type = type.insertParameterTypes(pos, filterType.returnType());
-                break;
-            default:
-                throw new InternalError();
-        }
-        return type;
-    }
-
-    static MethodType entryType(Kind kind, int pos, MethodType filterType, MethodType targetType) {
-        MethodType type = targetType;
-        switch (kind) {
-            case value:
-            case flyby:
-                break;  // no change
-            case fold:
-                type = type.dropParameterTypes(0, 1);
-                break;
-            case collect:
-                type = type.dropParameterTypes(pos, pos+1);
-                type = type.insertParameterTypes(pos, filterType.parameterList());
-                break;
-            default:
-                throw new InternalError();
-        }
-        return type;
-    }
-
-    /* Create an adapter that handles spreading calls for the given type. */
-    static Adapter findAdapter(MethodType entryType, Kind kind, int pos) {
-        int argc = entryType.parameterCount();
-        String cname0 = "F"+argc;
-        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;
-            // see if it has the required invoke method
-            MethodHandle entryPoint = null;
-            try {
-                entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
-            } catch (ReflectiveOperationException ex) {
-            }
-            if (entryPoint == null)  continue;
-            Constructor<? extends Adapter> ctor = null;
-            try {
-                ctor = acls.getDeclaredConstructor(MethodHandle.class);
-            } catch (NoSuchMethodException ex) {
-            } catch (SecurityException ex) {
-            }
-            if (ctor == null)  continue;
-            try {
-                // Produce an instance configured as a prototype.
-                return ctor.newInstance(entryPoint);
-            } 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 entryType, Kind kind, int pos) {
-        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 BoundMethodHandle {
-        protected final MethodHandle filter; // transforms one or more arguments
-        protected final MethodHandle target; // ultimate target
-
-        @Override
-        public String toString() {
-            return MethodHandleImpl.addTypeString(target, this);
-        }
-
-        protected boolean isPrototype() { return target == null; }
-        protected Adapter(MethodHandle entryPoint) {
-            this(entryPoint, entryPoint, null);
-            assert(isPrototype());
-        }
-        protected MethodHandle prototypeEntryPoint() {
-            if (!isPrototype())  throw new InternalError();
-            return filter;
-        }
-
-        protected Adapter(MethodHandle entryPoint,
-                          MethodHandle filter, MethodHandle target) {
-            super(Access.TOKEN, entryPoint);
-            this.filter = filter;
-            this.target = target;
-        }
-
-        /** Make a copy of self, with new fields. */
-        protected abstract Adapter makeInstance(MethodHandle entryPoint,
-                MethodHandle filter, MethodHandle target);
-        // { return new ThisType(entryPoint, filter, target); }
-
-        static private final String CLASS_PREFIX; // "sun.dyn.FilterGeneric$"
-        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;
-            }
-        }
-    }
-
-    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(); }
-    }
-
-    /* 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 F1X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
-                        { return new F1X(e, f, t); }
-        protected Object invoke_V0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); }
-        protected Object invoke_F0(Object a0) { return target.invokeExact(filter.invokeExact(), a0); }
-        protected Object invoke_F1(Object a0) { return target.invokeExact(filter.invokeExact(a0), a0); }
-        protected Object invoke_C0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); }
-        protected Object invoke_C1(Object a0) { return target.invokeExact(a0, filter.invokeExact()); }
-        protected Object invoke_Y0(Object a0) { Object[] av = { a0 };
-                       filter.invokeExact(av); return target.invokeExact(av[0]); }
-    }
-    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 F2X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
-                        { return new F2X(e, f, t); }
-        protected Object invoke_V0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0), a1); }
-        protected Object invoke_V1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); }
-        protected Object invoke_F0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(), a0, a1); }
-        protected Object invoke_F1(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0), a0, a1); }
-        protected Object invoke_F2(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0, a1), a0, a1); }
-        protected Object invoke_C0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0, a1)); }
-        protected Object invoke_C1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); }
-        protected Object invoke_C2(Object a0, Object a1) { return target.invokeExact(a0, a1, filter.invokeExact()); }
-        protected Object invoke_Y0(Object a0, Object a1) { Object[] av = { a0, a1 };
-                       filter.invokeExact(av); return target.invokeExact(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.invokeExact(filter.invokeExact()); }
-        protected Object invoke_C0() throws Throwable {
-            return target.invokeExact(filter.invokeExact()); }
-        static final Object[] NO_ARGS = { };
-        protected Object invoke_Y0() throws Throwable {
-            filter.invokeExact(NO_ARGS); // make the flyby
-            return target.invokeExact(); }
-    }
-
-/*
-  : 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.invokeExact(@a0_@@Psp@filter.invokeExact(a@P@)@_aN@); }",
-        "        //@end-P@",
-        "        //@each-P@",
-        "        protected Object invoke_F@P@(@Tvav@) throws Throwable {",
-        "            return target.invokeExact(filter.invokeExact(@a0@),",
-        "                                 @av@); }",
-        "        //@end-P@",
-        "        protected Object invoke_F@N@(@Tvav@) throws Throwable {",
-        "            return target.invokeExact(filter.invokeExact(@av@),",
-        "                                 @av@); }",
-        "        //@each-P@",
-        "        protected Object invoke_C@P@(@Tvav@) throws Throwable {",
-        "            return target.invokeExact(@a0_@filter.invokeExact(a@P@@_aN@)); }",
-        "        //@end-P@",
-        "        protected Object invoke_C@N@(@Tvav@) throws Throwable {",
-        "            return target.invokeExact(@av@, filter.invokeExact()); }",
-        "        protected Object invoke_Y0(@Tvav@) throws Throwable {",
-        "            Object[] av = { @av@ };",
-        "            filter.invokeExact(av); // make the flyby",
-        "            return target.invokeExact(@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.invokeExact(filter.invokeExact(a0)); }
-        protected Object invoke_F0(Object a0) throws Throwable {
-            return target.invokeExact(filter.invokeExact(),
-                                 a0); }
-        protected Object invoke_F1(Object a0) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0),
-                                 a0); }
-        protected Object invoke_C0(Object a0) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0)); }
-        protected Object invoke_C1(Object a0) throws Throwable {
-            return target.invokeExact(a0, filter.invokeExact()); }
-        protected Object invoke_Y0(Object a0) throws Throwable {
-            Object[] av = { a0 };
-            filter.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(a0), a1); }
-        protected Object invoke_V1(Object a0, Object a1) throws Throwable {
-            return target.invokeExact(a0, filter.invokeExact(a1)); }
-        protected Object invoke_F0(Object a0, Object a1) throws Throwable {
-            return target.invokeExact(filter.invokeExact(),
-                                 a0, a1); }
-        protected Object invoke_F1(Object a0, Object a1) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0),
-                                 a0, a1); }
-        protected Object invoke_F2(Object a0, Object a1) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0, a1),
-                                 a0, a1); }
-        protected Object invoke_C0(Object a0, Object a1) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0, a1)); }
-        protected Object invoke_C1(Object a0, Object a1) throws Throwable {
-            return target.invokeExact(a0, filter.invokeExact(a1)); }
-        protected Object invoke_C2(Object a0, Object a1) throws Throwable {
-            return target.invokeExact(a0, a1, filter.invokeExact()); }
-        protected Object invoke_Y0(Object a0, Object a1) throws Throwable {
-            Object[] av = { a0, a1 };
-            filter.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(a0), a1, a2); }
-        protected Object invoke_V1(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(a0, filter.invokeExact(a1), a2); }
-        protected Object invoke_V2(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(a0, a1, filter.invokeExact(a2)); }
-        protected Object invoke_F0(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(filter.invokeExact(),
-                                 a0, a1, a2); }
-        protected Object invoke_F1(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0),
-                                 a0, a1, a2); }
-        protected Object invoke_F2(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0, a1),
-                                 a0, a1, a2); }
-        protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0, a1, a2),
-                                 a0, a1, a2); }
-        protected Object invoke_C0(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0, a1, a2)); }
-        protected Object invoke_C1(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(a0, filter.invokeExact(a1, a2)); }
-        protected Object invoke_C2(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(a0, a1, filter.invokeExact(a2)); }
-        protected Object invoke_C3(Object a0, Object a1, Object a2) throws Throwable {
-            return target.invokeExact(a0, a1, a2, filter.invokeExact()); }
-        protected Object invoke_Y0(Object a0, Object a1, Object a2) throws Throwable {
-            Object[] av = { a0, a1, a2 };
-            filter.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(a0), a1, a2, a3); }
-        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(a0, filter.invokeExact(a1), a2, a3); }
-        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(a0, a1, filter.invokeExact(a2), a3); }
-        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3)); }
-        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(filter.invokeExact(),
-                                 a0, a1, a2, a3); }
-        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0),
-                                 a0, a1, a2, a3); }
-        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0, a1),
-                                 a0, a1, a2, a3); }
-        protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0, a1, a2),
-                                 a0, a1, a2, a3); }
-        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
-                                 a0, a1, a2, a3); }
-        protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0, a1, a2, a3)); }
-        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(a0, filter.invokeExact(a1, a2, a3)); }
-        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(a0, a1, filter.invokeExact(a2, a3)); }
-        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3)); }
-        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact()); }
-        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            Object[] av = { a0, a1, a2, a3 };
-            filter.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4); }
-        protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4); }
-        protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4); }
-        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4); }
-        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4)); }
-        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(filter.invokeExact(),
-                                 a0, a1, a2, a3, a4); }
-        protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(filter.invokeExact(a0),
-                                 a0, a1, a2, a3, a4); }
-        protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4)); }
-        protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4)); }
-        protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4)); }
-        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4)); }
-        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4)); }
-        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact()); }
-        protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4) throws Throwable {
-            Object[] av = { a0, a1, a2, a3, a4 };
-            filter.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5); }
-        protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5) throws Throwable {
-            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5); }
-        protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5); }
-        protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5)); }
-        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5) throws Throwable {
-            return target.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5)); }
-        protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5) throws Throwable {
-            return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5)); }
-        protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5)); }
-        protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5)); }
-        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6); }
-        protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5, Object a6) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6)); }
-        protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5, Object a6) throws Throwable {
-            return target.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6)); }
-        protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5, Object a6) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6)); }
-        protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
-                                   Object a4, Object a5, Object a6) throws Throwable {
-            return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact(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.invokeExact(filter.invokeExact(),
-                                 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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(filter.invokeExact(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.invokeExact(a0, filter.invokeExact(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.invokeExact(a0, a1, filter.invokeExact(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.invokeExact(a0, a1, a2, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
-                                 a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, filter.invokeExact()); }
-        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.invokeExact(av); // make the flyby
-            return target.invokeExact(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	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import static sun.dyn.MemberName.uncaughtException;
-
-/**
- * Unary function composition, useful for many small plumbing jobs.
- * The invoke method takes a single reference argument, and returns a reference
- * Internally, it first calls the {@code filter} method on the argument,
- * Making up the difference between the raw method type and the
- * final method type is the responsibility of a JVM-level adapter.
- * @author jrose
- */
-public class FilterOneArgument extends BoundMethodHandle {
-    protected final MethodHandle filter;  // Object -> Object
-    protected final MethodHandle target;  // Object -> Object
-
-    @Override
-    public String toString() {
-        return target.toString();
-    }
-
-    protected Object invoke(Object argument) throws Throwable {
-        Object filteredArgument = filter.invokeExact(argument);
-        return target.invokeExact(filteredArgument);
-    }
-
-    private static final MethodHandle INVOKE;
-    static {
-        try {
-            INVOKE =
-                MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
-                                                         MethodType.genericMethodType(1));
-        } catch (ReflectiveOperationException ex) {
-            throw uncaughtException(ex);
-        }
-    }
-
-    protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
-        super(Access.TOKEN, INVOKE);
-        this.filter = filter;
-        this.target = target;
-    }
-
-    public static MethodHandle make(MethodHandle filter, MethodHandle target) {
-        if (filter == null)  return target;
-        if (target == null)  return filter;
-        return new FilterOneArgument(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	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,629 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import java.lang.reflect.*;
-import sun.dyn.util.*;
-import static sun.dyn.MethodTypeImpl.invokers;
-
-/**
- * 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
- * only Object arguments.  A non-generic call therefore features
- * primitives and/or reference types other than Object.
- * An adapter has types for its incoming and outgoing calls.
- * The incoming call type is simply determined by the adapter's type
- * (the MethodType it presents to callers).  The outgoing call type
- * is determined by the adapter's target (a MethodHandle that the adapter
- * 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.)
- * @author jrose
- */
-class FromGeneric {
-    // type for the outgoing call (may have primitives, etc.)
-    private final MethodType targetType;
-    // type of the outgoing call internal to the adapter
-    private final MethodType internalType;
-    // prototype adapter (clone and customize for each new target!)
-    private final Adapter adapter;
-    // entry point for adapter (Adapter mh, a...) => ...
-    private final MethodHandle entryPoint;
-    // unboxing invoker of type (MH, Object**N) => raw return value
-    // it makes up the difference of internalType => targetType
-    private final MethodHandle unboxingInvoker;
-    // conversion which boxes a the target's raw return value
-    private final MethodHandle returnConversion;
-
-    /** Compute and cache information common to all unboxing adapters
-     *  that can call out to targets of the erasure-family of the given erased type.
-     */
-    private FromGeneric(MethodType targetType) {
-        this.targetType = targetType;
-        MethodType internalType0;
-        // the target invoker will generally need casts on reference arguments
-        Adapter ad = findAdapter(internalType0 = targetType.erase());
-        if (ad != null) {
-            // Immediate hit to exactly the adapter we want,
-            // with no monkeying around with primitive types.
-            this.internalType = internalType0;
-            this.adapter = ad;
-            this.entryPoint = ad.prototypeEntryPoint();
-            this.returnConversion = computeReturnConversion(targetType, internalType0);
-            this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
-            return;
-        }
-
-        // outgoing primitive arguments will be wrapped; unwrap them
-        MethodType primsAsObj = MethodTypeImpl.of(targetType).primArgsAsBoxes();
-        MethodType objArgsRawRet = MethodTypeImpl.of(primsAsObj).primsAsInts();
-        if (objArgsRawRet != targetType)
-            ad = findAdapter(internalType0 = objArgsRawRet);
-        if (ad == null) {
-            ad = buildAdapterFromBytecodes(internalType0 = targetType);
-        }
-        this.internalType = internalType0;
-        this.adapter = ad;
-        MethodType tepType = targetType.insertParameterTypes(0, adapter.getClass());
-        this.entryPoint = ad.prototypeEntryPoint();
-        this.returnConversion = computeReturnConversion(targetType, internalType0);
-        this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
-    }
-
-    /**
-     * The typed target will be called according to targetType.
-     * The adapter code will in fact see the raw result from internalType,
-     * and must box it into an object.  Produce a converter for this.
-     */
-    private static MethodHandle computeReturnConversion(
-            MethodType targetType, MethodType internalType) {
-        Class<?> tret = targetType.returnType();
-        Class<?> iret = internalType.returnType();
-        Wrapper wrap = Wrapper.forBasicType(tret);
-        if (!iret.isPrimitive()) {
-            assert(iret == Object.class);
-            return ValueConversions.identity();
-        } else if (wrap.primitiveType() == iret) {
-            return ValueConversions.box(wrap, false);
-        } else {
-            assert(tret == double.class ? iret == long.class : iret == int.class);
-            return ValueConversions.boxRaw(wrap, false);
-        }
-    }
-
-    /**
-     * The typed target will need an exact invocation point; provide it here.
-     * The adapter will possibly need to make a slightly different call,
-     * so adapt the invoker.  This way, the logic for making up the
-     * difference between what the adapter can call and what the target
-     * needs can be cached once per type.
-     */
-    private static MethodHandle computeUnboxingInvoker(
-            MethodType targetType, MethodType internalType) {
-        // All the adapters we have here have reference-untyped internal calls.
-        assert(internalType == internalType.erase());
-        MethodHandle invoker = invokers(targetType).exactInvoker();
-        // cast all narrow reference types, unbox all primitive arguments:
-        MethodType fixArgsType = internalType.changeReturnType(targetType.returnType());
-        MethodHandle fixArgs = AdapterMethodHandle.convertArguments(Access.TOKEN,
-                                 invoker, Invokers.invokerType(fixArgsType),
-                                 invoker.type(), null);
-        if (fixArgs == null)
-            throw new InternalError("bad fixArgs");
-        // reinterpret the calling sequence as raw:
-        MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(Access.TOKEN,
-                                        Invokers.invokerType(internalType), fixArgs);
-        if (retyper == null)
-            throw new InternalError("bad retyper");
-        return retyper;
-    }
-
-    Adapter makeInstance(MethodHandle typedTarget) {
-        MethodType type = typedTarget.type();
-        if (type == targetType) {
-            return adapter.makeInstance(entryPoint, unboxingInvoker, returnConversion, typedTarget);
-        }
-        // my erased-type is not exactly the same as the desired type
-        assert(type.erase() == targetType);  // else we are busted
-        MethodHandle invoker = computeUnboxingInvoker(type, internalType);
-        return adapter.makeInstance(entryPoint, invoker, returnConversion, typedTarget);
-    }
-
-    /** 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 typedTarget) {
-        MethodType type = typedTarget.type();
-        if (type == type.generic())  return typedTarget;
-        return FromGeneric.of(type).makeInstance(typedTarget);
-    }
-
-    /** Return the adapter information for this type's erasure. */
-    static FromGeneric of(MethodType type) {
-        MethodTypeImpl form = MethodTypeImpl.of(type);
-        FromGeneric fromGen = form.fromGeneric;
-        if (fromGen == null)
-            form.fromGeneric = fromGen = new FromGeneric(form.erasedType());
-        return fromGen;
-    }
-
-    public String toString() {
-        return "FromGeneric"+targetType;
-    }
-
-    /* Create an adapter that handles spreading calls for the given type. */
-    static Adapter findAdapter(MethodType internalType) {
-        MethodType entryType = internalType.generic();
-        MethodTypeImpl form = MethodTypeImpl.of(internalType);
-        Class<?> rtype = internalType.returnType();
-        int argc = form.parameterCount();
-        int lac = form.longPrimitiveParameterCount();
-        int iac = form.primitiveParameterCount() - lac;
-        String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
-        String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
-        String cname0 = rawReturn + argc;
-        String cname1 = "A"       + argc;
-        String[] cnames = { cname0+intsAndLongs, cname0, cname1+intsAndLongs, cname1 };
-        String iname = "invoke_"+cname0+intsAndLongs;
-        // 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 (ReflectiveOperationException ex) {
-            }
-            if (entryPoint == null)  continue;
-            Constructor<? extends Adapter> ctor = null;
-            try {
-                ctor = acls.getDeclaredConstructor(MethodHandle.class);
-            } catch (NoSuchMethodException ex) {
-            } catch (SecurityException ex) {
-            }
-            if (ctor == null)  continue;
-            try {
-                // Produce an instance configured as a prototype.
-                return ctor.newInstance(entryPoint);
-            } 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 internalType) {
-        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 BoundMethodHandle {
-        /*
-         * class X<<R,int N>> extends Adapter {
-         *   (MH, Object**N)=>raw(R) invoker;
-         *   (any**N)=>R target;
-         *   raw(R)=>Object convert;
-         *   Object invoke(Object**N a) = convert(invoker(target, a...))
-         * }
-         */
-        protected final MethodHandle invoker;  // (MH, Object**N) => raw(R)
-        protected final MethodHandle convert;  // raw(R) => Object
-        protected final MethodHandle target;   // (any**N) => R
-
-        @Override
-        public String toString() {
-            return MethodHandleImpl.addTypeString(target, this);
-        }
-
-        protected boolean isPrototype() { return target == null; }
-        protected Adapter(MethodHandle entryPoint) {
-            this(entryPoint, null, entryPoint, null);
-            assert(isPrototype());
-        }
-        protected MethodHandle prototypeEntryPoint() {
-            if (!isPrototype())  throw new InternalError();
-            return convert;
-        }
-
-        protected Adapter(MethodHandle entryPoint,
-                          MethodHandle invoker, MethodHandle convert, MethodHandle target) {
-            super(Access.TOKEN, entryPoint);
-            this.invoker = invoker;
-            this.convert = convert;
-            this.target  = target;
-        }
-
-        /** Make a copy of self, with new fields. */
-        protected abstract Adapter makeInstance(MethodHandle entryPoint,
-                MethodHandle invoker, MethodHandle convert, MethodHandle target);
-        // { return new ThisType(entryPoint, convert, target); }
-
-        /// Conversions on the value returned from the target.
-        protected Object convert_L(Object result) throws Throwable { return convert.invokeExact(result); }
-        protected Object convert_I(int    result) throws Throwable { return convert.invokeExact(result); }
-        protected Object convert_J(long   result) throws Throwable { return convert.invokeExact(result); }
-        protected Object convert_F(float  result) throws Throwable { return convert.invokeExact(result); }
-        protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); }
-
-        static private final String CLASS_PREFIX; // "sun.dyn.FromGeneric$"
-        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 xA2 extends Adapter {
-        protected xA2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
-        protected xA2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
-                        { 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) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
-        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1)); }
-        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1)); }
-        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
-        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
-    }
-    // */
-
-/*
-: SHELL; n=FromGeneric; 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[] TYPES = { "Object",    "int   ",    "long  ",    "float ",    "double" };
-    static String[] WRAPS = { "         ", "(Integer)", "(Long)   ", "(Float)  ", "(Double) " };
-    static String[] TCHARS = { "L",     "I",      "J",      "F",      "D",     "A" };
-    static String[][] TEMPLATES = { {
-        "@for@ arity=0..10  rcat<=4 nrefs<=99 nints=0   nlongs=0",
-        "    //@each-cat@",
-        "    static class @cat@ extends Adapter {",
-        "        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); }",
-        "        //@each-R@",
-        "        protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@((@R@)@W@invoker.invokeExact(target@av@)); }",
-        "        //@end-R@",
-        "    }",
-    } };
-    static final String NEWLINE_INDENT = "\n                ";
-    enum VAR {
-        cat, catN, R, Rc, W, av, Tvav, Ovav;
-        public final String pattern = "@"+toString().replace('_','.')+"@";
-        public String binding;
-        static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
-            int nargs = nrefs + nints + nlongs;
-            if (topLevel)
-                VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
-            VAR.catN.binding = catstr(rcat, nrefs, nints, nlongs);
-            VAR.R.binding = TYPES[rcat];
-            VAR.Rc.binding = TCHARS[rcat];
-            VAR.W.binding = WRAPS[rcat];
-            String[] Tv = new String[nargs];
-            String[] av = new String[nargs];
-            String[] Tvav = new String[nargs];
-            String[] Ovav = new String[nargs];
-            for (int i = 0; i < nargs; i++) {
-                int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
-                Tv[i] = TYPES[tcat];
-                av[i] = arg(i);
-                Tvav[i] = param(Tv[i], av[i]);
-                Ovav[i] = param("Object", av[i]);
-            }
-            VAR.av.binding = comma(", ", av);
-            VAR.Tvav.binding = comma(Tvav);
-            VAR.Ovav.binding = comma(Ovav);
-        }
-        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 sep, String[] v) {
-            if (v.length == 0)  return "";
-            String res = sep+v[0];
-            for (int i = 1; i < v.length; i++)  res += ", "+v[i];
-            return res;
-        }
-        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, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
-    static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
-    static HashSet<String> done = new HashSet<String>();
-    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++]);
-        MAX_RCAT  = Integer.valueOf(params[pcur++]);
-        MAX_REFS  = Integer.valueOf(params[pcur++]);
-        MAX_INTS  = Integer.valueOf(params[pcur++]);
-        MAX_LONGS = Integer.valueOf(params[pcur++]);
-        if (pcur != params.length)  throw new RuntimeException("bad extra param: "+forLine);
-        if (MAX_RCAT >= TYPES.length)  MAX_RCAT = TYPES.length - 1;
-        ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
-        ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
-        for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
-            for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
-                expandTemplate(template, true, rcat, nargs, 0, 0);
-                if (ALL_ARG_TYPES)  break;
-                expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
-                if (ALL_RETURN_TYPES)  break;
-            }
-        }
-    }
-    static String catstr(int rcat, int nrefs, int nints, int nlongs) {
-        int nargs = nrefs + nints + nlongs;
-        String cat = TCHARS[rcat] + nargs;
-        if (!ALL_ARG_TYPES)  cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
-        return cat;
-    }
-    static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
-        for (int isLong = 0; isLong <= 1; isLong++) {
-            for (int nprims = 1; nprims <= nargs; nprims++) {
-                int nrefs = nargs - nprims;
-                int nints = ((1-isLong) * nprims);
-                int nlongs = (isLong * nprims);
-                expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
-            }
-        }
-    }
-    static void expandTemplate(String[] template, boolean topLevel,
-                               int rcat, int nrefs, int nints, int nlongs) {
-        int nargs = nrefs + nints + nlongs;
-        if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS)  return;
-        VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
-        if (topLevel && !done.add(VAR.cat.binding)) {
-            System.out.println("    //repeat "+VAR.cat.binding);
-            return;
-        }
-        for (int i = 0; i < template.length; i++) {
-            String line = template[i];
-            if (line.endsWith("@each-cat@")) {
-                // ignore
-            } else if (line.endsWith("@each-R@")) {
-                int blockEnd = indexAfter(template, i, "@end-R@");
-                String[] block = stringsIn(template, i+1, blockEnd-1);
-                for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
-                    expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
-                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
-                i = blockEnd-1; continue;
-            } else if (line.endsWith("@each-Tv@")) {
-                int blockEnd = indexAfter(template, i, "@end-Tv@");
-                String[] block = stringsIn(template, i+1, blockEnd-1);
-                expandTemplate(block, false, rcat, nrefs, nints, nlongs);
-                expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
-                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
-                i = blockEnd-1; continue;
-            } else {
-                System.out.println(VAR.transform(line));
-            }
-        }
-    }
-}
-//}}} */
-//params=[0, 10, 4, 99, 0, 0]
-    static class A0 extends Adapter {
-        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 invoke_L0() throws Throwable { return convert_L((Object)invoker.invokeExact(target)); }
-        protected Object invoke_I0() throws Throwable { return convert_I((int)   invoker.invokeExact(target)); }
-        protected Object invoke_J0() throws Throwable { return convert_J((long)  invoker.invokeExact(target)); }
-        protected Object invoke_F0() throws Throwable { return convert_F((float) invoker.invokeExact(target)); }
-        protected Object invoke_D0() throws Throwable { return convert_D((double)invoker.invokeExact(target)); }
-    }
-    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 invoke_L1(Object a0) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0)); }
-        protected Object invoke_I1(Object a0) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0)); }
-        protected Object invoke_J1(Object a0) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0)); }
-        protected Object invoke_F1(Object a0) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0)); }
-        protected Object invoke_D1(Object a0) throws Throwable { return convert_D((double)invoker.invokeExact(target, 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 invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
-        protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1)); }
-        protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1)); }
-        protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
-        protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, 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 invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2)); }
-        protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2)); }
-        protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2)); }
-        protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2)); }
-        protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2)); }
-    }
-    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 invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3)); }
-        protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3)); }
-        protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3)); }
-        protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3)); }
-        protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D((double)invoker.invokeExact(target, 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 invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
-    }
-    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 invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, 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 invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, 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 invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, 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 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((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, 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 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((Object)invoker.invokeExact(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((int)   invoker.invokeExact(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((long)  invoker.invokeExact(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((float) invoker.invokeExact(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((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/InvokeGeneric.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import java.lang.reflect.*;
-import sun.dyn.util.*;
-import static sun.dyn.MethodTypeImpl.invokers;
-
-/**
- * Adapters which manage MethodHanndle.invokeGeneric calls.
- * The JVM calls one of these when the exact type match fails.
- * @author jrose
- */
-class InvokeGeneric {
-    // erased type for the call, which originates from an invokeGeneric site
-    private final MethodType erasedCallerType;
-    // an invoker of type (MT, MH; A...) -> R
-    private final MethodHandle initialInvoker;
-
-    /** Compute and cache information for this adapter, so that it can
-     *  call out to targets of the erasure-family of the given erased type.
-     */
-    private InvokeGeneric(MethodType erasedCallerType) throws ReflectiveOperationException {
-        this.erasedCallerType = erasedCallerType;
-        this.initialInvoker = makeInitialInvoker();
-        assert initialInvoker.type().equals(erasedCallerType
-                                            .insertParameterTypes(0, MethodType.class, MethodHandle.class))
-            : initialInvoker.type();
-    }
-
-    private static MethodHandles.Lookup lookup() {
-        return MethodHandleImpl.IMPL_LOOKUP;
-    }
-
-    /** Return the adapter information for this type's erasure. */
-    static MethodHandle genericInvokerOf(MethodType type) {
-        MethodTypeImpl form = MethodTypeImpl.of(type);
-        MethodHandle genericInvoker = form.genericInvoker;
-        if (genericInvoker == null) {
-            try {
-                InvokeGeneric gen = new InvokeGeneric(form.erasedType());
-                form.genericInvoker = genericInvoker = gen.initialInvoker;
-            } catch (ReflectiveOperationException ex) {
-                throw new RuntimeException(ex);
-            }
-        }
-        return genericInvoker;
-    }
-
-    private MethodHandle makeInitialInvoker() throws ReflectiveOperationException {
-        // postDispatch = #(MH'; MT, MH; A...){MH'(MT, MH; A)}
-        MethodHandle postDispatch = makePostDispatchInvoker();
-        MethodHandle invoker;
-        if (returnConversionPossible()) {
-            invoker = MethodHandles.foldArguments(postDispatch,
-                                                  dispatcher("dispatchWithConversion"));
-        } else {
-            invoker = MethodHandles.foldArguments(postDispatch, dispatcher("dispatch"));
-        }
-        return invoker;
-    }
-
-    private static final Class<?>[] EXTRA_ARGS = { MethodType.class, MethodHandle.class };
-    private MethodHandle makePostDispatchInvoker() {
-        // Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...).
-        MethodType invokerType = erasedCallerType.insertParameterTypes(0, EXTRA_ARGS);
-        return invokers(invokerType).exactInvoker();
-    }
-    private MethodHandle dropDispatchArguments(MethodHandle targetInvoker) {
-        assert(targetInvoker.type().parameterType(0) == MethodHandle.class);
-        return MethodHandles.dropArguments(targetInvoker, 1, EXTRA_ARGS);
-    }
-
-    private MethodHandle dispatcher(String dispatchName) throws ReflectiveOperationException {
-        return lookup().bind(this, dispatchName,
-                             MethodType.methodType(MethodHandle.class,
-                                                   MethodType.class, MethodHandle.class));
-    }
-
-    static final boolean USE_AS_TYPE_PATH = true;
-
-    /** Return a method handle to invoke on the callerType, target, and remaining arguments.
-     *  The method handle must finish the call.
-     *  This is the first look at the caller type and target.
-     */
-    private MethodHandle dispatch(MethodType callerType, MethodHandle target) {
-        MethodType targetType = target.type();
-        if (USE_AS_TYPE_PATH || target.isVarargsCollector()) {
-            MethodHandle newTarget = target.asType(callerType);
-            targetType = callerType;
-            Invokers invokers = MethodTypeImpl.invokers(Access.TOKEN, targetType);
-            MethodHandle invoker = invokers.erasedInvokerWithDrops;
-            if (invoker == null) {
-                invokers.erasedInvokerWithDrops = invoker =
-                    dropDispatchArguments(invokers.erasedInvoker());
-            }
-            return invoker.bindTo(newTarget);
-        }
-        throw new RuntimeException("NYI");
-    }
-
-    private MethodHandle dispatchWithConversion(MethodType callerType, MethodHandle target) {
-        MethodHandle finisher = dispatch(callerType, target);
-        if (returnConversionNeeded(callerType, target))
-            finisher = addReturnConversion(finisher, callerType.returnType());  //FIXME: slow
-        return finisher;
-    }
-
-    private boolean returnConversionPossible() {
-        Class<?> needType = erasedCallerType.returnType();
-        return !needType.isPrimitive();
-    }
-    private boolean returnConversionNeeded(MethodType callerType, MethodHandle target) {
-        Class<?> needType = callerType.returnType();
-        if (needType == erasedCallerType.returnType())
-            return false;  // no conversions possible, since must be primitive or Object
-        Class<?> haveType = target.type().returnType();
-        if (VerifyType.isNullConversion(haveType, needType))
-            return false;
-        return true;
-    }
-    private MethodHandle addReturnConversion(MethodHandle target, Class<?> type) {
-        if (true) throw new RuntimeException("NYI");
-        // FIXME: This is slow because it creates a closure node on every call that requires a return cast.
-        MethodType targetType = target.type();
-        MethodHandle caster = ValueConversions.identity(type);
-        caster = caster.asType(MethodType.methodType(type, targetType.returnType()));
-        // Drop irrelevant arguments, because we only care about the return value:
-        caster = MethodHandles.dropArguments(caster, 1, targetType.parameterList());
-        MethodHandle result = MethodHandles.foldArguments(caster, target);
-        return result.asType(target.type());
-    }
-
-    public String toString() {
-        return "InvokeGeneric"+erasedCallerType;
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/Invokers.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import sun.dyn.empty.Empty;
-
-/**
- * Construction and caching of often-used invokers.
- * @author jrose
- */
-public class Invokers {
-    // exact type (sans leading taget MH) for the outgoing call
-    private final MethodType targetType;
-
-    // exact invoker for the outgoing call
-    private /*lazy*/ MethodHandle exactInvoker;
-
-    // erased (partially untyped but with primitives) invoker for the outgoing call
-    private /*lazy*/ MethodHandle erasedInvoker;
-    /*lazy*/ MethodHandle erasedInvokerWithDrops;  // for InvokeGeneric
-
-    // 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[] spreadInvokers;
-
-    // invoker for an unbound callsite
-    private /*lazy*/ MethodHandle uninitializedCallSite;
-
-    /** Compute and cache information common to all collecting adapters
-     *  that implement members of the erasure-family of the given erased type.
-     */
-    /*non-public*/ Invokers(MethodType targetType) {
-        this.targetType = targetType;
-        this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
-    }
-
-    public static MethodType invokerType(MethodType targetType) {
-        return targetType.insertParameterTypes(0, MethodHandle.class);
-    }
-
-    public MethodHandle exactInvoker() {
-        MethodHandle invoker = exactInvoker;
-        if (invoker != null)  return invoker;
-        try {
-            invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType);
-        } catch (ReflectiveOperationException ex) {
-            throw new InternalError("JVM cannot find invoker for "+targetType);
-        }
-        assert(invokerType(targetType) == invoker.type());
-        exactInvoker = invoker;
-        return invoker;
-    }
-
-    public MethodHandle genericInvoker() {
-        MethodHandle invoker1 = exactInvoker();
-        MethodHandle invoker = genericInvoker;
-        if (invoker != null)  return invoker;
-        MethodType genericType = targetType.generic();
-        invoker = MethodHandles.convertArguments(invoker1, invokerType(genericType));
-        genericInvoker = invoker;
-        return invoker;
-    }
-
-    public MethodHandle erasedInvoker() {
-        MethodHandle invoker1 = exactInvoker();
-        MethodHandle invoker = erasedInvoker;
-        if (invoker != null)  return invoker;
-        MethodType erasedType = targetType.erase();
-        if (erasedType == targetType.generic())
-            invoker = genericInvoker();
-        else
-            invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType));
-        erasedInvoker = invoker;
-        return invoker;
-    }
-
-    public MethodHandle spreadInvoker(int objectArgCount) {
-        MethodHandle vaInvoker = spreadInvokers[objectArgCount];
-        if (vaInvoker != null)  return vaInvoker;
-        MethodHandle gInvoker = genericInvoker();
-        vaInvoker = gInvoker.asSpreader(Object[].class, targetType.parameterCount() - objectArgCount);
-        spreadInvokers[objectArgCount] = vaInvoker;
-        return vaInvoker;
-    }
-
-    private static MethodHandle THROW_UCS = null;
-
-    public MethodHandle uninitializedCallSite() {
-        MethodHandle invoker = uninitializedCallSite;
-        if (invoker != null)  return invoker;
-        if (targetType.parameterCount() > 0) {
-            MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
-            Invokers invokers0 = MethodTypeImpl.invokers(type0);
-            invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
-                                                  0, targetType.parameterList());
-            assert(invoker.type().equals(targetType));
-            uninitializedCallSite = invoker;
-            return invoker;
-        }
-        if (THROW_UCS == null) {
-            try {
-                THROW_UCS = MethodHandleImpl.IMPL_LOOKUP
-                    .findStatic(CallSite.class, "uninitializedCallSite",
-                                MethodType.methodType(Empty.class));
-            } catch (ReflectiveOperationException ex) {
-                throw new RuntimeException(ex);
-            }
-        }
-        invoker = AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, targetType, THROW_UCS);
-        assert(invoker.type().equals(targetType));
-        uninitializedCallSite = invoker;
-        return invoker;
-    }
-
-    public String toString() {
-        return "Invokers"+targetType;
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/MemberName.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,739 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import sun.dyn.util.BytecodeDescriptor;
-import java.dyn.*;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-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;
-import static sun.dyn.MethodHandleNatives.Constants.*;
-
-/**
- * A {@code MemberName} is a compact symbolic datum which fully characterizes
- * a method or field reference.
- * A member name refers to a field, method, constructor, or member type.
- * Every member name has a simple name (a string) and a type (either a Class or MethodType).
- * A member name may also have a non-null declaring class, or it may be simply
- * a naked name/type pair.
- * A member name may also have non-zero modifier flags.
- * Finally, a member name may be either resolved or unresolved.
- * If it is resolved, the existence of the named
- * <p>
- * Whether resolved or not, a member name provides no access rights or
- * invocation capability to its possessor.  It is merely a compact
- * representation of all symbolic information necessary to link to
- * and properly use the named member.
- * <p>
- * When resolved, a member name's internal implementation may include references to JVM metadata.
- * This representation is stateless and only decriptive.
- * It provides no private information and no capability to use the member.
- * <p>
- * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
- * about the internals of a method (except its bytecodes) and also
- * allows invocation.  A MemberName is much lighter than a Method,
- * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
- * and those seven fields omit much of the information in Method.
- * @author jrose
- */
-public final class MemberName implements Member, Cloneable {
-    private Class<?>   clazz;       // class in which the method is defined
-    private String     name;        // may be null if not yet materialized
-    private Object     type;        // may be null if not yet materialized
-    private int        flags;       // modifier bits; see reflect.Modifier
-
-    private Object     vmtarget;    // VM-specific target value
-    private int        vmindex;     // method index within class or interface
-
-    { vmindex = VM_INDEX_UNINITIALIZED; }
-
-    /** Return the declaring class of this member.
-     *  In the case of a bare name and type, the declaring class will be null.
-     */
-    public Class<?> getDeclaringClass() {
-        if (clazz == null && isResolved()) {
-            expandFromVM();
-        }
-        return clazz;
-    }
-
-    /** Utility method producing the class loader of the declaring class. */
-    public ClassLoader getClassLoader() {
-        return clazz.getClassLoader();
-    }
-
-    /** Return the simple name of this member.
-     *  For a type, it is the same as {@link Class#getSimpleName}.
-     *  For a method or field, it is the simple name of the member.
-     *  For a constructor, it is always {@code "&lt;init&gt;"}.
-     */
-    public String getName() {
-        if (name == null) {
-            expandFromVM();
-            if (name == null)  return null;
-        }
-        return name;
-    }
-
-    /** Return the declared type of this member, which
-     *  must be a method or constructor.
-     */
-    public MethodType getMethodType() {
-        if (type == null) {
-            expandFromVM();
-            if (type == null)  return null;
-        }
-        if (!isInvocable())
-            throw newIllegalArgumentException("not invocable, no method type");
-        if (type instanceof MethodType) {
-            return (MethodType) type;
-        }
-        if (type instanceof String) {
-            String sig = (String) type;
-            MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
-            this.type = res;
-            return res;
-        }
-        if (type instanceof Object[]) {
-            Object[] typeInfo = (Object[]) type;
-            Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
-            Class<?> rtype = (Class<?>) typeInfo[0];
-            MethodType res = MethodType.methodType(rtype, ptypes);
-            this.type = res;
-            return res;
-        }
-        throw new InternalError("bad method type "+type);
-    }
-
-    /** Return the actual type under which this method or constructor must be invoked.
-     *  For non-static methods or constructors, this is the type with a leading parameter,
-     *  a reference to declaring class.  For static methods, it is the same as the declared type.
-     */
-    public MethodType getInvocationType() {
-        MethodType itype = getMethodType();
-        if (!isStatic())
-            itype = itype.insertParameterTypes(0, clazz);
-        return itype;
-    }
-
-    /** Utility method producing the parameter types of the method type. */
-    public Class<?>[] getParameterTypes() {
-        return getMethodType().parameterArray();
-    }
-
-    /** Utility method producing the return type of the method type. */
-    public Class<?> getReturnType() {
-        return getMethodType().returnType();
-    }
-
-    /** Return the declared type of this member, which
-     *  must be a field or type.
-     *  If it is a type member, that type itself is returned.
-     */
-    public Class<?> getFieldType() {
-        if (type == null) {
-            expandFromVM();
-            if (type == null)  return null;
-        }
-        if (isInvocable())
-            throw newIllegalArgumentException("not a field or nested class, no simple type");
-        if (type instanceof Class<?>) {
-            return (Class<?>) type;
-        }
-        if (type instanceof String) {
-            String sig = (String) type;
-            MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
-            Class<?> res = mtype.returnType();
-            this.type = res;
-            return res;
-        }
-        throw new InternalError("bad field type "+type);
-    }
-
-    /** Utility method to produce either the method type or field type of this member. */
-    public Object getType() {
-        return (isInvocable() ? getMethodType() : getFieldType());
-    }
-
-    /** Utility method to produce the signature of this member,
-     *  used within the class file format to describe its type.
-     */
-    public String getSignature() {
-        if (type == null) {
-            expandFromVM();
-            if (type == null)  return null;
-        }
-        if (type instanceof String)
-            return (String) type;
-        if (isInvocable())
-            return BytecodeDescriptor.unparse(getMethodType());
-        else
-            return BytecodeDescriptor.unparse(getFieldType());
-    }
-
-    /** Return the modifier flags of this member.
-     *  @see java.lang.reflect.Modifier
-     */
-    public int getModifiers() {
-        return (flags & RECOGNIZED_MODIFIERS);
-    }
-
-    private void setFlags(int flags) {
-        this.flags = flags;
-        assert(testAnyFlags(ALL_KINDS));
-    }
-
-    private boolean testFlags(int mask, int value) {
-        return (flags & mask) == value;
-    }
-    private boolean testAllFlags(int mask) {
-        return testFlags(mask, mask);
-    }
-    private boolean testAnyFlags(int mask) {
-        return !testFlags(mask, 0);
-    }
-
-    /** Utility method to query the modifier flags of this member. */
-    public boolean isStatic() {
-        return Modifier.isStatic(flags);
-    }
-    /** Utility method to query the modifier flags of this member. */
-    public boolean isPublic() {
-        return Modifier.isPublic(flags);
-    }
-    /** Utility method to query the modifier flags of this member. */
-    public boolean isPrivate() {
-        return Modifier.isPrivate(flags);
-    }
-    /** Utility method to query the modifier flags of this member. */
-    public boolean isProtected() {
-        return Modifier.isProtected(flags);
-    }
-    /** Utility method to query the modifier flags of this member. */
-    public boolean isFinal() {
-        return Modifier.isFinal(flags);
-    }
-    /** Utility method to query the modifier flags of this member. */
-    public boolean isAbstract() {
-        return Modifier.isAbstract(flags);
-    }
-    // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
-
-    // unofficial modifier flags, used by HotSpot:
-    static final int BRIDGE    = 0x00000040;
-    static final int VARARGS   = 0x00000080;
-    static final int SYNTHETIC = 0x00001000;
-    static final int ANNOTATION= 0x00002000;
-    static final int ENUM      = 0x00004000;
-    /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
-    public boolean isBridge() {
-        return testAllFlags(IS_METHOD | BRIDGE);
-    }
-    /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
-    public boolean isVarargs() {
-        return testAllFlags(VARARGS) && isInvocable();
-    }
-    /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
-    public boolean isSynthetic() {
-        return testAllFlags(SYNTHETIC);
-    }
-
-    static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
-
-    // modifiers exported by the JVM:
-    static final int RECOGNIZED_MODIFIERS = 0xFFFF;
-
-    // private flags, not part of RECOGNIZED_MODIFIERS:
-    static final int
-            IS_METHOD      = MN_IS_METHOD,      // method (not constructor)
-            IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
-            IS_FIELD       = MN_IS_FIELD,       // field
-            IS_TYPE        = MN_IS_TYPE;        // nested type
-    static final int  // for MethodHandleNatives.getMembers
-            SEARCH_SUPERCLASSES = MN_SEARCH_SUPERCLASSES,
-            SEARCH_INTERFACES   = MN_SEARCH_INTERFACES;
-
-    static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
-    static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
-    static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
-    static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
-    static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES;
-
-    /** Utility method to query whether this member is a method or constructor. */
-    public boolean isInvocable() {
-        return testAnyFlags(IS_INVOCABLE);
-    }
-    /** Utility method to query whether this member is a method, constructor, or field. */
-    public boolean isFieldOrMethod() {
-        return testAnyFlags(IS_FIELD_OR_METHOD);
-    }
-    /** Query whether this member is a method. */
-    public boolean isMethod() {
-        return testAllFlags(IS_METHOD);
-    }
-    /** Query whether this member is a constructor. */
-    public boolean isConstructor() {
-        return testAllFlags(IS_CONSTRUCTOR);
-    }
-    /** Query whether this member is a field. */
-    public boolean isField() {
-        return testAllFlags(IS_FIELD);
-    }
-    /** Query whether this member is a type. */
-    public boolean isType() {
-        return testAllFlags(IS_TYPE);
-    }
-    /** Utility method to query whether this member is neither public, private, nor protected. */
-    public boolean isPackage() {
-        return !testAnyFlags(ALL_ACCESS);
-    }
-
-    /** Initialize a query.   It is not resolved. */
-    private void init(Class<?> defClass, String name, Object type, int flags) {
-        // defining class is allowed to be null (for a naked name/type pair)
-        //name.toString();  // null check
-        //type.equals(type);  // null check
-        // fill in fields:
-        this.clazz = defClass;
-        this.name = name;
-        this.type = type;
-        setFlags(flags);
-        assert(!isResolved());
-    }
-
-    private void expandFromVM() {
-        if (!isResolved())  return;
-        if (type instanceof Object[])
-            type = null;  // don't saddle JVM w/ typeInfo
-        MethodHandleNatives.expand(this);
-    }
-
-    // Capturing information from the Core Reflection API:
-    private static int flagsMods(int flags, int mods) {
-        assert((flags & RECOGNIZED_MODIFIERS) == 0);
-        assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
-        return flags | mods;
-    }
-    /** Create a name for the given reflected method.  The resulting name will be in a resolved state. */
-    public MemberName(Method m) {
-        Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() };
-        init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers()));
-        // fill in vmtarget, vmindex while we have m in hand:
-        MethodHandleNatives.init(this, m);
-        assert(isResolved());
-    }
-    /** Create a name for the given reflected constructor.  The resulting name will be in a resolved state. */
-    public MemberName(Constructor ctor) {
-        Object[] typeInfo = { void.class, ctor.getParameterTypes() };
-        init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
-        // fill in vmtarget, vmindex while we have ctor in hand:
-        MethodHandleNatives.init(this, ctor);
-        assert(isResolved());
-    }
-    /** Create a name for the given reflected field.  The resulting name will be in a resolved state. */
-    public MemberName(Field fld) {
-        init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers()));
-        // fill in vmtarget, vmindex while we have fld in hand:
-        MethodHandleNatives.init(this, fld);
-        assert(isResolved());
-    }
-    /** Create a name for the given class.  The resulting name will be in a resolved state. */
-    public MemberName(Class<?> type) {
-        init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers()));
-        vmindex = 0;  // isResolved
-        assert(isResolved());
-    }
-
-    // bare-bones constructor; the JVM will fill it in
-    MemberName() { }
-
-    // locally useful cloner
-    @Override protected MemberName clone() {
-        try {
-            return (MemberName) super.clone();
-        } catch (CloneNotSupportedException ex) {
-            throw new InternalError();
-        }
-     }
-
-    // %%% define equals/hashcode?
-
-    // Construction from symbolic parts, for queries:
-    /** Create a field or type name from the given components:  Declaring class, name, type, modifiers.
-     *  The declaring class may be supplied as null if this is to be a bare name and type.
-     *  The resulting name will in an unresolved state.
-     */
-    public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) {
-        init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS));
-    }
-    /** Create a field or type name from the given components:  Declaring class, name, type.
-     *  The declaring class may be supplied as null if this is to be a bare name and type.
-     *  The modifier flags default to zero.
-     *  The resulting name will in an unresolved state.
-     */
-    public MemberName(Class<?> defClass, String name, Class<?> type) {
-        this(defClass, name, type, 0);
-    }
-    /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
-     *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
-     *  The declaring class may be supplied as null if this is to be a bare name and type.
-     *  The resulting name will in an unresolved state.
-     */
-    public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) {
-        int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
-        init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS));
-    }
-    /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
-     *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
-     *  The declaring class may be supplied as null if this is to be a bare name and type.
-     *  The modifier flags default to zero.
-     *  The resulting name will in an unresolved state.
-     */
-    public MemberName(Class<?> defClass, String name, MethodType type) {
-        this(defClass, name, type, 0);
-    }
-
-    /** Query whether this member name is resolved.
-     *  A resolved member name is one for which the JVM has found
-     *  a method, constructor, field, or type binding corresponding exactly to the name.
-     *  (Document?)
-     */
-    public boolean isResolved() {
-        return (vmindex != VM_INDEX_UNINITIALIZED);
-    }
-
-    /** Query whether this member name is resolved to a non-static, non-final method.
-     */
-    public boolean hasReceiverTypeDispatch() {
-        return (isMethod() && getVMIndex(Access.TOKEN) >= 0);
-    }
-
-    /** Produce a string form of this member name.
-     *  For types, it is simply the type's own string (as reported by {@code toString}).
-     *  For fields, it is {@code "DeclaringClass.name/type"}.
-     *  For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
-     *  If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
-     *  If the member is unresolved, a prefix {@code "*."} is prepended.
-     */
-    @Override
-    public String toString() {
-        if (isType())
-            return type.toString();  // class java.lang.String
-        // else it is a field, method, or constructor
-        StringBuilder buf = new StringBuilder();
-        if (getDeclaringClass() != null) {
-            buf.append(getName(clazz));
-            buf.append('.');
-        }
-        String name = getName();
-        buf.append(name == null ? "*" : name);
-        Object type = getType();
-        if (!isInvocable()) {
-            buf.append('/');
-            buf.append(type == null ? "*" : getName(type));
-        } else {
-            buf.append(type == null ? "(*)*" : getName(type));
-        }
-        /*
-        buf.append('/');
-        // key: Public, private, pRotected, sTatic, Final, sYnchronized,
-        // transient/Varargs, native, (interface), abstract, sTrict, sYnthetic,
-        // (annotation), Enum, (unused)
-        final String FIELD_MOD_CHARS  = "PprTF?vt????Y?E?";
-        final String METHOD_MOD_CHARS = "PprTFybVn?atY???";
-        String modChars = (isInvocable() ? METHOD_MOD_CHARS : FIELD_MOD_CHARS);
-        for (int i = 0; i < modChars.length(); i++) {
-            if ((flags & (1 << i)) != 0) {
-                char mc = modChars.charAt(i);
-                if (mc != '?')
-                    buf.append(mc);
-            }
-        }
-         */
-        return buf.toString();
-    }
-    private static String getName(Object obj) {
-        if (obj instanceof Class<?>)
-            return ((Class<?>)obj).getName();
-        return String.valueOf(obj);
-    }
-
-    // Queries to the JVM:
-    /** Document? */
-    public int getVMIndex(Access token) {
-        Access.check(token);
-        if (!isResolved())
-            throw newIllegalStateException("not resolved");
-        return vmindex;
-    }
-//    public Object getVMTarget(Access token) {
-//        Access.check(token);
-//        if (!isResolved())
-//            throw newIllegalStateException("not resolved");
-//        return vmtarget;
-//    }
-    private RuntimeException newIllegalStateException(String message) {
-        return new IllegalStateException(message+": "+this);
-    }
-
-    // handy shared exception makers (they simplify the common case code)
-    public static RuntimeException newIllegalArgumentException(String message) {
-        return new IllegalArgumentException(message);
-    }
-    public static IllegalAccessException newNoAccessException(MemberName name, Object from) {
-        return newNoAccessException("cannot access", name, from);
-    }
-    public static IllegalAccessException newNoAccessException(String message,
-            MemberName name, Object from) {
-        message += ": " + name;
-        if (from != null)  message += ", from " + from;
-        return new IllegalAccessException(message);
-    }
-    public static ReflectiveOperationException newNoAccessException(MemberName name) {
-        if (name.isResolved())
-            return new IllegalAccessException(name.toString());
-        else if (name.isConstructor())
-            return new NoSuchMethodException(name.toString());
-        else if (name.isMethod())
-            return new NoSuchMethodException(name.toString());
-        else
-            return new NoSuchFieldException(name.toString());
-    }
-    public static Error uncaughtException(Exception ex) {
-        Error err = new InternalError("uncaught exception");
-        err.initCause(ex);
-        return err;
-    }
-
-    /** Actually making a query requires an access check. */
-    public static Factory getFactory(Access token) {
-        Access.check(token);
-        return Factory.INSTANCE;
-    }
-    public static Factory getFactory() {
-        return getFactory(Access.getToken());
-    }
-    /** A factory type for resolving member names with the help of the VM.
-     *  TBD: Define access-safe public constructors for this factory.
-     */
-    public static class Factory {
-        private Factory() { } // singleton pattern
-        static Factory INSTANCE = new Factory();
-
-        private static int ALLOWED_FLAGS = SEARCH_ALL_SUPERS | ALL_KINDS;
-
-        /// Queries
-        List<MemberName> getMembers(Class<?> defc,
-                String matchName, Object matchType,
-                int matchFlags, Class<?> lookupClass) {
-            matchFlags &= ALLOWED_FLAGS;
-            String matchSig = null;
-            if (matchType != null) {
-                matchSig = BytecodeDescriptor.unparse(matchType);
-                if (matchSig.startsWith("("))
-                    matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
-                else
-                    matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
-            }
-            final int BUF_MAX = 0x2000;
-            int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
-            MemberName[] buf = newMemberBuffer(len1);
-            int totalCount = 0;
-            ArrayList<MemberName[]> bufs = null;
-            int bufCount = 0;
-            for (;;) {
-                bufCount = MethodHandleNatives.getMembers(defc,
-                        matchName, matchSig, matchFlags,
-                        lookupClass,
-                        totalCount, buf);
-                if (bufCount <= buf.length) {
-                    if (bufCount < 0)  bufCount = 0;
-                    totalCount += bufCount;
-                    break;
-                }
-                // JVM returned to us with an intentional overflow!
-                totalCount += buf.length;
-                int excess = bufCount - buf.length;
-                if (bufs == null)  bufs = new ArrayList<MemberName[]>(1);
-                bufs.add(buf);
-                int len2 = buf.length;
-                len2 = Math.max(len2, excess);
-                len2 = Math.max(len2, totalCount / 4);
-                buf = newMemberBuffer(Math.min(BUF_MAX, len2));
-            }
-            ArrayList<MemberName> result = new ArrayList<MemberName>(totalCount);
-            if (bufs != null) {
-                for (MemberName[] buf0 : bufs) {
-                    Collections.addAll(result, buf0);
-                }
-            }
-            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.
-            if (matchType != null && matchType != matchSig) {
-                for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
-                    MemberName m = it.next();
-                    if (!matchType.equals(m.getType()))
-                        it.remove();
-                }
-            }
-            return result;
-        }
-        boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
-            if (m.name == null || m.type == null) {  // find unique non-overloaded name
-                Class<?> defc = m.getDeclaringClass();
-                List<MemberName> choices = null;
-                if (m.isMethod())
-                    choices = getMethods(defc, searchSupers, m.name, (MethodType) m.type, lookupClass);
-                else if (m.isConstructor())
-                    choices = getConstructors(defc, lookupClass);
-                else if (m.isField())
-                    choices = getFields(defc, searchSupers, m.name, (Class<?>) m.type, lookupClass);
-                //System.out.println("resolving "+m+" to "+choices);
-                if (choices == null || choices.size() != 1)
-                    return false;
-                if (m.name == null)  m.name = choices.get(0).name;
-                if (m.type == null)  m.type = choices.get(0).type;
-            }
-            MethodHandleNatives.resolve(m, lookupClass);
-            if (m.isResolved())  return true;
-            int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
-            String matchSig = m.getSignature();
-            MemberName[] buf = { m };
-            int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
-                    m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
-            if (n != 1)  return false;
-            return m.isResolved();
-        }
-        /** Produce a resolved version of the given member.
-         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
-         *  Access checking is performed on behalf of the given {@code lookupClass}.
-         *  If lookup fails or access is not permitted, null is returned.
-         *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
-         */
-        public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) {
-            MemberName result = m.clone();
-            if (resolveInPlace(result, searchSupers, lookupClass))
-                return result;
-            return null;
-        }
-        /** Produce a resolved version of the given member.
-         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
-         *  Access checking is performed on behalf of the given {@code lookupClass}.
-         *  If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
-         *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
-         */
-        public
-        <NoSuchMemberException extends ReflectiveOperationException>
-        MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass,
-                                 Class<NoSuchMemberException> nsmClass)
-                throws IllegalAccessException, NoSuchMemberException {
-            MemberName result = resolveOrNull(m, searchSupers, lookupClass);
-            if (result != null)
-                return result;
-            ReflectiveOperationException ex = newNoAccessException(m);
-            if (ex instanceof IllegalAccessException)  throw (IllegalAccessException) ex;
-            throw nsmClass.cast(ex);
-        }
-        /** Return a list of all methods defined by the given class.
-         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
-         *  Access checking is performed on behalf of the given {@code lookupClass}.
-         *  Inaccessible members are not added to the last.
-         */
-        public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
-                Class<?> lookupClass) {
-            return getMethods(defc, searchSupers, null, null, lookupClass);
-        }
-        /** Return a list of matching methods defined by the given class.
-         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
-         *  Returned methods will match the name (if not null) and the type (if not null).
-         *  Access checking is performed on behalf of the given {@code lookupClass}.
-         *  Inaccessible members are not added to the last.
-         */
-        public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
-                String name, MethodType type, Class<?> lookupClass) {
-            int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
-            return getMembers(defc, name, type, matchFlags, lookupClass);
-        }
-        /** Return a list of all constructors defined by the given class.
-         *  Access checking is performed on behalf of the given {@code lookupClass}.
-         *  Inaccessible members are not added to the last.
-         */
-        public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
-            return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
-        }
-        /** Return a list of all fields defined by the given class.
-         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
-         *  Access checking is performed on behalf of the given {@code lookupClass}.
-         *  Inaccessible members are not added to the last.
-         */
-        public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
-                Class<?> lookupClass) {
-            return getFields(defc, searchSupers, null, null, lookupClass);
-        }
-        /** Return a list of all fields defined by the given class.
-         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
-         *  Returned fields will match the name (if not null) and the type (if not null).
-         *  Access checking is performed on behalf of the given {@code lookupClass}.
-         *  Inaccessible members are not added to the last.
-         */
-        public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
-                String name, Class<?> type, Class<?> lookupClass) {
-            int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
-            return getMembers(defc, name, type, matchFlags, lookupClass);
-        }
-        /** Return a list of all nested types defined by the given class.
-         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
-         *  Access checking is performed on behalf of the given {@code lookupClass}.
-         *  Inaccessible members are not added to the last.
-         */
-        public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
-                Class<?> lookupClass) {
-            int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
-            return getMembers(defc, null, null, matchFlags, lookupClass);
-        }
-        private static MemberName[] newMemberBuffer(int length) {
-            MemberName[] buf = new MemberName[length];
-            // fill the buffer with dummy structs for the JVM to fill in
-            for (int i = 0; i < length; i++)
-                buf[i] = new MemberName();
-            return buf;
-        }
-    }
-
-//    static {
-//        System.out.println("Hello world!  My methods are:");
-//        System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
-//    }
-}
--- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1284 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import java.dyn.MethodHandles.Lookup;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import sun.dyn.util.VerifyType;
-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;
-import static sun.dyn.MemberName.uncaughtException;
-
-/**
- * Base class for method handles, containing JVM-specific fields and logic.
- * TO DO:  It should not be a base class.
- * @author jrose
- */
-public abstract class MethodHandleImpl {
-
-    // Fields which really belong in MethodHandle:
-    private byte       vmentry;    // adapter stub or method entry point
-    //private int      vmslots;    // optionally, hoist type.form.vmslots
-    protected Object   vmtarget;   // VM-specific, class-specific target value
-    //MethodType       type;       // defined in MethodHandle
-
-    // TO DO:  vmtarget should be invisible to Java, since the JVM puts internal
-    // managed pointers into it.  Making it visible exposes it to debuggers,
-    // which can cause errors when they treat the pointer as an Object.
-
-    // These two dummy fields are present to force 'I' and 'J' signatures
-    // into this class's constant pool, so they can be transferred
-    // to vmentry when this class is loaded.
-    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.
-    // The JVM adjusts its type to int or long depending on system wordsize.
-    // Since it is statically typed as neither int nor long, it is impossible
-    // to use this field from Java bytecode.  (Please don't try to, either.)
-
-    // The vmentry is an assembly-language stub which is jumped to
-    // immediately after the method type is verified.
-    // For a direct MH, this stub loads the vmtarget's entry point
-    // and jumps to it.
-
-    /**
-     * VM-based method handles must have a security token.
-     * This security token can only be obtained by trusted code.
-     * Do not create method handles directly; use factory methods.
-     */
-    public MethodHandleImpl(Access token) {
-        Access.check(token);
-    }
-
-    /** Initialize the method type form to participate in JVM calls.
-     *  This is done once for each erased type.
-     */
-    public static void init(Access token, MethodType self) {
-        Access.check(token);
-        if (MethodHandleNatives.JVM_SUPPORT)
-            MethodHandleNatives.init(self);
-    }
-
-    /// Factory methods to create method handles:
-
-    private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE;
-
-    static private Lookup IMPL_LOOKUP_INIT;
-
-    public static void initLookup(Access token, Lookup lookup) {
-        Access.check(token);
-        if (IMPL_LOOKUP_INIT != null)
-            throw new InternalError();
-        IMPL_LOOKUP_INIT = lookup;
-    }
-
-    public static Lookup getLookup(Access token) {
-        Access.check(token);
-        return IMPL_LOOKUP;
-    }
-
-    static {
-        if (!MethodHandleNatives.JVM_SUPPORT)  // force init of native API
-            throw new InternalError("No JVM support for JSR 292");
-        // Force initialization of Lookup, so it calls us back as initLookup:
-        MethodHandles.publicLookup();
-        if (IMPL_LOOKUP_INIT == null)
-            throw new InternalError();
-    }
-
-    public static void initStatics() {
-        // Trigger preceding sequence.
-    }
-
-    /** Shared secret with MethodHandles.Lookup, a copy of Lookup.IMPL_LOOKUP. */
-    static final Lookup IMPL_LOOKUP = IMPL_LOOKUP_INIT;
-
-
-    /** Look up a given method.
-     * Callable only from java.dyn and related packages.
-     * <p>
-     * The resulting method handle type will be of the given type,
-     * with a receiver type {@code rcvc} prepended if the member is not static.
-     * <p>
-     * Access checks are made as of the given lookup class.
-     * In particular, if the method is protected and {@code defc} is in a
-     * different package from the lookup class, then {@code rcvc} must be
-     * the lookup class or a subclass.
-     * @param token Proof that the lookup class has access to this package.
-     * @param member Resolved method or constructor to call.
-     * @param name Name of the desired method.
-     * @param rcvc Receiver type of desired non-static method (else null)
-     * @param doDispatch whether the method handle will test the receiver type
-     * @param lookupClass access-check relative to this class
-     * @return a direct handle to the matching method
-     * @throws IllegalAccessException if the given method cannot be accessed by the lookup class
-     */
-    public static
-    MethodHandle findMethod(Access token, MemberName method,
-                            boolean doDispatch, Class<?> lookupClass) throws IllegalAccessException {
-        Access.check(token);  // only trusted calls
-        MethodType mtype = method.getMethodType();
-        if (!method.isStatic()) {
-            // 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.insertParameterTypes(0, recvType);
-        }
-        DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
-        if (!mh.isValid())
-            throw newNoAccessException(method, lookupClass);
-        assert(mh.type() == mtype);
-        if (!method.isVarargs())
-            return mh;
-        else
-            return mh.asVarargsCollector(mtype.parameterType(mtype.parameterCount()-1));
-    }
-
-    public static
-    MethodHandle makeAllocator(Access token, MethodHandle rawConstructor) {
-        Access.check(token);
-        MethodType rawConType = rawConstructor.type();
-        // Wrap the raw (unsafe) constructor with the allocation of a suitable object.
-        MethodHandle allocator
-            = AllocateObject.make(token, rawConType.parameterType(0), rawConstructor);
-        assert(allocator.type()
-               .equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
-        return allocator;
-    }
-
-    static final class AllocateObject<C> extends BoundMethodHandle {
-        private static final Unsafe unsafe = Unsafe.getUnsafe();
-
-        private final Class<C> allocateClass;
-        private final MethodHandle rawConstructor;
-
-        private AllocateObject(MethodHandle invoker,
-                               Class<C> allocateClass, MethodHandle rawConstructor) {
-            super(Access.TOKEN, invoker);
-            this.allocateClass = allocateClass;
-            this.rawConstructor = rawConstructor;
-        }
-        static MethodHandle make(Access token,
-                                 Class<?> allocateClass, MethodHandle rawConstructor) {
-            Access.check(token);
-            MethodType rawConType = rawConstructor.type();
-            assert(rawConType.parameterType(0) == allocateClass);
-            MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
-            int nargs = rawConType.parameterCount() - 1;
-            if (nargs < INVOKES.length) {
-                MethodHandle invoke = INVOKES[nargs];
-                MethodType conType = CON_TYPES[nargs];
-                MethodHandle gcon = convertArguments(token, rawConstructor, conType, rawConType, null);
-                if (gcon == null)  return null;
-                MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
-                assert(galloc.type() == newType.generic());
-                return convertArguments(token, galloc, newType, galloc.type(), null);
-            } else {
-                MethodHandle invoke = VARARGS_INVOKE;
-                MethodType conType = CON_TYPES[nargs];
-                MethodHandle gcon = spreadArguments(token, rawConstructor, conType, 1);
-                if (gcon == null)  return null;
-                MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
-                return collectArguments(token, galloc, newType, 1, null);
-            }
-        }
-        @Override
-        public String toString() {
-            return addTypeString(allocateClass.getSimpleName(), this);
-        }
-        @SuppressWarnings("unchecked")
-        private C allocate() throws InstantiationException {
-            return (C) unsafe.allocateInstance(allocateClass);
-        }
-        private C invoke_V(Object... av) throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj, av);
-            return obj;
-        }
-        private C invoke_L0() throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj);
-            return obj;
-        }
-        private C invoke_L1(Object a0) throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj, a0);
-            return obj;
-        }
-        private C invoke_L2(Object a0, Object a1) throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj, a0, a1);
-            return obj;
-        }
-        private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj, a0, a1, a2);
-            return obj;
-        }
-        private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3);
-            return obj;
-        }
-        private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4);
-            return obj;
-        }
-        private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5);
-            return obj;
-        }
-        private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6);
-            return obj;
-        }
-        private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
-            C obj = allocate();
-            rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7);
-            return obj;
-        }
-        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(AllocateObject.class, name, MethodType.genericMethodType(nargs));
-                } catch (ReflectiveOperationException 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(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
-            } catch (ReflectiveOperationException ex) {
-                throw uncaughtException(ex);
-            }
-        }
-        // Corresponding generic constructor types:
-        static final MethodType[] CON_TYPES = new MethodType[INVOKES.length];
-        static {
-            for (int i = 0; i < INVOKES.length; i++)
-                CON_TYPES[i] = makeConType(INVOKES[i]);
-        }
-        static final MethodType VARARGS_CON_TYPE = makeConType(VARARGS_INVOKE);
-        static MethodType makeConType(MethodHandle invoke) {
-            MethodType invType = invoke.type();
-            return invType.changeParameterType(0, Object.class).changeReturnType(void.class);
-        }
-    }
-
-    public static
-    MethodHandle accessField(Access token,
-                             MemberName member, boolean isSetter,
-                             Class<?> lookupClass) {
-        Access.check(token);
-        // 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) {
-        Access.check(token);
-        if (!arrayClass.isArray())
-            throw newIllegalArgumentException("not an array: "+arrayClass);
-        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 BoundMethodHandle {
-        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(Access.TOKEN, 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 addTypeString(name, this); }
-
-        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) {
-                throw uncaughtException(ee);
-            }
-        }
-
-        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 (ReflectiveOperationException ex) {
-                throw uncaughtException(ex);
-            }
-            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 (ReflectiveOperationException ex) {
-                throw uncaughtException(ex);
-            }
-            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.
-     * Callable only from MethodHandles.
-     * @param token Proof that the caller has access to this package.
-     * @param target Any direct method handle.
-     * @param receiver Receiver (or first static method argument) to pre-bind.
-     * @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
-     */
-    public static
-    MethodHandle bindReceiver(Access token,
-                              MethodHandle target, Object receiver) {
-        Access.check(token);
-        if (target instanceof AdapterMethodHandle &&
-            ((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
-            ) {
-            Object info = MethodHandleNatives.getTargetInfo(target);
-            if (info instanceof DirectMethodHandle) {
-                DirectMethodHandle dmh = (DirectMethodHandle) info;
-                if (receiver == null ||
-                    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)
-            return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
-        return null;   // let caller try something else
-    }
-
-    /** Bind a predetermined argument to the given arbitrary method handle.
-     * Callable only from MethodHandles.
-     * @param token Proof that the caller has access to this package.
-     * @param target Any method handle.
-     * @param receiver Argument (which can be a boxed primitive) to pre-bind.
-     * @return a suitable BoundMethodHandle
-     */
-    public static
-    MethodHandle bindArgument(Access token,
-                              MethodHandle target, int argnum, Object receiver) {
-        Access.check(token);
-        return new BoundMethodHandle(target, receiver, argnum);
-    }
-
-    public static MethodHandle convertArguments(Access token,
-                                                MethodHandle target,
-                                                MethodType newType,
-                                                MethodType oldType,
-                                                int[] permutationOrNull) {
-        Access.check(token);
-        assert(oldType.parameterCount() == target.type().parameterCount());
-        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;
-        int argc = oldType.parameterCount();
-        // The JVM can't do it directly, so fill in the gap with a Java adapter.
-        // TO DO: figure out what to put here from case-by-case experience
-        // 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.genericMethodType(argc);
-        MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target);
-        if (objTarget == null)
-            objTarget = FromGeneric.make(target);
-        res = AdapterMethodHandle.makePairwiseConvert(token, newType, objTarget);
-        if (res != null)
-            return res;
-        return ToGeneric.make(newType, objTarget);
-    }
-
-    public static MethodHandle spreadArguments(Access token,
-                                               MethodHandle target,
-                                               MethodType newType,
-                                               int spreadArg) {
-        Access.check(token);
-        // TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
-        MethodType oldType = target.type();
-        // spread the last argument of newType to oldType
-        int spreadCount = oldType.parameterCount() - spreadArg;
-        Class<Object[]> spreadArgType = Object[].class;
-        MethodHandle res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount);
-        if (res != null)
-            return res;
-        // try an intermediate adapter
-        Class<?> spreadType = null;
-        if (spreadArg < 0 || spreadArg >= newType.parameterCount()
-            || !VerifyType.isSpreadArgType(spreadType = newType.parameterType(spreadArg)))
-            throw newIllegalArgumentException("no restarg in "+newType);
-        Class<?>[] ptypes = oldType.parameterArray();
-        for (int i = 0; i < spreadCount; i++)
-            ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i);
-        MethodType midType = MethodType.methodType(newType.returnType(), ptypes);
-        // after spreading, some arguments may need further conversion
-        MethodHandle target2 = convertArguments(token, target, midType, oldType, null);
-        if (target2 == null)
-            throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType);
-        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,
-                                                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 BoundMethodHandle {
-        private final MethodHandle test, target, fallback;
-        private GuardWithTest(MethodHandle invoker,
-                              MethodHandle test, MethodHandle target, MethodHandle fallback) {
-            super(Access.TOKEN, invoker);
-            this.test = test;
-            this.target = target;
-            this.fallback = fallback;
-        }
-        static MethodHandle make(Access token,
-                                 MethodHandle test, MethodHandle target, MethodHandle fallback) {
-            Access.check(token);
-            MethodType type = target.type();
-            int nargs = type.parameterCount();
-            if (nargs < INVOKES.length) {
-                MethodHandle invoke = INVOKES[nargs];
-                MethodType gtype = type.generic();
-                assert(invoke.type().dropParameterTypes(0,1) == gtype);
-                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(invoke, gtest, gtarget, gfallback);
-                return convertArguments(token, gguard, type, gtype, null);
-            } else {
-                MethodHandle invoke = VARARGS_INVOKE;
-                MethodType gtype = MethodType.genericMethodType(1);
-                assert(invoke.type().dropParameterTypes(0,1) == gtype);
-                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(invoke, gtest, gtarget, gfallback);
-                if (gtest == null || gtarget == null || gfallback == null)  return null;
-                return collectArguments(token, gguard, type, 0, null);
-            }
-        }
-        @Override
-        public String toString() {
-            return addTypeString(target, this);
-        }
-        private Object invoke_V(Object... av) throws Throwable {
-            if ((boolean) test.invokeExact(av))
-                return target.invokeExact(av);
-            return fallback.invokeExact(av);
-        }
-        private Object invoke_L0() throws Throwable {
-            if ((boolean) test.invokeExact())
-                return target.invokeExact();
-            return fallback.invokeExact();
-        }
-        private Object invoke_L1(Object a0) throws Throwable {
-            if ((boolean) test.invokeExact(a0))
-                return target.invokeExact(a0);
-            return fallback.invokeExact(a0);
-        }
-        private Object invoke_L2(Object a0, Object a1) throws Throwable {
-            if ((boolean) test.invokeExact(a0, a1))
-                return target.invokeExact(a0, a1);
-            return fallback.invokeExact(a0, a1);
-        }
-        private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
-            if ((boolean) test.invokeExact(a0, a1, a2))
-                return target.invokeExact(a0, a1, a2);
-            return fallback.invokeExact(a0, a1, a2);
-        }
-        private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            if ((boolean) test.invokeExact(a0, a1, a2, a3))
-                return target.invokeExact(a0, a1, a2, a3);
-            return fallback.invokeExact(a0, a1, a2, a3);
-        }
-        private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
-            if ((boolean) test.invokeExact(a0, a1, a2, a3, a4))
-                return target.invokeExact(a0, a1, a2, a3, a4);
-            return fallback.invokeExact(a0, a1, a2, a3, a4);
-        }
-        private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
-            if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5))
-                return target.invokeExact(a0, a1, a2, a3, a4, a5);
-            return fallback.invokeExact(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 ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6))
-                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
-            return fallback.invokeExact(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 ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7))
-                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
-            return fallback.invokeExact(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 (ReflectiveOperationException 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 (ReflectiveOperationException ex) {
-                throw uncaughtException(ex);
-            }
-        }
-    }
-
-    public static
-    MethodHandle makeGuardWithTest(Access token,
-                                   MethodHandle test,
-                                   MethodHandle target,
-                                   MethodHandle fallback) {
-        return GuardWithTest.make(token, test, target, fallback);
-    }
-
-    private static class GuardWithCatch extends BoundMethodHandle {
-        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(Access.TOKEN, invoker);
-            this.target = target;
-            this.exType = exType;
-            this.catcher = catcher;
-        }
-        @Override
-        public String toString() {
-            return addTypeString(target, this);
-        }
-        private Object invoke_V(Object... av) throws Throwable {
-            try {
-                return target.invokeExact(av);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, av);
-            }
-        }
-        private Object invoke_L0() throws Throwable {
-            try {
-                return target.invokeExact();
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t);
-            }
-        }
-        private Object invoke_L1(Object a0) throws Throwable {
-            try {
-                return target.invokeExact(a0);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0);
-            }
-        }
-        private Object invoke_L2(Object a0, Object a1) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1);
-            }
-        }
-        private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1, a2);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1, a2);
-            }
-        }
-        private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1, a2, a3);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(t, a0, a1, a2, a3);
-            }
-        }
-        private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
-            try {
-                return target.invokeExact(a0, a1, a2, a3, a4);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(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.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
-            } catch (Throwable t) {
-                if (!exType.isInstance(t))  throw t;
-                return catcher.invokeExact(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 (ReflectiveOperationException 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 (ReflectiveOperationException ex) {
-                throw uncaughtException(ex);
-            }
-        }
-    }
-
-
-    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 throwException(Access token, MethodType type) {
-        Access.check(token);
-        return AdapterMethodHandle.makeRetypeRaw(token, type, THROW_EXCEPTION);
-    }
-
-    static final MethodHandle THROW_EXCEPTION;
-    static {
-        try {
-            THROW_EXCEPTION
-            = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
-                    MethodType.methodType(Empty.class, Throwable.class));
-        } catch (ReflectiveOperationException ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-    static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
-
-    public static String getNameString(Access token, MethodHandle target, Object type) {
-        Access.check(token);
-        if (!(type instanceof MethodType)) {
-            if (type == null)
-                type = target.type();
-            else if (type instanceof MethodHandle)
-                type = ((MethodHandle)type).type();
-        }
-        MemberName name = null;
-        if (target != null)
-            name = MethodHandleNatives.getMethodName(target);
-        if (name == null)
-            return "invoke" + type;
-        return name.getName() + type;
-    }
-
-    public static String getNameString(Access token, MethodHandle target) {
-        return getNameString(token, target, null);
-    }
-
-    static String addTypeString(Object obj, MethodHandle target) {
-        String str = String.valueOf(obj);
-        if (target == null)  return str;
-        int paren = str.indexOf('(');
-        if (paren >= 0) str = str.substring(0, paren);
-        return str + target.type();
-    }
-
-    static void checkSpreadArgument(Object av, int n) {
-        if (av == null ? n != 0 : ((Object[])av).length != n)
-            throw newIllegalArgumentException("Array is not of length "+n);
-    }
-
-    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);
-        }
-    }
-
-    // Linkage support:
-    public static void registerBootstrap(Access token, Class<?> callerClass, MethodHandle bootstrapMethod) {
-        Access.check(token);
-        MethodHandleNatives.registerBootstrap(callerClass, bootstrapMethod);
-    }
-    public static MethodHandle getBootstrap(Access token, Class<?> callerClass) {
-        Access.check(token);
-        return MethodHandleNatives.getBootstrap(callerClass);
-    }
-
-    public static MethodHandle asVarargsCollector(Access token, MethodHandle target, Class<?> arrayType) {
-        Access.check(token);
-        return AdapterMethodHandle.makeVarargsCollector(token, target, arrayType);
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,359 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import java.dyn.MethodHandles.Lookup;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import static sun.dyn.MethodHandleNatives.Constants.*;
-import static sun.dyn.MethodHandleImpl.IMPL_LOOKUP;
-
-/**
- * The JVM interface for the method handles package is all here.
- * This is an interface internal and private to an implemetantion of JSR 292.
- * <em>This class is not part of the JSR 292 standard.</em>
- * @author jrose
- */
-class MethodHandleNatives {
-
-    private MethodHandleNatives() { } // static only
-
-    /// MethodName support
-
-    static native void init(MemberName self, Object ref);
-    static native void expand(MemberName self);
-    static native void resolve(MemberName self, Class<?> caller);
-    static native int getMembers(Class<?> defc, String matchName, String matchSig,
-            int matchFlags, Class<?> caller, int skip, MemberName[] results);
-
-    /// MethodHandle support
-
-    /** Initialize the method handle to adapt the call. */
-    static native void init(AdapterMethodHandle self, MethodHandle target, int argnum);
-    /** Initialize the method handle to call the correct method, directly. */
-    static native void init(BoundMethodHandle self, Object target, int argnum);
-    /** Initialize the method handle to call as if by an invoke* instruction. */
-    static native void init(DirectMethodHandle self, Object ref, boolean doDispatch, Class<?> caller);
-
-    /** Initialize a method type, once per form. */
-    static native void init(MethodType self);
-
-    /** Tell the JVM about a class's bootstrap method. */
-    static native void registerBootstrap(Class<?> caller, MethodHandle bootstrapMethod);
-
-    /** Ask the JVM about a class's bootstrap method. */
-    static native MethodHandle getBootstrap(Class<?> caller);
-
-    /** Tell the JVM that we need to change the target of an invokedynamic. */
-    static native void setCallSiteTarget(CallSite site, MethodHandle target);
-
-    /** Fetch the vmtarget field.
-     *  It will be sanitized as necessary to avoid exposing non-Java references.
-     *  This routine is for debugging and reflection.
-     */
-    static native Object getTarget(MethodHandle self, int format);
-
-    /** Fetch the name of the handled method, if available.
-     *  This routine is for debugging and reflection.
-     */
-    static MemberName getMethodName(MethodHandle self) {
-        if (!JVM_SUPPORT)  return null;
-        return (MemberName) getTarget(self, ETF_METHOD_NAME);
-    }
-
-    /** Fetch the reflective version of the handled method, if available.
-     */
-    static AccessibleObject getTargetMethod(MethodHandle self) {
-        if (!JVM_SUPPORT)  return null;
-        return (AccessibleObject) getTarget(self, ETF_REFLECT_METHOD);
-    }
-
-    /** Fetch the target of this method handle.
-     *  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) {
-        if (!JVM_SUPPORT)  return null;
-        return getTarget(self, ETF_HANDLE_OR_METHOD_NAME);
-    }
-
-    static Object[] makeTarget(Class<?> defc, String name, String sig, int mods, Class<?> refc) {
-        return new Object[] { defc, name, sig, mods, refc };
-    }
-
-    /** Fetch MH-related JVM parameter.
-     *  which=0 retrieves MethodHandlePushLimit
-     *  which=1 retrieves stack slot push size (in address units)
-     */
-    static native int getConstant(int which);
-
-    /** True iff this HotSpot JVM has built-in support for method handles.
-     * If false, some test cases might run, but functionality will be missing.
-     */
-    public static final boolean JVM_SUPPORT;
-
-    /** Java copy of MethodHandlePushLimit in range 2..255. */
-    static final int JVM_PUSH_LIMIT;
-    /** JVM stack motion (in words) after one slot is pushed, usually -1.
-     */
-    static final int JVM_STACK_MOVE_UNIT;
-
-    /** Which conv-ops are implemented by the JVM? */
-    static final int CONV_OP_IMPLEMENTED_MASK;
-
-    private static native void registerNatives();
-    static {
-        boolean JVM_SUPPORT_;
-        int     JVM_PUSH_LIMIT_;
-        int     JVM_STACK_MOVE_UNIT_;
-        int     CONV_OP_IMPLEMENTED_MASK_;
-        try {
-            registerNatives();
-            JVM_SUPPORT_ = true;
-            JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
-            JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT);
-            CONV_OP_IMPLEMENTED_MASK_ = getConstant(Constants.GC_CONV_OP_IMPLEMENTED_MASK);
-            //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
-        } catch (UnsatisfiedLinkError ee) {
-            // ignore; if we use init() methods later we'll see linkage errors
-            JVM_SUPPORT_ = false;
-            JVM_PUSH_LIMIT_ = 3;  // arbitrary
-            JVM_STACK_MOVE_UNIT_ = -1;  // arbitrary
-            CONV_OP_IMPLEMENTED_MASK_ = 0;
-            //System.out.println("Warning: Running with JVM_SUPPORT=false");
-            //System.out.println(ee);
-            JVM_SUPPORT = JVM_SUPPORT_;
-            JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
-            JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
-            throw ee;  // just die; hopeless to try to run with an older JVM
-        }
-        JVM_SUPPORT = JVM_SUPPORT_;
-        JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
-        JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
-        if (CONV_OP_IMPLEMENTED_MASK_ == 0)
-            CONV_OP_IMPLEMENTED_MASK_ = DEFAULT_CONV_OP_IMPLEMENTED_MASK;
-        CONV_OP_IMPLEMENTED_MASK = CONV_OP_IMPLEMENTED_MASK_;
-    }
-
-    // All compile-time constants go here.
-    // There is an opportunity to check them against the JVM's idea of them.
-    static class Constants {
-        Constants() { } // static only
-        // MethodHandleImpl
-        static final int // for getConstant
-                GC_JVM_PUSH_LIMIT = 0,
-                GC_JVM_STACK_MOVE_UNIT = 1,
-                GC_CONV_OP_IMPLEMENTED_MASK = 2;
-        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)
-                ETF_METHOD_NAME           = 2, // ultimate method as MemberName
-                ETF_REFLECT_METHOD        = 3; // ultimate method as java.lang.reflect object (sans refClass)
-
-        // MemberName
-        // The JVM uses values of -2 and above for vtable indexes.
-        // Field values are simple positive offsets.
-        // Ref: src/share/vm/oops/methodOop.hpp
-        // This value is negative enough to avoid such numbers,
-        // but not too negative.
-        static final int
-                MN_IS_METHOD           = 0x00010000, // method (not constructor)
-                MN_IS_CONSTRUCTOR      = 0x00020000, // constructor
-                MN_IS_FIELD            = 0x00040000, // field
-                MN_IS_TYPE             = 0x00080000, // nested type
-                MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
-                MN_SEARCH_INTERFACES   = 0x00200000, // for MHN.getMembers
-                VM_INDEX_UNINITIALIZED = -99;
-
-        // AdapterMethodHandle
-        /** Conversions recognized by the JVM.
-         *  They must align with the constants in sun.dyn_AdapterMethodHandle,
-         *  in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp.
-         */
-        static final int
-            OP_RETYPE_ONLY   = 0x0, // no argument changes; straight retype
-            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.
-         */
-        static final int
-            CONV_OP_MASK     = 0xF00, // this nybble contains the conversion op field
-            CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
-            CONV_VMINFO_SHIFT     =  0, // position of bits in CONV_VMINFO_MASK
-            CONV_OP_SHIFT         =  8, // position of bits in CONV_OP_MASK
-            CONV_DEST_TYPE_SHIFT  = 12, // byte 2 has the adapter BasicType (if needed)
-            CONV_SRC_TYPE_SHIFT   = 16, // byte 2 has the source BasicType (if needed)
-            CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
-            CONV_STACK_MOVE_MASK  = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1;
-
-        /** Which conv-ops are implemented by the JVM? */
-        static final int DEFAULT_CONV_OP_IMPLEMENTED_MASK =
-                // Value to use if the corresponding JVM query fails.
-                ((1<<OP_RETYPE_ONLY)
-                |(1<<OP_RETYPE_RAW)
-                |(1<<OP_CHECK_CAST)
-                |(1<<OP_PRIM_TO_PRIM)
-                |(1<<OP_REF_TO_PRIM)
-                |(1<<OP_SWAP_ARGS)
-                |(1<<OP_ROT_ARGS)
-                |(1<<OP_DUP_ARGS)
-                |(1<<OP_DROP_ARGS)
-                //|(1<<OP_SPREAD_ARGS)
-                );
-
-        /**
-         * Basic types as encoded in the JVM.  These code values are not
-         * intended for use outside this class.  They are used as part of
-         * a private interface between the JVM and this class.
-         */
-        static final int
-            T_BOOLEAN  =  4,
-            T_CHAR     =  5,
-            T_FLOAT    =  6,
-            T_DOUBLE   =  7,
-            T_BYTE     =  8,
-            T_SHORT    =  9,
-            T_INT      = 10,
-            T_LONG     = 11,
-            T_OBJECT   = 12,
-            //T_ARRAY    = 13
-            T_VOID     = 14;
-            //T_ADDRESS  = 15
-
-        /**
-         * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
-         */
-        static final int
-            REF_getField                = 1,
-            REF_getStatic               = 2,
-            REF_putField                = 3,
-            REF_putStatic               = 4,
-            REF_invokeVirtual           = 5,
-            REF_invokeStatic            = 6,
-            REF_invokeSpecial           = 7,
-            REF_newInvokeSpecial        = 8,
-            REF_invokeInterface         = 9;
-    }
-
-    private static native int getNamedCon(int which, Object[] name);
-    static boolean verifyConstants() {
-        Object[] box = { null };
-        for (int i = 0; ; i++) {
-            box[0] = null;
-            int vmval = getNamedCon(i, box);
-            if (box[0] == null)  break;
-            String name = (String) box[0];
-            try {
-                Field con = Constants.class.getDeclaredField(name);
-                int jval = con.getInt(null);
-                if (jval != vmval)
-                    throw new InternalError(name+": JVM has "+vmval+" while Java has "+jval);
-            } catch (Exception ex) {
-                throw new InternalError(name+": access failed, got "+ex);
-            }
-        }
-        return true;
-    }
-    static {
-        if (JVM_SUPPORT)  verifyConstants();
-    }
-
-    // Up-calls from the JVM.
-    // These must NOT be public.
-
-    /**
-     * The JVM is linking an invokedynamic instruction.  Create a reified call site for it.
-     */
-    static CallSite makeDynamicCallSite(MethodHandle bootstrapMethod,
-                                        String name, MethodType type,
-                                        Object info,
-                                        MemberName callerMethod, int callerBCI) {
-        return CallSiteImpl.makeSite(bootstrapMethod, name, type, info, callerMethod, callerBCI);
-    }
-
-    /**
-     * The JVM wants a pointer to a MethodType.  Oblige it by finding or creating one.
-     */
-    static MethodType findMethodHandleType(Class<?> rtype, Class<?>[] ptypes) {
-        MethodType.genericMethodType(0);  // trigger initialization
-        return MethodTypeImpl.makeImpl(Access.TOKEN, rtype, ptypes, true);
-    }
-
-    /**
-     * The JVM wants to use a MethodType with invokeGeneric.  Give the runtime fair warning.
-     */
-    static void notifyGenericMethodType(MethodType type) {
-        try {
-            // Trigger adapter creation.
-            InvokeGeneric.genericInvokerOf(type);
-        } catch (Exception ex) {
-            Error err = new InternalError("Exception while resolving invokeGeneric");
-            err.initCause(ex);
-            throw err;
-        }
-    }
-
-    /**
-     * The JVM is resolving a CONSTANT_MethodHandle CP entry.  And it wants our help.
-     * It will make an up-call to this method.  (Do not change the name or signature.)
-     */
-    static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
-                                                 Class<?> defc, String name, Object type) {
-        try {
-            Lookup lookup = IMPL_LOOKUP.in(callerClass);
-            switch (refKind) {
-            case REF_getField:          return lookup.findGetter(       defc, name, (Class<?>)   type );
-            case REF_getStatic:         return lookup.findStaticGetter( defc, name, (Class<?>)   type );
-            case REF_putField:          return lookup.findSetter(       defc, name, (Class<?>)   type );
-            case REF_putStatic:         return lookup.findStaticSetter( defc, name, (Class<?>)   type );
-            case REF_invokeVirtual:     return lookup.findVirtual(      defc, name, (MethodType) type );
-            case REF_invokeStatic:      return lookup.findStatic(       defc, name, (MethodType) type );
-            case REF_invokeSpecial:     return lookup.findSpecial(      defc, name, (MethodType) type, callerClass );
-            case REF_newInvokeSpecial:  return lookup.findConstructor(  defc,       (MethodType) type );
-            case REF_invokeInterface:   return lookup.findVirtual(      defc, name, (MethodType) type );
-            }
-            throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
-        } catch (ReflectiveOperationException ex) {
-            Error err = new IncompatibleClassChangeError();
-            err.initCause(ex);
-            throw err;
-        }
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,516 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import sun.dyn.util.Wrapper;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-
-/**
- * Shared information for a group of method types, which differ
- * only by reference types, and therefore share a common erasure
- * and wrapping.
- * <p>
- * For an empirical discussion of the structure of method types,
- * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
- * the thread "Avoiding Boxing" on jvm-languages</a>.
- * There are approximately 2000 distinct erased method types in the JDK.
- * There are a little over 10 times that number of unerased types.
- * No more than half of these are likely to be loaded at once.
- * @author John Rose
- */
-public class MethodTypeImpl {
-    final int[] argToSlotTable, slotToArgTable;
-    final long argCounts;               // packed slot & value counts
-    final long primCounts;              // packed prim & double counts
-    final int vmslots;                  // total number of parameter slots
-    final MethodType erasedType;        // the canonical erasure
-
-    /*lazy*/ MethodType primsAsBoxes;   // replace prims by wrappers
-    /*lazy*/ MethodType primArgsAsBoxes; // wrap args only; make raw return
-    /*lazy*/ MethodType primsAsInts;    // replace prims by int/long
-    /*lazy*/ MethodType primsAsLongs;   // replace prims by long
-    /*lazy*/ MethodType primsAtEnd;     // reorder primitives to the end
-
-    // 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*/ MethodHandle genericInvoker; // hook for invokeGeneric
-
-    public MethodType erasedType() {
-        return erasedType;
-    }
-
-    public static MethodTypeImpl of(MethodType type) {
-        return METHOD_TYPE_FRIEND.form(type);
-    }
-
-    /** Access methods for the internals of MethodType, supplied to
-     *  MethodTypeImpl as a trusted agent.
-     */
-    static public interface MethodTypeFriend {
-        Class<?>[]     ptypes(MethodType mt);
-        MethodTypeImpl form(MethodType mt);
-        void           setForm(MethodType mt, MethodTypeImpl form);
-        MethodType     makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted);
-        MethodTypeImpl newMethodTypeForm(MethodType mt);
-        Invokers       getInvokers(MethodType mt);
-        void           setInvokers(MethodType mt, Invokers inv);
-    }
-    public static void setMethodTypeFriend(Access token, MethodTypeFriend am) {
-        Access.check(token);
-        if (METHOD_TYPE_FRIEND != null)
-            throw new InternalError();  // just once
-        METHOD_TYPE_FRIEND = am;
-    }
-    static private MethodTypeFriend METHOD_TYPE_FRIEND;
-
-    static MethodType makeImpl(Access token, Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
-        Access.check(token);
-        return METHOD_TYPE_FRIEND.makeImpl(rtype, ptypes, trusted);
-    }
-
-    protected MethodTypeImpl(MethodType erasedType) {
-        this.erasedType = erasedType;
-
-        Class<?>[] ptypes = METHOD_TYPE_FRIEND.ptypes(erasedType);
-        int ptypeCount = ptypes.length;
-        int pslotCount = ptypeCount;            // temp. estimate
-        int rtypeCount = 1;                     // temp. estimate
-        int rslotCount = 1;                     // temp. estimate
-
-        int[] argToSlotTab = null, slotToArgTab = null;
-
-        // Walk the argument types, looking for primitives.
-        int pac = 0, lac = 0, prc = 0, lrc = 0;
-        Class<?> epts[] = ptypes;
-        for (int i = 0; i < epts.length; i++) {
-            Class<?> pt = epts[i];
-            if (pt != Object.class) {
-                assert(pt.isPrimitive());
-                ++pac;
-                if (hasTwoArgSlots(pt))  ++lac;
-            }
-        }
-        pslotCount += lac;                  // #slots = #args + #longs
-        Class<?> rt = erasedType.returnType();
-        if (rt != Object.class) {
-            ++prc;          // even void.class counts as a prim here
-            if (hasTwoArgSlots(rt))  ++lrc;
-            // adjust #slots, #args
-            if (rt == void.class)
-                rtypeCount = rslotCount = 0;
-            else
-                rslotCount += lrc;
-        }
-        if (lac != 0) {
-            int slot = ptypeCount + lac;
-            slotToArgTab = new int[slot+1];
-            argToSlotTab = new int[1+ptypeCount];
-            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
-            for (int i = 0; i < epts.length; i++) {
-                Class<?> pt = epts[i];
-                if (hasTwoArgSlots(pt))  --slot;
-                --slot;
-                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
-                argToSlotTab[1+i]  = slot;
-            }
-            assert(slot == 0);  // filled the table
-        }
-        this.primCounts = pack(lrc, prc, lac, pac);
-        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
-        if (slotToArgTab == null) {
-            int slot = ptypeCount; // first arg is deepest in stack
-            slotToArgTab = new int[slot+1];
-            argToSlotTab = new int[1+ptypeCount];
-            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
-            for (int i = 0; i < ptypeCount; i++) {
-                --slot;
-                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
-                argToSlotTab[1+i]  = slot;
-            }
-        }
-        this.argToSlotTable = argToSlotTab;
-        this.slotToArgTable = slotToArgTab;
-
-        if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
-
-        // send a few bits down to the JVM:
-        this.vmslots = parameterSlotCount();
-
-        // short circuit some no-op canonicalizations:
-        if (!hasPrimitives()) {
-            primsAsBoxes = erasedType;
-            primArgsAsBoxes = erasedType;
-            primsAsInts  = erasedType;
-            primsAsLongs = erasedType;
-            primsAtEnd   = erasedType;
-        }
-    }
-
-    /** Turn all primitive types to corresponding wrapper types.
-     */
-    public MethodType primsAsBoxes() {
-        MethodType ct = primsAsBoxes;
-        if (ct != null)  return ct;
-        MethodType t = erasedType;
-        ct = canonicalize(erasedType, WRAP, WRAP);
-        if (ct == null)  ct = t;  // no prims to box
-        return primsAsBoxes = ct;
-    }
-
-    /** Turn all primitive argument types to corresponding wrapper types.
-     *  Subword and void return types are promoted to int.
-     */
-    public MethodType primArgsAsBoxes() {
-        MethodType ct = primArgsAsBoxes;
-        if (ct != null)  return ct;
-        MethodType t = erasedType;
-        ct = canonicalize(erasedType, RAW_RETURN, WRAP);
-        if (ct == null)  ct = t;  // no prims to box
-        return primArgsAsBoxes = ct;
-    }
-
-    /** Turn all primitive types to either int or long.
-     *  Floating point return types are not changed, because
-     *  they may require special calling sequences.
-     *  A void return value is turned to int.
-     */
-    public MethodType primsAsInts() {
-        MethodType ct = primsAsInts;
-        if (ct != null)  return ct;
-        MethodType t = erasedType;
-        ct = canonicalize(t, RAW_RETURN, INTS);
-        if (ct == null)  ct = t;  // no prims to int-ify
-        return primsAsInts = ct;
-    }
-
-    /** Turn all primitive types to either int or long.
-     *  Floating point return types are not changed, because
-     *  they may require special calling sequences.
-     *  A void return value is turned to int.
-     */
-    public MethodType primsAsLongs() {
-        MethodType ct = primsAsLongs;
-        if (ct != null)  return ct;
-        MethodType t = erasedType;
-        ct = canonicalize(t, RAW_RETURN, LONGS);
-        if (ct == null)  ct = t;  // no prims to int-ify
-        return primsAsLongs = ct;
-    }
-
-    /** Stably sort parameters into 3 buckets: ref, int, long. */
-    public MethodType primsAtEnd() {
-        MethodType ct = primsAtEnd;
-        if (ct != null)  return ct;
-        MethodType t = erasedType;
-
-        int pac = primitiveParameterCount();
-        if (pac == 0)
-            return primsAtEnd = t;
-
-        int argc = parameterCount();
-        int lac = longPrimitiveParameterCount();
-        if (pac == argc && (lac == 0 || lac == argc))
-            return primsAtEnd = t;
-
-        // known to have a mix of 2 or 3 of ref, int, long
-        int[] reorder = primsAtEndOrder(t);
-        ct = reorderParameters(t, reorder, null);
-        //System.out.println("t="+t+" / reorder="+java.util.Arrays.toString(reorder)+" => "+ct);
-        return primsAtEnd = ct;
-    }
-
-    /** Compute a new ordering of parameters so that all references
-     *  are before all ints or longs, and all ints are before all longs.
-     *  For this ordering, doubles count as longs, and all other primitive
-     *  values count as ints.
-     *  As a special case, if the parameters are already in the specified
-     *  order, this method returns a null reference, rather than an array
-     *  specifying a null permutation.
-     *  <p>
-     *  For example, the type {@code (int,boolean,int,Object,String)void}
-     *  produces the order {@code {3,4,0,1,2}}, the type
-     *  {@code (long,int,String)void} produces {@code {2,1,2}}, and
-     *  the type {@code (Object,int)Object} produces {@code null}.
-     */
-    public static int[] primsAtEndOrder(MethodType mt) {
-        MethodTypeImpl form = METHOD_TYPE_FRIEND.form(mt);
-        if (form.primsAtEnd == form.erasedType)
-            // quick check shows no reordering is necessary
-            return null;
-
-        int argc = form.parameterCount();
-        int[] paramOrder = new int[argc];
-
-        // 3-way bucket sort:
-        int pac = form.primitiveParameterCount();
-        int lac = form.longPrimitiveParameterCount();
-        int rfill = 0, ifill = argc - pac, lfill = argc - lac;
-
-        Class<?>[] ptypes = METHOD_TYPE_FRIEND.ptypes(mt);
-        boolean changed = false;
-        for (int i = 0; i < ptypes.length; i++) {
-            Class<?> pt = ptypes[i];
-            int ord;
-            if (!pt.isPrimitive())             ord = rfill++;
-            else if (!hasTwoArgSlots(pt))      ord = ifill++;
-            else                               ord = lfill++;
-            if (ord != i)  changed = true;
-            assert(paramOrder[ord] == 0);
-            paramOrder[ord] = i;
-        }
-        assert(rfill == argc - pac && ifill == argc - lac && lfill == argc);
-        if (!changed) {
-            form.primsAtEnd = form.erasedType;
-            return null;
-        }
-        return paramOrder;
-    }
-
-    /** Put the existing parameters of mt into a new order, given by newParamOrder.
-     *  The third argument is logically appended to mt.parameterArray,
-     *  so that elements of newParamOrder can index either pre-existing or
-     *  new parameter types.
-     */
-    public static MethodType reorderParameters(MethodType mt, int[] newParamOrder, Class<?>[] moreParams) {
-        if (newParamOrder == null)  return mt;  // no-op reordering
-        Class<?>[] ptypes = METHOD_TYPE_FRIEND.ptypes(mt);
-        Class<?>[] ntypes = new Class<?>[newParamOrder.length];
-        int maxParam = ptypes.length + (moreParams == null ? 0 : moreParams.length);
-        boolean changed = (ntypes.length != ptypes.length);
-        for (int i = 0; i < newParamOrder.length; i++) {
-            int param = newParamOrder[i];
-            if (param != i)  changed = true;
-            Class<?> nt;
-            if (param < ptypes.length)   nt = ptypes[param];
-            else if (param == maxParam)  nt = mt.returnType();
-            else                         nt = moreParams[param - ptypes.length];
-            ntypes[i] = nt;
-        }
-        if (!changed)  return mt;
-        return METHOD_TYPE_FRIEND.makeImpl(mt.returnType(), ntypes, true);
-    }
-
-    private static boolean hasTwoArgSlots(Class<?> type) {
-        return type == long.class || type == double.class;
-    }
-
-    private static long pack(int a, int b, int c, int d) {
-        assert(((a|b|c|d) & ~0xFFFF) == 0);
-        long hw = ((a << 16) | b), lw = ((c << 16) | d);
-        return (hw << 32) | lw;
-    }
-    private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
-        assert(word <= 3);
-        return (char)(packed >> ((3-word) * 16));
-    }
-
-    public int parameterCount() {                      // # outgoing values
-        return unpack(argCounts, 3);
-    }
-    public int parameterSlotCount() {                  // # outgoing interpreter slots
-        return unpack(argCounts, 2);
-    }
-    public int returnCount() {                         // = 0 (V), or 1
-        return unpack(argCounts, 1);
-    }
-    public int returnSlotCount() {                     // = 0 (V), 2 (J/D), or 1
-        return unpack(argCounts, 0);
-    }
-    public int primitiveParameterCount() {
-        return unpack(primCounts, 3);
-    }
-    public int longPrimitiveParameterCount() {
-        return unpack(primCounts, 2);
-    }
-    public int primitiveReturnCount() {                // = 0 (obj), or 1
-        return unpack(primCounts, 1);
-    }
-    public int longPrimitiveReturnCount() {            // = 1 (J/D), or 0
-        return unpack(primCounts, 0);
-    }
-    public boolean hasPrimitives() {
-        return primCounts != 0;
-    }
-//    public boolean hasNonVoidPrimitives() {
-//        if (primCounts == 0)  return false;
-//        if (primitiveParameterCount() != 0)  return true;
-//        return (primitiveReturnCount() != 0 && returnCount() != 0);
-//    }
-    public boolean hasLongPrimitives() {
-        return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
-    }
-    public int parameterToArgSlot(int i) {
-        return argToSlotTable[1+i];
-    }
-    public int argSlotToParameter(int argSlot) {
-        // Note:  Empty slots are represented by zero in this table.
-        // Valid arguments slots contain incremented entries, so as to be non-zero.
-        // We return -1 the caller to mean an empty slot.
-        return slotToArgTable[argSlot] - 1;
-    }
-
-    public static void initForm(Access token, MethodType mt) {
-        Access.check(token);
-        MethodTypeImpl form = findForm(mt);
-        METHOD_TYPE_FRIEND.setForm(mt, form);
-        if (form.erasedType == mt) {
-            // This is a principal (erased) type; show it to the JVM.
-            MethodHandleImpl.init(token, mt);
-        }
-    }
-
-    static MethodTypeImpl findForm(MethodType mt) {
-        MethodType erased = canonicalize(mt, ERASE, ERASE);
-        if (erased == null) {
-            // It is already erased.  Make a new MethodTypeImpl.
-            return METHOD_TYPE_FRIEND.newMethodTypeForm(mt);
-        } else {
-            // Share the MethodTypeImpl with the erased version.
-            return METHOD_TYPE_FRIEND.form(erased);
-        }
-    }
-
-    /** Codes for {@link #canonicalize(java.lang.Class, int).
-     * ERASE means change every reference to {@code Object}.
-     * WRAP means convert primitives (including {@code void} to their
-     * corresponding wrapper types.  UNWRAP means the reverse of WRAP.
-     * INTS means convert all non-void primitive types to int or long,
-     * according to size.  LONGS means convert all non-void primitives
-     * to long, regardless of size.  RAW_RETURN means convert a type
-     * (assumed to be a return type) to int if it is smaller than an int,
-     * or if it is void.
-     */
-    public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
-
-    /** Canonicalize the types in the given method type.
-     * If any types change, intern the new type, and return it.
-     * Otherwise return null.
-     */
-    public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
-        Class<?>[] ptypes = METHOD_TYPE_FRIEND.ptypes(mt);
-        Class<?>[] ptc = MethodTypeImpl.canonicalizes(ptypes, howArgs);
-        Class<?> rtype = mt.returnType();
-        Class<?> rtc = MethodTypeImpl.canonicalize(rtype, howRet);
-        if (ptc == null && rtc == null) {
-            // It is already canonical.
-            return null;
-        }
-        // Find the erased version of the method type:
-        if (rtc == null)  rtc = rtype;
-        if (ptc == null)  ptc = ptypes;
-        return METHOD_TYPE_FRIEND.makeImpl(rtc, ptc, true);
-    }
-
-    /** Canonicalize the given return or param type.
-     *  Return null if the type is already canonicalized.
-     */
-    static Class<?> canonicalize(Class<?> t, int how) {
-        Class<?> ct;
-        if (t == Object.class) {
-            // no change, ever
-        } else if (!t.isPrimitive()) {
-            switch (how) {
-                case UNWRAP:
-                    ct = Wrapper.asPrimitiveType(t);
-                    if (ct != t)  return ct;
-                    break;
-                case RAW_RETURN:
-                case ERASE:
-                    return Object.class;
-            }
-        } else if (t == void.class) {
-            // no change, usually
-            switch (how) {
-                case RAW_RETURN:
-                    return int.class;
-                case WRAP:
-                    return Void.class;
-            }
-        } else {
-            // non-void primitive
-            switch (how) {
-                case WRAP:
-                    return Wrapper.asWrapperType(t);
-                case INTS:
-                    if (t == int.class || t == long.class)
-                        return null;  // no change
-                    if (t == double.class)
-                        return long.class;
-                    return int.class;
-                case LONGS:
-                    if (t == long.class)
-                        return null;  // no change
-                    return long.class;
-                case RAW_RETURN:
-                    if (t == int.class || t == long.class ||
-                        t == float.class || t == double.class)
-                        return null;  // no change
-                    // everything else returns as an int
-                    return int.class;
-            }
-        }
-        // no change; return null to signify
-        return null;
-    }
-
-    /** Canonicalize each param type in the given array.
-     *  Return null if all types are already canonicalized.
-     */
-    static Class<?>[] canonicalizes(Class<?>[] ts, int how) {
-        Class<?>[] cs = null;
-        for (int imax = ts.length, i = 0; i < imax; i++) {
-            Class<?> c = canonicalize(ts[i], how);
-            if (c != null) {
-                if (cs == null)
-                    cs = ts.clone();
-                cs[i] = c;
-            }
-        }
-        return cs;
-    }
-
-    public static Invokers invokers(Access token, MethodType type) {
-        Access.check(token);
-        return invokers(type);
-    }
-    /*non-public*/ static Invokers invokers(MethodType type) {
-        Invokers inv = METHOD_TYPE_FRIEND.getInvokers(type);
-        if (inv != null)  return inv;
-        inv = new Invokers(type);
-        METHOD_TYPE_FRIEND.setInvokers(type, inv);
-        return inv;
-    }
-
-    @Override
-    public String toString() {
-        return "Form"+erasedType;
-    }
-
-}
--- a/jdk/src/share/classes/sun/dyn/SpreadGeneric.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,678 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-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 (ReflectiveOperationException 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 BoundMethodHandle {
-        /*
-         * 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 MethodHandleImpl.addTypeString(target, this);
-        }
-
-        static final MethodHandle NO_ENTRY = ValueConversions.identity();
-
-        protected boolean isPrototype() { return target == null; }
-        protected Adapter(SpreadGeneric outer) {
-            super(Access.TOKEN, NO_ENTRY);
-            this.outer = outer;
-            this.target = null;
-            assert(isPrototype());
-        }
-
-        protected Adapter(SpreadGeneric outer, MethodHandle target) {
-            super(Access.TOKEN, 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.invokeExact(a0, a1)); }
-        protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1);
-             return target.invokeExact(a0,
-                super.select(av,0)); }
-        protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1);
-             return target.invokeExact(
-                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.invokeExact(@av@); }",
-        "        //@each-S@",
-        "        protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);",
-        "            return target.invokeExact(@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.invokeExact(); }
-    }
-    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.invokeExact(a0); }
-        protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1);
-            return target.invokeExact(
-                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.invokeExact(a0, a1); }
-        protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1);
-            return target.invokeExact(a0,
-                super.select(av,0)); }
-        protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2);
-            return target.invokeExact(
-                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.invokeExact(a0, a1, a2); }
-        protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1);
-            return target.invokeExact(a0, a1,
-                super.select(av,0)); }
-        protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2);
-            return target.invokeExact(a0,
-                super.select(av,0), super.select(av,1)); }
-        protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3);
-            return target.invokeExact(
-                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
-                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
-                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
-                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
-                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
-                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
-                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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(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.invokeExact(
-                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	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1042 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.*;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.Wrapper;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-import static sun.dyn.MethodTypeImpl.invokers;
-
-/**
- * Adapters which mediate between incoming calls which are not generic
- * and outgoing calls which are.  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
- * only Object arguments.  A non-generic call therefore features
- * primitives and/or reference types other than Object.
- * An adapter has types for its incoming and outgoing calls.
- * The incoming call type is simply determined by the adapter's type
- * (the MethodType it presents to callers).  The outgoing call type
- * is determined by the adapter's target (a MethodHandle that the adapter
- * 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.)
- * @author jrose
- */
-class ToGeneric {
-    // type for the incoming call (may be erased)
-    private final MethodType entryType;
-    // incoming type with primitives moved to the end and turned to int/long
-    private final MethodType rawEntryType;
-    // adapter for the erased type
-    private final Adapter adapter;
-    // entry point for adapter (Adapter mh, a...) => ...
-    private final MethodHandle entryPoint;
-    // permutation of arguments for primsAtEndType
-    private final int[] primsAtEndOrder;
-    // optional final argument list conversions (at least, invokes the target)
-    private final MethodHandle invoker;
-    // conversion which unboxes a primitive return value
-    private final MethodHandle returnConversion;
-
-    /** 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) {
-        assert(entryType.erase() == entryType); // for now
-        // incoming call will first "forget" all reference types except Object
-        this.entryType = entryType;
-        MethodHandle invoker0 = invokers(entryType.generic()).exactInvoker();
-        MethodType rawEntryTypeInit;
-        Adapter ad = findAdapter(rawEntryTypeInit = entryType);
-        if (ad != null) {
-            // Immediate hit to exactly the adapter we want,
-            // with no monkeying around with primitive types.
-            this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
-            this.rawEntryType = rawEntryTypeInit;
-            this.adapter = ad;
-            this.entryPoint = ad.prototypeEntryPoint();
-            this.primsAtEndOrder = null;
-            this.invoker = invoker0;
-            return;
-        }
-
-        // next, it will reorder primitives after references
-        MethodType primsAtEnd = MethodTypeImpl.of(entryType).primsAtEnd();
-        // at the same time, it will "forget" all primitive types except int/long
-        this.primsAtEndOrder = MethodTypeImpl.primsAtEndOrder(entryType);
-        if (primsAtEndOrder != null) {
-            // reordering is required; build on top of a simpler ToGeneric
-            ToGeneric va2 = ToGeneric.of(primsAtEnd);
-            this.adapter = va2.adapter;
-            if (true) throw new UnsupportedOperationException("NYI: primitive parameters must follow references; entryType = "+entryType);
-            this.entryPoint = MethodHandleImpl.convertArguments(Access.TOKEN,
-                    va2.entryPoint, primsAtEnd, entryType, primsAtEndOrder);
-            // example: for entryType of (int,Object,Object), the reordered
-            // type is (Object,Object,int) and the order is {1,2,0},
-            // and putPAE is (mh,int0,obj1,obj2) => mh.invokeExact(obj1,obj2,int0)
-            return;
-        }
-
-        // after any needed argument reordering, it will reinterpret
-        // primitive arguments according to their "raw" types int/long
-        MethodType intsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsInts();
-        ad = findAdapter(rawEntryTypeInit = intsAtEnd);
-        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) {
-                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();
-            }
-        }
-        MethodType tepType = entryType.insertParameterTypes(0, ad.getClass());
-        this.entryPoint =
-            AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, rawEntryPoint);
-        if (this.entryPoint == null)
-            throw new UnsupportedOperationException("cannot retype to "+entryType
-                    +" from "+rawEntryPoint.type().dropParameterTypes(0, 1));
-        this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
-        this.rawEntryType = rawEntryTypeInit;
-        this.adapter = ad;
-        this.invoker = makeRawArgumentFilter(invoker0, rawEntryTypeInit, entryType);
-    }
-
-    /** A generic argument list will be created by a call of type 'raw'.
-     *  The values need to be reboxed for to match 'cooked'.
-     *  Do this on the fly.
-     */
-    // TO DO: Use a generic argument converter in a different file
-    static MethodHandle makeRawArgumentFilter(MethodHandle invoker,
-            MethodType raw, MethodType cooked) {
-        MethodHandle filteredInvoker = null;
-        for (int i = 0, nargs = raw.parameterCount(); i < nargs; i++) {
-            Class<?> src = raw.parameterType(i);
-            Class<?> dst = cooked.parameterType(i);
-            if (src == dst)  continue;
-            assert(src.isPrimitive() && dst.isPrimitive());
-            if (filteredInvoker == null) {
-                filteredInvoker =
-                        AdapterMethodHandle.makeCheckCast(Access.TOKEN,
-                            invoker.type().generic(), invoker, 0, MethodHandle.class);
-                if (filteredInvoker == null)  throw new UnsupportedOperationException("NYI");
-            }
-            MethodHandle reboxer = ValueConversions.rebox(dst, false);
-            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);
-    }
-
-    /**
-     * Caller will be expecting a result from a call to {@code type},
-     * while the internal adapter entry point is rawEntryType.
-     * Also, the internal target method will be returning a boxed value,
-     * as an untyped object.
-     * <p>
-     * Produce a value converter which will be typed to convert from
-     * {@code Object} to the return value of {@code rawEntryType}, and will
-     * in fact ensure that the value is compatible with the return type of
-     * {@code type}.
-     */
-    private static MethodHandle computeReturnConversion(
-            MethodType type, MethodType rawEntryType, boolean mustCast) {
-        Class<?> tret = type.returnType();
-        Class<?> rret = rawEntryType.returnType();
-        if (mustCast || !tret.isPrimitive()) {
-            assert(!tret.isPrimitive());
-            assert(!rret.isPrimitive());
-            if (rret == Object.class && !mustCast)
-                return null;
-            return ValueConversions.cast(tret, false);
-        } else if (tret == rret) {
-            return ValueConversions.unbox(tret, false);
-        } else {
-            assert(rret.isPrimitive());
-            assert(tret == double.class ? rret == long.class : rret == int.class);
-            return ValueConversions.unboxRaw(tret, false);
-        }
-    }
-
-    Adapter makeInstance(MethodType type, MethodHandle genericTarget) {
-        genericTarget.getClass();  // check for NPE
-        MethodHandle convert = returnConversion;
-        if (primsAtEndOrder != null)
-            // reorder arguments passed to genericTarget, if primsAtEndOrder
-            throw new UnsupportedOperationException("NYI");
-        if (type == entryType) {
-            if (convert == null)  convert = ValueConversions.identity();
-            return adapter.makeInstance(entryPoint, invoker, convert, genericTarget);
-        }
-        // my erased-type is not exactly the same as the desired type
-        assert(type.erase() == entryType);  // else we are busted
-        if (convert == null)
-            convert = computeReturnConversion(type, rawEntryType, true);
-        // retype erased reference arguments (the cast makes it safe to do this)
-        MethodType tepType = type.insertParameterTypes(0, adapter.getClass());
-        MethodHandle typedEntryPoint =
-            AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, entryPoint);
-        return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget);
-    }
-
-    /** Build an adapter of the given type, which invokes genericTarget
-     *  on the incoming arguments, after boxing as necessary.
-     *  The return value is unboxed if necessary.
-     * @param type  the required type of the
-     * @param genericTarget the target, which must accept and return only Object values
-     * @return an adapter method handle
-     */
-    public static MethodHandle make(MethodType type, MethodHandle genericTarget) {
-        MethodType gtype = genericTarget.type();
-        if (type.generic() != gtype)
-            throw newIllegalArgumentException("type must be generic");
-        if (type == gtype)  return genericTarget;
-        return ToGeneric.of(type).makeInstance(type, genericTarget);
-    }
-
-    /** Return the adapter information for this type's erasure. */
-    static ToGeneric of(MethodType type) {
-        MethodTypeImpl form = MethodTypeImpl.of(type);
-        ToGeneric toGen = form.toGeneric;
-        if (toGen == null)
-            form.toGeneric = toGen = new ToGeneric(form.erasedType());
-        return toGen;
-    }
-
-    public String toString() {
-        return "ToGeneric"+entryType
-                +(primsAtEndOrder!=null?"[reorder]":"");
-    }
-
-    /* Create an adapter for the given incoming call type. */
-    static Adapter findAdapter(MethodType entryPointType) {
-        MethodTypeImpl form = MethodTypeImpl.of(entryPointType);
-        Class<?> rtype = entryPointType.returnType();
-        int argc = form.parameterCount();
-        int lac = form.longPrimitiveParameterCount();
-        int iac = form.primitiveParameterCount() - lac;
-        String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
-        String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
-        String iname0 = "invoke_"+rawReturn;
-        String iname1 = "invoke";
-        String[] inames = { iname0, iname1 };
-        String cname0 = rawReturn + argc;
-        String cname1 = "A"       + argc;
-        String[] cnames = { cname1, cname1+intsAndLongs, cname0, cname0+intsAndLongs };
-        // e.g., D5I2, D5, L5I2, L5
-        for (String cname : cnames) {
-            Class<? extends Adapter> acls = Adapter.findSubClass(cname);
-            if (acls == null)  continue;
-            // see if it has the required invoke method
-            for (String iname : inames) {
-                MethodHandle entryPoint = null;
-                try {
-                    entryPoint = MethodHandleImpl.IMPL_LOOKUP.
-                                    findSpecial(acls, iname, entryPointType, acls);
-                } catch (ReflectiveOperationException ex) {
-                }
-                if (entryPoint == null)  continue;
-                Constructor<? extends Adapter> ctor = null;
-                try {
-                    // Prototype builder:
-                    ctor = acls.getDeclaredConstructor(MethodHandle.class);
-                } catch (NoSuchMethodException ex) {
-                } catch (SecurityException ex) {
-                }
-                if (ctor == null)  continue;
-                try {
-                    return ctor.newInstance(entryPoint);
-                } 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 entryPointType) {
-        throw new UnsupportedOperationException("NYI");
-    }
-
-    /**
-     * The invoke method takes some particular but unconstrained spread
-     * of raw argument types, and returns a raw return type (in L/I/J/F/D).
-     * Internally, it converts the incoming arguments uniformly into objects.
-     * This series of objects is then passed to the {@code target} method,
-     * which returns a result object.  This result is finally converted,
-     * via another method handle {@code convert}, which is responsible for
-     * converting the object result into the raw return value.
-     */
-    static abstract class Adapter extends BoundMethodHandle {
-        /*
-         * class X<<R,A...>> extends Adapter {
-         *   Object...=>Object target;
-         *   Object=>R convert;
-         *   R invoke(A... a...) = convert(invoker(target, a...)))
-         * }
-         */
-        protected final MethodHandle invoker;  // (MH, Object...) -> Object
-        protected final MethodHandle target;   // Object... -> Object
-        protected final MethodHandle convert;  // Object -> R
-
-        @Override
-        public String toString() {
-            return target == null ? "prototype:"+convert : MethodHandleImpl.addTypeString(target, this);
-        }
-
-        protected boolean isPrototype() { return target == null; }
-        /* Prototype constructor. */
-        protected Adapter(MethodHandle entryPoint) {
-            super(Access.TOKEN, entryPoint);
-            this.invoker = null;
-            this.convert = entryPoint;
-            this.target = null;
-            assert(isPrototype());
-        }
-        protected MethodHandle prototypeEntryPoint() {
-            if (!isPrototype())  throw new InternalError();
-            return convert;
-        }
-
-        protected Adapter(MethodHandle entryPoint, MethodHandle invoker, MethodHandle convert, MethodHandle target) {
-            super(Access.TOKEN, entryPoint);
-            this.invoker = invoker;
-            this.convert = convert;
-            this.target = target;
-        }
-
-        /** Make a copy of self, with new fields. */
-        protected abstract Adapter makeInstance(MethodHandle entryPoint,
-                MethodHandle invoker, MethodHandle convert, MethodHandle target);
-        // { return new ThisType(entryPoint, convert, target); }
-
-        // Code to run when the arguments (<= 4) have all been boxed.
-        protected Object target()               throws Throwable { return invoker.invokeExact(target); }
-        protected Object target(Object a0)      throws Throwable { return invoker.invokeExact(target, a0); }
-        protected Object target(Object a0, Object a1)
-                                                throws Throwable { return invoker.invokeExact(target, a0, a1); }
-        protected Object target(Object a0, Object a1, Object a2)
-                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2); }
-        protected Object target(Object a0, Object a1, Object a2, Object a3)
-                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); }
-        /*
-        protected Object target_0(Object... av) throws Throwable { return invoker.invokeExact(target, av); }
-        protected Object target_1(Object a0, Object... av)
-                                                throws Throwable { return invoker.invokeExact(target, a0, (Object)av); }
-        protected Object target_2(Object a0, Object a1, Object... av)
-                                                throws Throwable { return invoker.invokeExact(target, a0, a1, (Object)av); }
-        protected Object target_3(Object a0, Object a1, Object a2, Object... av)
-                                                throws Throwable { return invoker.invokeExact(target, a0, a1, a2, (Object)av); }
-        protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av)
-                                                throws Throwable { return invoker.invokeExact(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) throws Throwable { return (Object)convert.invokeExact(res); }
-        protected int    return_I(Object res) throws Throwable { return (int)   convert.invokeExact(res); }
-        protected long   return_J(Object res) throws Throwable { return (long)  convert.invokeExact(res); }
-        protected float  return_F(Object res) throws Throwable { return (float) convert.invokeExact(res); }
-        protected double return_D(Object res) throws Throwable { return (double)convert.invokeExact(res); }
-
-        static private final String CLASS_PREFIX; // "sun.dyn.ToGeneric$"
-        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 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)   throws Throwable { return invoker.invokeExact(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)); }
-    }
-    // */
-
-/*
-: SHELL; n=ToGeneric; 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[] TYPES = { "Object", "int   ", "long  ", "float ", "double" };
-    static String[] TCHARS = { "L",     "I",      "J",      "F",      "D",     "A" };
-    static String[][] TEMPLATES = { {
-        "@for@ arity=0..3   rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
-        "@for@ arity=4..5   rcat<=2 nrefs<=99 nints<=99 nlongs<=99",
-        "@for@ arity=6..10  rcat<=2 nrefs<=99 nints=0   nlongs<=99",
-        "    //@each-cat@",
-        "    static class @cat@ extends Adapter {",
-        "        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@)   throws Throwable { return invoker.invokeExact(target, @av@); }",
-        "        //@each-Tv@",
-        "        protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
-        "        //@end-Tv@",
-        "        //@each-Tv@",
-        "        //@each-R@",
-        "        protected @R@ invoke_@Rc@(@Tvav@) throws Throwable { return return_@Rc@(target@cat@(@av@)); }",
-        "        //@end-R@",
-        "        //@end-Tv@",
-        "    }",
-    } };
-    enum VAR {
-        cat, R, Rc, Tv, av, Tvav, Ovav;
-        public final String pattern = "@"+toString().replace('_','.')+"@";
-        public String binding;
-        static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
-            int nargs = nrefs + nints + nlongs;
-            if (topLevel)
-                VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
-            VAR.R.binding = TYPES[rcat];
-            VAR.Rc.binding = TCHARS[rcat];
-            String[] Tv = new String[nargs];
-            String[] av = new String[nargs];
-            String[] Tvav = new String[nargs];
-            String[] Ovav = new String[nargs];
-            for (int i = 0; i < nargs; i++) {
-                int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
-                Tv[i] = TYPES[tcat];
-                av[i] = arg(i);
-                Tvav[i] = param(Tv[i], av[i]);
-                Ovav[i] = param("Object", av[i]);
-            }
-            VAR.Tv.binding = comma(Tv);
-            VAR.av.binding = comma(av);
-            VAR.Tvav.binding = comma(Tvav);
-            VAR.Ovav.binding = comma(Ovav);
-        }
-        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 sep, String[] v) {
-            if (v.length == 0)  return "";
-            String res = sep+v[0];
-            for (int i = 1; i < v.length; i++)  res += ", "+v[i];
-            return res;
-        }
-        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, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
-    static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
-    static HashSet<String> done = new HashSet<String>();
-    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++]);
-        MAX_RCAT  = Integer.valueOf(params[pcur++]);
-        MAX_REFS  = Integer.valueOf(params[pcur++]);
-        MAX_INTS  = Integer.valueOf(params[pcur++]);
-        MAX_LONGS = Integer.valueOf(params[pcur++]);
-        if (pcur != params.length)  throw new RuntimeException("bad extra param: "+forLine);
-        if (MAX_RCAT >= TYPES.length)  MAX_RCAT = TYPES.length - 1;
-        ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
-        ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
-        for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
-            for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
-                expandTemplate(template, true, rcat, nargs, 0, 0);
-                if (ALL_ARG_TYPES)  break;
-                expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
-                if (ALL_RETURN_TYPES)  break;
-            }
-        }
-    }
-    static String catstr(int rcat, int nrefs, int nints, int nlongs) {
-        int nargs = nrefs + nints + nlongs;
-        String cat = TCHARS[rcat] + nargs;
-        if (!ALL_ARG_TYPES)  cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
-        return cat;
-    }
-    static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
-        for (int isLong = 0; isLong <= 1; isLong++) {
-            for (int nprims = 1; nprims <= nargs; nprims++) {
-                int nrefs = nargs - nprims;
-                int nints = ((1-isLong) * nprims);
-                int nlongs = (isLong * nprims);
-                expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
-            }
-        }
-    }
-    static void expandTemplate(String[] template, boolean topLevel,
-                               int rcat, int nrefs, int nints, int nlongs) {
-        int nargs = nrefs + nints + nlongs;
-        if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS)  return;
-        VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
-        if (topLevel && !done.add(VAR.cat.binding)) {
-            System.out.println("    //repeat "+VAR.cat.binding);
-            return;
-        }
-        for (int i = 0; i < template.length; i++) {
-            String line = template[i];
-            if (line.endsWith("@each-cat@")) {
-                // ignore
-            } else if (line.endsWith("@each-R@")) {
-                int blockEnd = indexAfter(template, i, "@end-R@");
-                String[] block = stringsIn(template, i+1, blockEnd-1);
-                for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
-                    expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
-                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
-                i = blockEnd-1; continue;
-            } else if (line.endsWith("@each-Tv@")) {
-                int blockEnd = indexAfter(template, i, "@end-Tv@");
-                String[] block = stringsIn(template, i+1, blockEnd-1);
-                expandTemplate(block, false, rcat, nrefs, nints, nlongs);
-                expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
-                VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
-                i = blockEnd-1; continue;
-            } else {
-                System.out.println(VAR.transform(line));
-            }
-        }
-    }
-}
-//}}} */
-//params=[0, 3, 4, 99, 99, 99]
-    static class A0 extends Adapter {
-        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()   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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)   throws Throwable { return invoker.invokeExact(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/WrapperInstance.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.MethodHandle;
-
-/**
- * Private API used inside of java.dyn.MethodHandles.
- * Interface implemented by every object which is produced by
- * {@link java.dyn.MethodHandles#asInstance MethodHandles.asInstance}.
- * The methods of this interface allow a caller to recover the parameters
- * to {@code asInstance}.
- * This allows applications to repeatedly convert between method handles
- * and SAM objects, without the risk of creating unbounded delegation chains.
- */
-public interface WrapperInstance {
-    /** Produce or recover a target method handle which is behaviorally
-     *  equivalent to the SAM method of this object.
-     */
-    public MethodHandle getWrapperInstanceTarget();
-    /** Recover the SAM type for which this object was created.
-     */
-    public Class<?> getWrapperInstanceType();
-}
-
--- a/jdk/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import sun.misc.IOUtils;
-
-/**
- * Anonymous class loader.  Will load any valid classfile, producing
- * a {@link Class} metaobject, without installing that class in the
- * system dictionary.  Therefore, {@link Class#forName(String)} will never
- * produce a reference to an anonymous class.
- * <p>
- * The access permissions of the anonymous class are borrowed from
- * a <em>host class</em>.  The new class behaves as if it were an
- * inner class of the host class.  It can access the host's private
- * members, if the creator of the class loader has permission to
- * do so (or to create accessible reflective objects).
- * <p>
- * When the anonymous class is loaded, elements of its constant pool
- * can be patched to new values.  This provides a hook to pre-resolve
- * named classes in the constant pool to other classes, including
- * anonymous ones.  Also, string constants can be pre-resolved to
- * any reference.  (The verifier treats non-string, non-class reference
- * constants as plain objects.)
- *  <p>
- * Why include the patching function?  It makes some use cases much easier.
- * Second, the constant pool needed some internal patching anyway,
- * to anonymize the loaded class itself.  Finally, if you are going
- * to use this seriously, you'll want to build anonymous classes
- * on top of pre-existing anonymous classes, and that requires patching.
- *
- * <p>%%% TO-DO:
- * <ul>
- * <li>needs better documentation</li>
- * <li>needs more security work (for safe delegation)</li>
- * <li>needs a clearer story about error processing</li>
- * <li>patch member references also (use ';' as delimiter char)</li>
- * <li>patch method references to (conforming) method handles</li>
- * </ul>
- *
- * @author jrose
- * @author Remi Forax
- * @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
- *      http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
- */
-
-public class AnonymousClassLoader {
-    final Class<?> hostClass;
-
-    // Note: Do not refactor the calls to checkHostClass unless you
-    //       also adjust this constant:
-    private static int CHC_CALLERS = 3;
-
-    public AnonymousClassLoader() {
-        this.hostClass = checkHostClass(null);
-    }
-    public AnonymousClassLoader(Class<?> hostClass) {
-        this.hostClass = checkHostClass(hostClass);
-    }
-
-    private static Class<?> getTopLevelClass(Class<?> clazz) {
-      for(Class<?> outer = clazz.getDeclaringClass(); outer != null;
-          outer = outer.getDeclaringClass()) {
-        clazz = outer;
-      }
-      return clazz;
-    }
-
-    private static Class<?> checkHostClass(Class<?> hostClass) {
-        // called only from the constructor
-        // does a context-sensitive check on caller class
-        // CC[0..3] = {Reflection, this.checkHostClass, this.<init>, caller}
-        Class<?> caller = sun.reflect.Reflection.getCallerClass(CHC_CALLERS);
-
-        if (caller == null) {
-            // called from the JVM directly
-            if (hostClass == null)
-                return AnonymousClassLoader.class; // anything central will do
-            return hostClass;
-        }
-
-        if (hostClass == null)
-            hostClass = caller; // default value is caller itself
-
-        // anonymous class will access hostClass on behalf of caller
-        Class<?> callee = hostClass;
-
-        if (caller == callee)
-            // caller can always nominate itself to grant caller's own access rights
-            return hostClass;
-
-        // normalize caller and callee to their top-level classes:
-        caller = getTopLevelClass(caller);
-        callee = getTopLevelClass(callee);
-        if (caller == callee)
-            return caller;
-
-        ClassLoader callerCL = caller.getClassLoader();
-        if (callerCL == null) {
-            // caller is trusted code, so accept the proposed hostClass
-            return hostClass;
-        }
-
-        // %%% should do something with doPrivileged, because trusted
-        // code should have a way to execute on behalf of
-        // partially-trusted clients
-
-        // Does the caller have the right to access the private
-        // members of the callee?  If not, raise an error.
-        final int ACC_PRIVATE = 2;
-        try {
-            sun.reflect.Reflection.ensureMemberAccess(caller, callee, null, ACC_PRIVATE);
-        } catch (IllegalAccessException ee) {
-            throw new IllegalArgumentException(ee);
-        }
-
-        return hostClass;
-    }
-
-    public Class<?> loadClass(byte[] classFile) {
-        if (defineAnonymousClass == null) {
-            // no JVM support; try to fake an approximation
-            try {
-                return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
-            } catch (InvalidConstantPoolFormatException ee) {
-                throw new IllegalArgumentException(ee);
-            }
-        }
-        return loadClass(classFile, null);
-    }
-
-    public Class<?> loadClass(ConstantPoolPatch classPatch) {
-        if (defineAnonymousClass == null) {
-            // no JVM support; try to fake an approximation
-            return fakeLoadClass(classPatch);
-        }
-        Object[] patches = classPatch.patchArray;
-        // Convert class names (this late in the game)
-        // to use slash '/' instead of dot '.'.
-        // Java likes dots, but the JVM likes slashes.
-        for (int i = 0; i < patches.length; i++) {
-            Object value = patches[i];
-            if (value != null) {
-                byte tag = classPatch.getTag(i);
-                switch (tag) {
-                case ConstantPoolVisitor.CONSTANT_Class:
-                    if (value instanceof String) {
-                        if (patches == classPatch.patchArray)
-                            patches = patches.clone();
-                        patches[i] = ((String)value).replace('.', '/');
-                    }
-                    break;
-                case ConstantPoolVisitor.CONSTANT_Fieldref:
-                case ConstantPoolVisitor.CONSTANT_Methodref:
-                case ConstantPoolVisitor.CONSTANT_InterfaceMethodref:
-                case ConstantPoolVisitor.CONSTANT_NameAndType:
-                    // When/if the JVM supports these patches,
-                    // we'll probably need to reformat them also.
-                    // Meanwhile, let the class loader create the error.
-                    break;
-                }
-            }
-        }
-        return loadClass(classPatch.outer.classFile, classPatch.patchArray);
-    }
-
-    private Class<?> loadClass(byte[] classFile, Object[] patchArray) {
-        try {
-            return (Class<?>)
-                defineAnonymousClass.invoke(unsafe,
-                                            hostClass, classFile, patchArray);
-        } catch (Exception ex) {
-            throwReflectedException(ex);
-            throw new RuntimeException("error loading into "+hostClass, ex);
-        }
-    }
-
-    private static void throwReflectedException(Exception ex) {
-        if (ex instanceof InvocationTargetException) {
-            Throwable tex = ((InvocationTargetException)ex).getTargetException();
-            if (tex instanceof Error)
-                throw (Error) tex;
-            ex = (Exception) tex;
-        }
-        if (ex instanceof RuntimeException) {
-            throw (RuntimeException) ex;
-        }
-    }
-
-    private Class<?> fakeLoadClass(ConstantPoolPatch classPatch) {
-        // Implementation:
-        // 1. Make up a new name nobody has used yet.
-        // 2. Inspect the tail-header of the class to find the this_class index.
-        // 3. Patch the CONSTANT_Class for this_class to the new name.
-        // 4. Add other CP entries required by (e.g.) string patches.
-        // 5. Flatten Class constants down to their names, making sure that
-        //    the host class loader can pick them up again accurately.
-        // 6. Generate the edited class file bytes.
-        //
-        // Potential limitations:
-        // * The class won't be truly anonymous, and may interfere with others.
-        // * Flattened class constants might not work, because of loader issues.
-        // * Pseudo-string constants will not flatten down to real strings.
-        // * Method handles will (of course) fail to flatten to linkage strings.
-        if (true)  throw new UnsupportedOperationException("NYI");
-        Object[] cpArray;
-        try {
-            cpArray = classPatch.getOriginalCP();
-        } catch (InvalidConstantPoolFormatException ex) {
-            throw new RuntimeException(ex);
-        }
-        int thisClassIndex = classPatch.getParser().getThisClassIndex();
-        String thisClassName = (String) cpArray[thisClassIndex];
-        synchronized (AnonymousClassLoader.class) {
-            thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
-        }
-        classPatch.putUTF8(thisClassIndex, thisClassName);
-        byte[] classFile = null;
-        return unsafe.defineClass(null, classFile, 0, classFile.length,
-                                  hostClass.getClassLoader(),
-                                  hostClass.getProtectionDomain());
-    }
-    private static int fakeNameCounter = 99999;
-
-    // ignore two warnings on this line:
-    static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
-    // preceding line requires that this class be on the boot class path
-
-    static private final Method defineAnonymousClass;
-    static {
-        Method dac = null;
-        Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass();
-        try {
-            dac = unsafeClass.getMethod("defineAnonymousClass",
-                                        Class.class,
-                                        byte[].class,
-                                        Object[].class);
-        } catch (Exception ee) {
-            dac = null;
-        }
-        defineAnonymousClass = dac;
-    }
-
-    private static void noJVMSupport() {
-        throw new UnsupportedOperationException("no JVM support for anonymous classes");
-    }
-
-
-    private static native Class<?> loadClassInternal(Class<?> hostClass,
-                                                     byte[] classFile,
-                                                     Object[] patchArray);
-
-    public static byte[] readClassFile(Class<?> templateClass) throws IOException {
-        String templateName = templateClass.getName();
-        int lastDot = templateName.lastIndexOf('.');
-        java.net.URL url = templateClass.getResource(templateName.substring(lastDot+1)+".class");
-        java.net.URLConnection connection = url.openConnection();
-        int contentLength = connection.getContentLength();
-        if (contentLength < 0)
-            throw new IOException("invalid content length "+contentLength);
-
-        return IOUtils.readFully(connection.getInputStream(), contentLength, true);
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolParser.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,368 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-
-import static sun.dyn.anon.ConstantPoolVisitor.*;
-
-/** A constant pool parser.
- */
-public class ConstantPoolParser {
-    final byte[] classFile;
-    final byte[] tags;
-    final char[] firstHeader;  // maghi, maglo, minor, major, cplen
-
-    // these are filled in on first parse:
-    int endOffset;
-    char[] secondHeader;       // flags, this_class, super_class, intlen
-
-    // used to decode UTF8 array
-    private char[] charArray = new char[80];
-
-    /** Creates a constant pool parser.
-     * @param classFile an array of bytes containing a class.
-     * @throws InvalidConstantPoolFormatException if the header of the class has errors.
-     */
-    public ConstantPoolParser(byte[] classFile) throws InvalidConstantPoolFormatException {
-        this.classFile = classFile;
-        this.firstHeader = parseHeader(classFile);
-        this.tags = new byte[firstHeader[4]];
-    }
-
-    /** Create a constant pool parser by loading the bytecodes of the
-     *  class taken as argument.
-     *
-     * @param templateClass the class to parse.
-     *
-     * @throws IOException raised if an I/O occurs when loading
-     *  the bytecode of the template class.
-     * @throws InvalidConstantPoolFormatException if the header of the class has errors.
-     *
-     * @see #ConstantPoolParser(byte[])
-     * @see AnonymousClassLoader#readClassFile(Class)
-     */
-    public ConstantPoolParser(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
-        this(AnonymousClassLoader.readClassFile(templateClass));
-    }
-
-    /** Creates an empty patch to patch the class file
-     *  used by the current parser.
-     * @return a new class patch.
-     */
-    public ConstantPoolPatch createPatch() {
-        return new ConstantPoolPatch(this);
-    }
-
-    /** Report the tag of the indicated CP entry.
-     * @param index
-     * @return one of {@link ConstantPoolVisitor#CONSTANT_Utf8}, etc.
-     */
-    public byte getTag(int index) {
-        getEndOffset();  // trigger an exception if we haven't parsed yet
-        return tags[index];
-    }
-
-    /** Report the length of the constant pool. */
-    public int getLength() {
-        return firstHeader[4];
-    }
-
-    /** Report the offset, within the class file, of the start of the constant pool. */
-    public int getStartOffset() {
-        return firstHeader.length * 2;
-    }
-
-    /** Report the offset, within the class file, of the end of the constant pool. */
-    public int getEndOffset() {
-        if (endOffset == 0)
-            throw new IllegalStateException("class file has not yet been parsed");
-        return endOffset;
-    }
-
-    /** Report the CP index of this class's own name. */
-    public int getThisClassIndex() {
-        getEndOffset();   // provoke exception if not yet parsed
-        return secondHeader[1];
-    }
-
-    /** Report the total size of the class file. */
-    public int getTailLength() {
-        return classFile.length - getEndOffset();
-    }
-
-    /** Write the head (header plus constant pool)
-     *  of the class file to the indicated stream.
-     */
-    public void writeHead(OutputStream out) throws IOException {
-        out.write(classFile, 0, getEndOffset());
-    }
-
-    /** Write the head (header plus constant pool)
-     *  of the class file to the indicated stream,
-     *  incorporating the non-null entries of the given array
-     *  as patches.
-     */
-    void writePatchedHead(OutputStream out, Object[] patchArray) {
-        // this will be useful to partially emulate the class loader on old JVMs
-        throw new UnsupportedOperationException("Not yet implemented");
-    }
-
-    /** Write the tail (everything after the constant pool)
-     *  of the class file to the indicated stream.
-     */
-    public void writeTail(OutputStream out) throws IOException {
-        out.write(classFile, getEndOffset(), getTailLength());
-    }
-
-    private static char[] parseHeader(byte[] classFile) throws InvalidConstantPoolFormatException {
-        char[] result = new char[5];
-        ByteBuffer buffer = ByteBuffer.wrap(classFile);
-        for (int i = 0; i < result.length; i++)
-            result[i] = (char) getUnsignedShort(buffer);
-        int magic = result[0] << 16 | result[1] << 0;
-        if (magic != 0xCAFEBABE)
-            throw new InvalidConstantPoolFormatException("invalid magic number "+magic);
-        // skip major, minor version
-        int len = result[4];
-        if (len < 1)
-            throw new InvalidConstantPoolFormatException("constant pool length < 1");
-        return result;
-    }
-
-    /** Parse the constant pool of the class
-     *  calling a method visit* each time a constant pool entry is parsed.
-     *
-     *  The order of the calls to visit* is not guaranteed to be the same
-     *  than the order of the constant pool entry in the bytecode array.
-     *
-     * @param visitor
-     * @throws InvalidConstantPoolFormatException
-     */
-    public void parse(ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
-        ByteBuffer buffer = ByteBuffer.wrap(classFile);
-        buffer.position(getStartOffset()); //skip header
-
-        Object[] values = new Object[getLength()];
-        try {
-            parseConstantPool(buffer, values, visitor);
-        } catch(BufferUnderflowException e) {
-            throw new InvalidConstantPoolFormatException(e);
-        }
-        if (endOffset == 0) {
-            endOffset = buffer.position();
-            secondHeader = new char[4];
-            for (int i = 0; i < secondHeader.length; i++) {
-                secondHeader[i] = (char) getUnsignedShort(buffer);
-            }
-        }
-        resolveConstantPool(values, visitor);
-    }
-
-    private char[] getCharArray(int utfLength) {
-        if (utfLength <= charArray.length)
-            return charArray;
-        return charArray = new char[utfLength];
-    }
-
-    private void parseConstantPool(ByteBuffer buffer, Object[] values, ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
-        for (int i = 1; i < tags.length; ) {
-            byte tag = (byte) getUnsignedByte(buffer);
-            assert(tags[i] == 0 || tags[i] == tag);
-            tags[i] = tag;
-            switch (tag) {
-                case CONSTANT_Utf8:
-                    int utfLen = getUnsignedShort(buffer);
-                    String value = getUTF8(buffer, utfLen, getCharArray(utfLen));
-                    visitor.visitUTF8(i, CONSTANT_Utf8, value);
-                    tags[i] = tag;
-                    values[i++] = value;
-                    break;
-                case CONSTANT_Integer:
-                    visitor.visitConstantValue(i, tag, buffer.getInt());
-                    i++;
-                    break;
-                case CONSTANT_Float:
-                    visitor.visitConstantValue(i, tag, buffer.getFloat());
-                    i++;
-                    break;
-                case CONSTANT_Long:
-                    visitor.visitConstantValue(i, tag, buffer.getLong());
-                    i+=2;
-                    break;
-                case CONSTANT_Double:
-                    visitor.visitConstantValue(i, tag, buffer.getDouble());
-                    i+=2;
-                    break;
-
-                case CONSTANT_Class:    // fall through:
-                case CONSTANT_String:
-                    tags[i] = tag;
-                    values[i++] = new int[] { getUnsignedShort(buffer) };
-                    break;
-
-                case CONSTANT_Fieldref:           // fall through:
-                case CONSTANT_Methodref:          // fall through:
-                case CONSTANT_InterfaceMethodref: // fall through:
-                case CONSTANT_NameAndType:
-                    tags[i] = tag;
-                    values[i++] = new int[] { getUnsignedShort(buffer), getUnsignedShort(buffer) };
-                    break;
-                default:
-                    throw new AssertionError("invalid constant "+tag);
-            }
-        }
-    }
-
-    private void resolveConstantPool(Object[] values, ConstantPoolVisitor visitor) {
-        // clean out the int[] values, which are temporary
-        for (int beg = 1, end = values.length-1, beg2, end2;
-             beg <= end;
-             beg = beg2, end = end2) {
-             beg2 = end; end2 = beg-1;
-             //System.out.println("CP resolve pass: "+beg+".."+end);
-             for (int i = beg; i <= end; i++) {
-                  Object value = values[i];
-                  if (!(value instanceof int[]))
-                      continue;
-                  int[] array = (int[]) value;
-                  byte tag = tags[i];
-                  switch (tag) {
-                      case CONSTANT_String:
-                          String stringBody = (String) values[array[0]];
-                          visitor.visitConstantString(i, tag, stringBody, array[0]);
-                          values[i] = null;
-                          break;
-                      case CONSTANT_Class: {
-                          String className = (String) values[array[0]];
-                          // use the external form favored by Class.forName:
-                          className = className.replace('/', '.');
-                          visitor.visitConstantString(i, tag, className, array[0]);
-                          values[i] = className;
-                          break;
-                      }
-                      case CONSTANT_NameAndType: {
-                          String memberName = (String) values[array[0]];
-                          String signature  = (String) values[array[1]];
-                          visitor.visitDescriptor(i, tag, memberName, signature,
-                                                  array[0], array[1]);
-                          values[i] = new String[] {memberName, signature};
-                          break;
-                      }
-                      case CONSTANT_Fieldref:           // fall through:
-                      case CONSTANT_Methodref:          // fall through:
-                      case CONSTANT_InterfaceMethodref: {
-                              Object className   = values[array[0]];
-                              Object nameAndType = values[array[1]];
-                              if (!(className instanceof String) ||
-                                  !(nameAndType instanceof String[])) {
-                                   // one more pass is needed
-                                   if (beg2 > i)  beg2 = i;
-                                   if (end2 < i)  end2 = i;
-                                   continue;
-                              }
-                              String[] nameAndTypeArray = (String[]) nameAndType;
-                              visitor.visitMemberRef(i, tag,
-                                  (String)className,
-                                  nameAndTypeArray[0],
-                                  nameAndTypeArray[1],
-                                  array[0], array[1]);
-                              values[i] = null;
-                          }
-                          break;
-                      default:
-                          continue;
-                }
-            }
-        }
-    }
-
-    private static int getUnsignedByte(ByteBuffer buffer) {
-        return buffer.get() & 0xFF;
-    }
-
-    private static int getUnsignedShort(ByteBuffer buffer) {
-        int b1 = getUnsignedByte(buffer);
-        int b2 = getUnsignedByte(buffer);
-        return (b1 << 8) + (b2 << 0);
-    }
-
-    private static String getUTF8(ByteBuffer buffer, int utfLen, char[] charArray) throws InvalidConstantPoolFormatException {
-      int utfLimit = buffer.position() + utfLen;
-      int index = 0;
-      while (buffer.position() < utfLimit) {
-          int c = buffer.get() & 0xff;
-          if (c > 127) {
-              buffer.position(buffer.position() - 1);
-              return getUTF8Extended(buffer, utfLimit, charArray, index);
-          }
-          charArray[index++] = (char)c;
-      }
-      return new String(charArray, 0, index);
-    }
-
-    private static String getUTF8Extended(ByteBuffer buffer, int utfLimit, char[] charArray, int index) throws InvalidConstantPoolFormatException {
-        int c, c2, c3;
-        while (buffer.position() < utfLimit) {
-            c = buffer.get() & 0xff;
-            switch (c >> 4) {
-                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
-                    /* 0xxxxxxx*/
-                    charArray[index++] = (char)c;
-                    break;
-                case 12: case 13:
-                    /* 110x xxxx   10xx xxxx*/
-                    c2 = buffer.get();
-                    if ((c2 & 0xC0) != 0x80)
-                        throw new InvalidConstantPoolFormatException(
-                            "malformed input around byte " + buffer.position());
-                     charArray[index++] = (char)(((c  & 0x1F) << 6) |
-                                                  (c2 & 0x3F));
-                    break;
-                case 14:
-                    /* 1110 xxxx  10xx xxxx  10xx xxxx */
-                    c2 = buffer.get();
-                    c3 = buffer.get();
-                    if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80))
-                       throw new InvalidConstantPoolFormatException(
-                          "malformed input around byte " + (buffer.position()));
-                    charArray[index++] = (char)(((c  & 0x0F) << 12) |
-                                                ((c2 & 0x3F) << 6)  |
-                                                ((c3 & 0x3F) << 0));
-                    break;
-                default:
-                    /* 10xx xxxx,  1111 xxxx */
-                    throw new InvalidConstantPoolFormatException(
-                        "malformed input around byte " + buffer.position());
-            }
-        }
-        // The number of chars produced may be less than utflen
-        return new String(charArray, 0, index);
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolPatch.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,503 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Map;
-
-import static sun.dyn.anon.ConstantPoolVisitor.*;
-
-/** A class and its patched constant pool.
- *
- *  This class allow to modify (patch) a constant pool
- *  by changing the value of its entry.
- *  Entry are referenced using index that can be get
- *  by parsing the constant pool using
- *  {@link ConstantPoolParser#parse(ConstantPoolVisitor)}.
- *
- * @see ConstantPoolVisitor
- * @see ConstantPoolParser#createPatch()
- */
-public class ConstantPoolPatch {
-    final ConstantPoolParser outer;
-    final Object[] patchArray;
-
-    ConstantPoolPatch(ConstantPoolParser outer) {
-        this.outer      = outer;
-        this.patchArray = new Object[outer.getLength()];
-    }
-
-    /** Create a {@link ConstantPoolParser} and
-     *  a {@link ConstantPoolPatch} in one step.
-     *  Equivalent to {@code new ConstantPoolParser(classFile).createPatch()}.
-     *
-     * @param classFile an array of bytes containing a class.
-     * @see #ConstantPoolParser(Class)
-     */
-    public ConstantPoolPatch(byte[] classFile) throws InvalidConstantPoolFormatException {
-        this(new ConstantPoolParser(classFile));
-    }
-
-    /** Create a {@link ConstantPoolParser} and
-     *  a {@link ConstantPoolPatch} in one step.
-     *  Equivalent to {@code new ConstantPoolParser(templateClass).createPatch()}.
-     *
-     * @param templateClass the class to parse.
-     * @see #ConstantPoolParser(Class)
-     */
-    public ConstantPoolPatch(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
-        this(new ConstantPoolParser(templateClass));
-    }
-
-
-    /** Creates a patch from an existing patch.
-     *  All changes are copied from that patch.
-     * @param patch a patch
-     *
-     * @see ConstantPoolParser#createPatch()
-     */
-    public ConstantPoolPatch(ConstantPoolPatch patch) {
-        outer      = patch.outer;
-        patchArray = patch.patchArray.clone();
-    }
-
-    /** Which parser built this patch? */
-    public ConstantPoolParser getParser() {
-        return outer;
-    }
-
-    /** Report the tag at the given index in the constant pool. */
-    public byte getTag(int index) {
-        return outer.getTag(index);
-    }
-
-    /** Report the current patch at the given index of the constant pool.
-     *  Null means no patch will be made.
-     *  To observe the unpatched entry at the given index, use
-     *  {@link #getParser()}{@code .}@link ConstantPoolParser#parse(ConstantPoolVisitor)}
-     */
-    public Object getPatch(int index) {
-        Object value = patchArray[index];
-        if (value == null)  return null;
-        switch (getTag(index)) {
-        case CONSTANT_Fieldref:
-        case CONSTANT_Methodref:
-        case CONSTANT_InterfaceMethodref:
-            if (value instanceof String)
-                value = stripSemis(2, (String) value);
-            break;
-        case CONSTANT_NameAndType:
-            if (value instanceof String)
-                value = stripSemis(1, (String) value);
-            break;
-        }
-        return value;
-    }
-
-    /** Clear all patches. */
-    public void clear() {
-        Arrays.fill(patchArray, null);
-    }
-
-    /** Clear one patch. */
-    public void clear(int index) {
-        patchArray[index] = null;
-    }
-
-    /** Produce the patches as an array. */
-    public Object[] getPatches() {
-        return patchArray.clone();
-    }
-
-    /** Produce the original constant pool as an array. */
-    public Object[] getOriginalCP() throws InvalidConstantPoolFormatException {
-        return getOriginalCP(0, patchArray.length, -1);
-    }
-
-    /** Walk the constant pool, applying patches using the given map.
-     *
-     * @param utf8Map Utf8 strings to modify, if encountered
-     * @param classMap Classes (or their names) to modify, if encountered
-     * @param valueMap Constant values to modify, if encountered
-     * @param deleteUsedEntries if true, delete map entries that are used
-     */
-    public void putPatches(final Map<String,String> utf8Map,
-                           final Map<String,Object> classMap,
-                           final Map<Object,Object> valueMap,
-                           boolean deleteUsedEntries) throws InvalidConstantPoolFormatException {
-        final HashSet<String> usedUtf8Keys;
-        final HashSet<String> usedClassKeys;
-        final HashSet<Object> usedValueKeys;
-        if (deleteUsedEntries) {
-            usedUtf8Keys  = (utf8Map  == null) ? null : new HashSet<String>();
-            usedClassKeys = (classMap == null) ? null : new HashSet<String>();
-            usedValueKeys = (valueMap == null) ? null : new HashSet<Object>();
-        } else {
-            usedUtf8Keys = null;
-            usedClassKeys = null;
-            usedValueKeys = null;
-        }
-
-        outer.parse(new ConstantPoolVisitor() {
-
-            @Override
-            public void visitUTF8(int index, byte tag, String utf8) {
-                putUTF8(index, utf8Map.get(utf8));
-                if (usedUtf8Keys != null)  usedUtf8Keys.add(utf8);
-            }
-
-            @Override
-            public void visitConstantValue(int index, byte tag, Object value) {
-                putConstantValue(index, tag, valueMap.get(value));
-                if (usedValueKeys != null)  usedValueKeys.add(value);
-            }
-
-            @Override
-            public void visitConstantString(int index, byte tag, String name, int nameIndex) {
-                if (tag == CONSTANT_Class) {
-                    putConstantValue(index, tag, classMap.get(name));
-                    if (usedClassKeys != null)  usedClassKeys.add(name);
-                } else {
-                    assert(tag == CONSTANT_String);
-                    visitConstantValue(index, tag, name);
-                }
-            }
-        });
-        if (usedUtf8Keys != null)   utf8Map.keySet().removeAll(usedUtf8Keys);
-        if (usedClassKeys != null)  classMap.keySet().removeAll(usedClassKeys);
-        if (usedValueKeys != null)  valueMap.keySet().removeAll(usedValueKeys);
-    }
-
-    Object[] getOriginalCP(final int startIndex,
-                           final int endIndex,
-                           final int tagMask) throws InvalidConstantPoolFormatException {
-        final Object[] cpArray = new Object[endIndex - startIndex];
-        outer.parse(new ConstantPoolVisitor() {
-
-            void show(int index, byte tag, Object value) {
-                if (index < startIndex || index >= endIndex)  return;
-                if (((1 << tag) & tagMask) == 0)  return;
-                cpArray[index - startIndex] = value;
-            }
-
-            @Override
-            public void visitUTF8(int index, byte tag, String utf8) {
-                show(index, tag, utf8);
-            }
-
-            @Override
-            public void visitConstantValue(int index, byte tag, Object value) {
-                assert(tag != CONSTANT_String);
-                show(index, tag, value);
-            }
-
-            @Override
-            public void visitConstantString(int index, byte tag,
-                                            String value, int j) {
-                show(index, tag, value);
-            }
-
-            @Override
-            public void visitMemberRef(int index, byte tag,
-                    String className, String memberName,
-                    String signature,
-                    int j, int k) {
-                show(index, tag, new String[]{ className, memberName, signature });
-            }
-
-            @Override
-            public void visitDescriptor(int index, byte tag,
-                    String memberName, String signature,
-                    int j, int k) {
-                show(index, tag, new String[]{ memberName, signature });
-            }
-        });
-        return cpArray;
-    }
-
-    /** Write the head (header plus constant pool)
-     *  of the patched class file to the indicated stream.
-     */
-    void writeHead(OutputStream out) throws IOException {
-        outer.writePatchedHead(out, patchArray);
-    }
-
-    /** Write the tail (everything after the constant pool)
-     *  of the patched class file to the indicated stream.
-     */
-    void writeTail(OutputStream out) throws IOException {
-        outer.writeTail(out);
-    }
-
-    private void checkConstantTag(byte tag, Object value) {
-        if (value == null)
-            throw new IllegalArgumentException(
-                    "invalid null constant value");
-        if (classForTag(tag) != value.getClass())
-            throw new IllegalArgumentException(
-                    "invalid constant value"
-                    + (tag == CONSTANT_None ? ""
-                        : " for tag "+tagName(tag))
-                    + " of class "+value.getClass());
-    }
-
-    private void checkTag(int index, byte putTag) {
-        byte tag = outer.tags[index];
-        if (tag != putTag)
-            throw new IllegalArgumentException(
-                "invalid put operation"
-                + " for " + tagName(putTag)
-                + " at index " + index + " found " + tagName(tag));
-    }
-
-    private void checkTagMask(int index, int tagBitMask) {
-        byte tag = outer.tags[index];
-        int tagBit = ((tag & 0x1F) == tag) ? (1 << tag) : 0;
-        if ((tagBit & tagBitMask) == 0)
-            throw new IllegalArgumentException(
-                "invalid put operation"
-                + " at index " + index + " found " + tagName(tag));
-    }
-
-    private static void checkMemberName(String memberName) {
-        if (memberName.indexOf(';') >= 0)
-            throw new IllegalArgumentException("memberName " + memberName + " contains a ';'");
-    }
-
-    /** Set the entry of the constant pool indexed by index to
-     *  a new string.
-     *
-     * @param index an index to a constant pool entry containing a
-     *        {@link ConstantPoolVisitor#CONSTANT_Utf8} value.
-     * @param utf8 a string
-     *
-     * @see ConstantPoolVisitor#visitUTF8(int, byte, String)
-     */
-    public void putUTF8(int index, String utf8) {
-        if (utf8 == null) { clear(index); return; }
-        checkTag(index, CONSTANT_Utf8);
-        patchArray[index] = utf8;
-    }
-
-    /** Set the entry of the constant pool indexed by index to
-     *  a new value, depending on its dynamic type.
-     *
-     * @param index an index to a constant pool entry containing a
-     *        one of the following structures:
-     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
-     *        {@link ConstantPoolVisitor#CONSTANT_Float},
-     *        {@link ConstantPoolVisitor#CONSTANT_Long},
-     *        {@link ConstantPoolVisitor#CONSTANT_Double},
-     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
-     *        {@link ConstantPoolVisitor#CONSTANT_Class}
-     * @param value a boxed int, float, long or double; or a string or class object
-     * @throws IllegalArgumentException if the type of the constant does not
-     *         match the constant pool entry type,
-     *         as reported by {@link #getTag(int)}
-     *
-     * @see #putConstantValue(int, byte, Object)
-     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
-     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
-     */
-    public void putConstantValue(int index, Object value) {
-        if (value == null) { clear(index); return; }
-        byte tag = tagForConstant(value.getClass());
-        checkConstantTag(tag, value);
-        checkTag(index, tag);
-        patchArray[index] = value;
-    }
-
-    /** Set the entry of the constant pool indexed by index to
-     *  a new value.
-     *
-     * @param index an index to a constant pool entry matching the given tag
-     * @param tag one of the following values:
-     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
-     *        {@link ConstantPoolVisitor#CONSTANT_Float},
-     *        {@link ConstantPoolVisitor#CONSTANT_Long},
-     *        {@link ConstantPoolVisitor#CONSTANT_Double},
-     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
-     *        {@link ConstantPoolVisitor#CONSTANT_Class}
-     * @param value a boxed number, string, or class object
-     * @throws IllegalArgumentException if the type of the constant does not
-     *         match the constant pool entry type, or if a class name contains
-     *         '/' or ';'
-     *
-     * @see #putConstantValue(int, Object)
-     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
-     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
-     */
-    public void putConstantValue(int index, byte tag, Object value) {
-        if (value == null) { clear(index); return; }
-        checkTag(index, tag);
-        if (tag == CONSTANT_Class && value instanceof String) {
-            checkClassName((String) value);
-        } else if (tag == CONSTANT_String) {
-            // the JVM accepts any object as a patch for a string
-        } else {
-            // make sure the incoming value is the right type
-            checkConstantTag(tag, value);
-        }
-        checkTag(index, tag);
-        patchArray[index] = value;
-    }
-
-    /** Set the entry of the constant pool indexed by index to
-     *  a new {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
-     *
-     * @param index an index to a constant pool entry containing a
-     *        {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
-     * @param memberName a memberName
-     * @param signature a signature
-     * @throws IllegalArgumentException if memberName contains the character ';'
-     *
-     * @see ConstantPoolVisitor#visitDescriptor(int, byte, String, String, int, int)
-     */
-    public void putDescriptor(int index, String memberName, String signature) {
-        checkTag(index, CONSTANT_NameAndType);
-        checkMemberName(memberName);
-        patchArray[index] = addSemis(memberName, signature);
-    }
-
-    /** Set the entry of the constant pool indexed by index to
-     *  a new {@link ConstantPoolVisitor#CONSTANT_Fieldref},
-     *  {@link ConstantPoolVisitor#CONSTANT_Methodref}, or
-     *  {@link ConstantPoolVisitor#CONSTANT_InterfaceMethodref} value.
-     *
-     * @param index an index to a constant pool entry containing a member reference
-     * @param className a class name
-     * @param memberName a field or method name
-     * @param signature a field or method signature
-     * @throws IllegalArgumentException if memberName contains the character ';'
-     *             or signature is not a correct signature
-     *
-     * @see ConstantPoolVisitor#visitMemberRef(int, byte, String, String, String, int, int)
-     */
-    public void putMemberRef(int index, byte tag,
-                    String className, String memberName, String signature) {
-        checkTagMask(tag, CONSTANT_MemberRef_MASK);
-        checkTag(index, tag);
-        checkClassName(className);
-        checkMemberName(memberName);
-        if (signature.startsWith("(") == (tag == CONSTANT_Fieldref))
-            throw new IllegalArgumentException("bad signature: "+signature);
-        patchArray[index] = addSemis(className, memberName, signature);
-    }
-
-    static private final int CONSTANT_MemberRef_MASK =
-              CONSTANT_Fieldref
-            | CONSTANT_Methodref
-            | CONSTANT_InterfaceMethodref;
-
-    private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
-        = new IdentityHashMap<Class<?>, Byte>();
-    private static final Class[] CONSTANT_VALUE_CLASS = new Class[16];
-    static {
-        Object[][] values = {
-            {Integer.class, CONSTANT_Integer},
-            {Long.class, CONSTANT_Long},
-            {Float.class, CONSTANT_Float},
-            {Double.class, CONSTANT_Double},
-            {String.class, CONSTANT_String},
-            {Class.class, CONSTANT_Class}
-        };
-        for (Object[] value : values) {
-            Class<?> cls = (Class<?>)value[0];
-            Byte     tag = (Byte) value[1];
-            CONSTANT_VALUE_CLASS_TAG.put(cls, tag);
-            CONSTANT_VALUE_CLASS[(byte)tag] = cls;
-        }
-    }
-
-    static Class<?> classForTag(byte tag) {
-        if ((tag & 0xFF) >= CONSTANT_VALUE_CLASS.length)
-            return null;
-        return CONSTANT_VALUE_CLASS[tag];
-    }
-
-    static byte tagForConstant(Class<?> cls) {
-        Byte tag = CONSTANT_VALUE_CLASS_TAG.get(cls);
-        return (tag == null) ? CONSTANT_None : (byte)tag;
-    }
-
-    private static void checkClassName(String className) {
-        if (className.indexOf('/') >= 0 || className.indexOf(';') >= 0)
-            throw new IllegalArgumentException("invalid class name " + className);
-    }
-
-    static String addSemis(String name, String... names) {
-        StringBuilder buf = new StringBuilder(name.length() * 5);
-        buf.append(name);
-        for (String name2 : names) {
-            buf.append(';').append(name2);
-        }
-        String res = buf.toString();
-        assert(stripSemis(names.length, res)[0].equals(name));
-        assert(stripSemis(names.length, res)[1].equals(names[0]));
-        assert(names.length == 1 ||
-               stripSemis(names.length, res)[2].equals(names[1]));
-        return res;
-    }
-
-    static String[] stripSemis(int count, String string) {
-        String[] res = new String[count+1];
-        int pos = 0;
-        for (int i = 0; i < count; i++) {
-            int pos2 = string.indexOf(';', pos);
-            if (pos2 < 0)  pos2 = string.length();  // yuck
-            res[i] = string.substring(pos, pos2);
-            pos = pos2;
-        }
-        res[count] = string.substring(pos);
-        return res;
-    }
-
-    public String toString() {
-        StringBuilder buf = new StringBuilder(this.getClass().getName());
-        buf.append("{");
-        Object[] origCP = null;
-        for (int i = 0; i < patchArray.length; i++) {
-            if (patchArray[i] == null)  continue;
-            if (origCP != null) {
-                buf.append(", ");
-            } else {
-                try {
-                    origCP = getOriginalCP();
-                } catch (InvalidConstantPoolFormatException ee) {
-                    origCP = new Object[0];
-                }
-            }
-            Object orig = (i < origCP.length) ? origCP[i] : "?";
-            buf.append(orig).append("=").append(patchArray[i]);
-        }
-        buf.append("}");
-        return buf.toString();
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolVisitor.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-/**
- * A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
- * when a constant pool entry is parsed.
- * <p>
- * A visit* method is called when a constant pool entry is parsed.
- * The first argument is always the constant pool index.
- * The second argument is always the constant pool tag,
- * even for methods like {@link #visitUTF8(int, byte, String)} which only apply to one tag.
- * String arguments refer to Utf8 or NameAndType entries declared elsewhere,
- * and are always accompanied by the indexes of those entries.
- * <p>
- * The order of the calls to the visit* methods is not necessarily related
- * to the order of the entries in the constant pool.
- * If one entry has a reference to another entry, the latter (lower-level)
- * entry will be visited first.
- * <p>
- * The following table shows the relation between constant pool entry
- * types and the corresponding visit* methods:
- *
- * <table border=1 cellpadding=5 summary="constant pool visitor methods">
- * <tr><th>Tag(s)</th><th>Method</th></tr>
- * <tr>
- *   <td>{@link #CONSTANT_Utf8}</td>
- *   <td>{@link #visitUTF8(int, byte, String)}</td>
- * </tr><tr>
- *   <td>{@link #CONSTANT_Integer}, {@link #CONSTANT_Float},
- *       {@link #CONSTANT_Long}, {@link #CONSTANT_Double}</td>
- *   <td>{@link #visitConstantValue(int, byte, Object)}</td>
- * </tr><tr>
- *   <td>{@link #CONSTANT_String}, {@link #CONSTANT_Class}</td>
- *   <td>{@link #visitConstantString(int, byte, String, int)}</td>
- * </tr><tr>
- *   <td>{@link #CONSTANT_NameAndType}</td>
- *   <td>{@link #visitDescriptor(int, byte, String, String, int, int)}</td>
- * </tr><tr>
- *   <td>{@link #CONSTANT_Fieldref},
- *       {@link #CONSTANT_Methodref},
- *       {@link #CONSTANT_InterfaceMethodref}</td>
- *   <td>{@link #visitMemberRef(int, byte, String, String, String, int, int)}</td>
- * </tr>
- * </table>
- *
- * @see ConstantPoolPatch
- * @author Remi Forax
- * @author jrose
- */
-public class ConstantPoolVisitor {
-  /** Called each time an UTF8 constant pool entry is found.
-   * @param index the constant pool index
-   * @param tag always {@link #CONSTANT_Utf8}
-   * @param utf8 string encoded in modified UTF-8 format passed as a {@code String}
-   *
-   * @see ConstantPoolPatch#putUTF8(int, String)
-   */
-  public void visitUTF8(int index, byte tag, String utf8) {
-    // do nothing
-  }
-
-  /** Called for each constant pool entry that encodes an integer,
-   *  a float, a long, or a double.
-   *  Constant strings and classes are not managed by this method but
-   *  by {@link #visitConstantString(int, byte, String, int)}.
-   *
-   * @param index the constant pool index
-   * @param tag one of {@link #CONSTANT_Integer},
-   *            {@link #CONSTANT_Float},
-   *            {@link #CONSTANT_Long},
-   *            or {@link #CONSTANT_Double}
-   * @param value encoded value
-   *
-   * @see ConstantPoolPatch#putConstantValue(int, Object)
-   */
-  public void visitConstantValue(int index, byte tag, Object value) {
-    // do nothing
-  }
-
-  /** Called for each constant pool entry that encodes a string or a class.
-   * @param index the constant pool index
-   * @param tag one of {@link #CONSTANT_String},
-   *            {@link #CONSTANT_Class},
-   * @param name string body or class name (using dot separator)
-   * @param nameIndex the index of the Utf8 string for the name
-   *
-   * @see ConstantPoolPatch#putConstantValue(int, byte, Object)
-   */
-  public void visitConstantString(int index, byte tag,
-                                  String name, int nameIndex) {
-    // do nothing
-  }
-
-  /** Called for each constant pool entry that encodes a name and type.
-   * @param index the constant pool index
-   * @param tag always {@link #CONSTANT_NameAndType}
-   * @param memberName a field or method name
-   * @param signature the member signature
-   * @param memberNameIndex index of the Utf8 string for the member name
-   * @param signatureIndex index of the Utf8 string for the signature
-   *
-   * @see ConstantPoolPatch#putDescriptor(int, String, String)
-   */
-  public void visitDescriptor(int index, byte tag,
-                              String memberName, String signature,
-                              int memberNameIndex, int signatureIndex) {
-    // do nothing
-  }
-
-  /** Called for each constant pool entry that encodes a field or method.
-   * @param index the constant pool index
-   * @param tag one of {@link #CONSTANT_Fieldref},
-   *            or {@link #CONSTANT_Methodref},
-   *            or {@link #CONSTANT_InterfaceMethodref}
-   * @param className the class name (using dot separator)
-   * @param memberName name of the field or method
-   * @param signature the field or method signature
-   * @param classNameIndex index of the Utf8 string for the class name
-   * @param descriptorIndex index of the NameAndType descriptor constant
-   *
-   * @see ConstantPoolPatch#putMemberRef(int, byte, String, String, String)
-   */
-  public void visitMemberRef(int index, byte tag,
-                             String className, String memberName, String signature,
-                             int classNameIndex, int descriptorIndex) {
-    // do nothing
-  }
-
-    public static final byte
-      CONSTANT_None = 0,
-      CONSTANT_Utf8 = 1,
-      //CONSTANT_Unicode = 2,               /* unused */
-      CONSTANT_Integer = 3,
-      CONSTANT_Float = 4,
-      CONSTANT_Long = 5,
-      CONSTANT_Double = 6,
-      CONSTANT_Class = 7,
-      CONSTANT_String = 8,
-      CONSTANT_Fieldref = 9,
-      CONSTANT_Methodref = 10,
-      CONSTANT_InterfaceMethodref = 11,
-      CONSTANT_NameAndType = 12;
-
-    private static String[] TAG_NAMES = {
-        "Empty",
-        "Utf8",
-        null, //"Unicode",
-        "Integer",
-        "Float",
-        "Long",
-        "Double",
-        "Class",
-        "String",
-        "Fieldref",
-        "Methodref",
-        "InterfaceMethodref",
-        "NameAndType"
-    };
-
-    public static String tagName(byte tag) {
-        String name = null;
-        if ((tag & 0xFF) < TAG_NAMES.length)
-            name = TAG_NAMES[tag];
-        if (name == null)
-            name = "Unknown#"+(tag&0xFF);
-        return name;
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/anon/InvalidConstantPoolFormatException.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-/** Exception used when there is an error in the constant pool
- *  format.
- */
-public class InvalidConstantPoolFormatException extends Exception {
-    private static final long serialVersionUID=-6103888330523770949L;
-
-    public InvalidConstantPoolFormatException(String message,Throwable cause) {
-        super(message,cause);
-    }
-
-    public InvalidConstantPoolFormatException(String message) {
-        super(message);
-    }
-
-    public InvalidConstantPoolFormatException(Throwable cause) {
-        super(cause);
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/empty/Empty.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.empty;
-
-/**
- * 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 {
-    private Empty() { throw new InternalError(); }
-}
--- a/jdk/src/share/classes/sun/dyn/package-info.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * Implementation details for JSR 292 RI, package java.dyn.
- * @author jrose
- */
-
-package sun.dyn;
--- a/jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package 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	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,627 +0,0 @@
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-/**
- * Utility routines for dealing with bytecode-level names.
- * Includes universal mangling rules for the JVM.
- *
- * <h3>Avoiding Dangerous Characters </h3>
- *
- * <p>
- * The JVM defines a very small set of characters which are illegal
- * in name spellings.  We will slightly extend and regularize this set
- * into a group of <cite>dangerous characters</cite>.
- * These characters will then be replaced, in mangled names, by escape sequences.
- * In addition, accidental escape sequences must be further escaped.
- * Finally, a special prefix will be applied if and only if
- * the mangling would otherwise fail to begin with the escape character.
- * This happens to cover the corner case of the null string,
- * and also clearly marks symbols which need demangling.
- * </p>
- * <p>
- * Dangerous characters are the union of all characters forbidden
- * or otherwise restricted by the JVM specification,
- * plus their mates, if they are brackets
- * (<code><big><b>[</b></big></code> and <code><big><b>]</b></big></code>,
- * <code><big><b>&lt;</b></big></code> and <code><big><b>&gt;</b></big></code>),
- * plus, arbitrarily, the colon character <code><big><b>:</b></big></code>.
- * There is no distinction between type, method, and field names.
- * This makes it easier to convert between mangled names of different
- * types, since they do not need to be decoded (demangled).
- * </p>
- * <p>
- * The escape character is backslash <code><big><b>\</b></big></code>
- * (also known as reverse solidus).
- * This character is, until now, unheard of in bytecode names,
- * but traditional in the proposed role.
- *
- * </p>
- * <h3> Replacement Characters </h3>
- *
- *
- * <p>
- * Every escape sequence is two characters
- * (in fact, two UTF8 bytes) beginning with
- * the escape character and followed by a
- * <cite>replacement character</cite>.
- * (Since the replacement character is never a backslash,
- * iterated manglings do not double in size.)
- * </p>
- * <p>
- * Each dangerous character has some rough visual similarity
- * to its corresponding replacement character.
- * This makes mangled symbols easier to recognize by sight.
- * </p>
- * <p>
- * The dangerous characters are
- * <code><big><b>/</b></big></code> (forward slash, used to delimit package components),
- * <code><big><b>.</b></big></code> (dot, also a package delimiter),
- * <code><big><b>;</b></big></code> (semicolon, used in signatures),
- * <code><big><b>$</b></big></code> (dollar, used in inner classes and synthetic members),
- * <code><big><b>&lt;</b></big></code> (left angle),
- * <code><big><b>&gt;</b></big></code> (right angle),
- * <code><big><b>[</b></big></code> (left square bracket, used in array types),
- * <code><big><b>]</b></big></code> (right square bracket, reserved in this scheme for language use),
- * and <code><big><b>:</b></big></code> (colon, reserved in this scheme for language use).
- * Their replacements are, respectively,
- * <code><big><b>|</b></big></code> (vertical bar),
- * <code><big><b>,</b></big></code> (comma),
- * <code><big><b>?</b></big></code> (question mark),
- * <code><big><b>%</b></big></code> (percent),
- * <code><big><b>^</b></big></code> (caret),
- * <code><big><b>_</b></big></code> (underscore), and
- * <code><big><b>{</b></big></code> (left curly bracket),
- * <code><big><b>}</b></big></code> (right curly bracket),
- * <code><big><b>!</b></big></code> (exclamation mark).
- * In addition, the replacement character for the escape character itself is
- * <code><big><b>-</b></big></code> (hyphen),
- * and the replacement character for the null prefix is
- * <code><big><b>=</b></big></code> (equal sign).
- * </p>
- * <p>
- * An escape character <code><big><b>\</b></big></code>
- * followed by any of these replacement characters
- * is an escape sequence, and there are no other escape sequences.
- * An equal sign is only part of an escape sequence
- * if it is the second character in the whole string, following a backslash.
- * Two consecutive backslashes do <em>not</em> form an escape sequence.
- * </p>
- * <p>
- * Each escape sequence replaces a so-called <cite>original character</cite>
- * which is either one of the dangerous characters or the escape character.
- * A null prefix replaces an initial null string, not a character.
- * </p>
- * <p>
- * All this implies that escape sequences cannot overlap and may be
- * determined all at once for a whole string.  Note that a spelling
- * string can contain <cite>accidental escapes</cite>, apparent escape
- * sequences which must not be interpreted as manglings.
- * These are disabled by replacing their leading backslash with an
- * escape sequence (<code><big><b>\-</b></big></code>).  To mangle a string, three logical steps
- * are required, though they may be carried out in one pass:
- * </p>
- * <ol>
- *   <li>In each accidental escape, replace the backslash with an escape sequence
- * (<code><big><b>\-</b></big></code>).</li>
- *   <li>Replace each dangerous character with an escape sequence
- * (<code><big><b>\|</b></big></code> for <code><big><b>/</b></big></code>, etc.).</li>
- *   <li>If the first two steps introduced any change, <em>and</em>
- * if the string does not already begin with a backslash, prepend a null prefix (<code><big><b>\=</b></big></code>).</li>
- * </ol>
- *
- * To demangle a mangled string that begins with an escape,
- * remove any null prefix, and then replace (in parallel)
- * each escape sequence by its original character.
- * <p>Spelling strings which contain accidental
- * escapes <em>must</em> have them replaced, even if those
- * strings do not contain dangerous characters.
- * This restriction means that mangling a string always
- * requires a scan of the string for escapes.
- * But then, a scan would be required anyway,
- * to check for dangerous characters.
- *
- * </p>
- * <h3> Nice Properties </h3>
- *
- * <p>
- * If a bytecode name does not contain any escape sequence,
- * demangling is a no-op:  The string demangles to itself.
- * Such a string is called <cite>self-mangling</cite>.
- * Almost all strings are self-mangling.
- * In practice, to demangle almost any name &ldquo;found in nature&rdquo;,
- * simply verify that it does not begin with a backslash.
- * </p>
- * <p>
- * Mangling is a one-to-one function, while demangling
- * is a many-to-one function.
- * A mangled string is defined as <cite>validly mangled</cite> if
- * it is in fact the unique mangling of its spelling string.
- * Three examples of invalidly mangled strings are <code><big><b>\=foo</b></big></code>,
- * <code><big><b>\-bar</b></big></code>, and <code><big><b>baz\!</b></big></code>, which demangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and
- * <code><big><b>baz\!</b></big></code>, but then remangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and <code><big><b>\=baz\-!</b></big></code>.
- * If a language back-end or runtime is using mangled names,
- * it should never present an invalidly mangled bytecode
- * name to the JVM.  If the runtime encounters one,
- * it should also report an error, since such an occurrence
- * probably indicates a bug in name encoding which
- * will lead to errors in linkage.
- * However, this note does not propose that the JVM verifier
- * detect invalidly mangled names.
- * </p>
- * <p>
- * As a result of these rules, it is a simple matter to
- * compute validly mangled substrings and concatenations
- * of validly mangled strings, and (with a little care)
- * these correspond to corresponding operations on their
- * spelling strings.
- * </p>
- * <ul>
- *   <li>Any prefix of a validly mangled string is also validly mangled,
- * although a null prefix may need to be removed.</li>
- *   <li>Any suffix of a validly mangled string is also validly mangled,
- * although a null prefix may need to be added.</li>
- *   <li>Two validly mangled strings, when concatenated,
- * are also validly mangled, although any null prefix
- * must be removed from the second string,
- * and a trailing backslash on the first string may need escaping,
- * if it would participate in an accidental escape when followed
- * by the first character of the second string.</li>
- * </ul>
- * <p>If languages that include non-Java symbol spellings use this
- * mangling convention, they will enjoy the following advantages:
- * </p>
- * <ul>
- *   <li>They can interoperate via symbols they share in common.</li>
- *   <li>Low-level tools, such as backtrace printers, will have readable displays.</li>
- *   <li>Future JVM and language extensions can safely use the dangerous characters
- * for structuring symbols, but will never interfere with valid spellings.</li>
- *   <li>Runtimes and compilers can use standard libraries for mangling and demangling.</li>
- *   <li>Occasional transliterations and name composition will be simple and regular,
- * for classes, methods, and fields.</li>
- *   <li>Bytecode names will continue to be compact.
- * When mangled, spellings will at most double in length, either in
- * UTF8 or UTF16 format, and most will not change at all.</li>
- * </ul>
- *
- *
- * <h3> Suggestions for Human Readable Presentations </h3>
- *
- *
- * <p>
- * For human readable displays of symbols,
- * it will be better to present a string-like quoted
- * representation of the spelling, because JVM users
- * are generally familiar with such tokens.
- * We suggest using single or double quotes before and after
- * mangled symbols which are not valid Java identifiers,
- * with quotes, backslashes, and non-printing characters
- * escaped as if for literals in the Java language.
- * </p>
- * <p>
- * For example, an HTML-like spelling
- * <code><big><b>&lt;pre&gt;</b></big></code> mangles to
- * <code><big><b>\^pre\_</b></big></code> and could
- * display more cleanly as
- * <code><big><b>'&lt;pre&gt;'</b></big></code>,
- * with the quotes included.
- * Such string-like conventions are <em>not</em> suitable
- * for mangled bytecode names, in part because
- * dangerous characters must be eliminated, rather
- * than just quoted.  Otherwise internally structured
- * strings like package prefixes and method signatures
- * could not be reliably parsed.
- * </p>
- * <p>
- * In such human-readable displays, invalidly mangled
- * names should <em>not</em> be demangled and quoted,
- * for this would be misleading.  Likewise, JVM symbols
- * which contain dangerous characters (like dots in field
- * names or brackets in method names) should not be
- * simply quoted.  The bytecode names
- * <code><big><b>\=phase\,1</b></big></code> and
- * <code><big><b>phase.1</b></big></code> are distinct,
- * and in demangled displays they should be presented as
- * <code><big><b>'phase.1'</b></big></code> and something like
- * <code><big><b>'phase'.1</b></big></code>, respectively.
- * </p>
- *
- * @author John Rose
- * @version 1.2, 02/06/2008
- * @see http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm
- */
-public class BytecodeName {
-    private BytecodeName() { }  // static only class
-
-    /** Given a source name, produce the corresponding bytecode name.
-     * The source name should not be qualified, because any syntactic
-     * markers (dots, slashes, dollar signs, colons, etc.) will be mangled.
-     * @param s the source name
-     * @return a valid bytecode name which represents the source name
-     */
-    public static String toBytecodeName(String s) {
-        String bn = mangle(s);
-        assert((Object)bn == s || looksMangled(bn)) : bn;
-        assert(s.equals(toSourceName(bn))) : s;
-        return bn;
-    }
-
-    /** Given an unqualified bytecode name, produce the corresponding source name.
-     * The bytecode name must not contain dangerous characters.
-     * In particular, it must not be qualified or segmented by colon {@code ':'}.
-     * @param s the bytecode name
-     * @return the source name, which may possibly have unsafe characters
-     * @throws IllegalArgumentException if the bytecode name is not {@link #isSafeBytecodeName safe}
-     * @see #isSafeBytecodeName(java.lang.String)
-     */
-    public static String toSourceName(String s) {
-        checkSafeBytecodeName(s);
-        String sn = s;
-        if (looksMangled(s)) {
-            sn = demangle(s);
-            assert(s.equals(mangle(sn))) : s+" => "+sn+" => "+mangle(sn);
-        }
-        return sn;
-    }
-
-    /**
-     * Given a bytecode name from a classfile, separate it into
-     * components delimited by dangerous characters.
-     * Each resulting array element will be either a dangerous character,
-     * or else a safe bytecode name.
-     * (The safe name might possibly be mangled to hide further dangerous characters.)
-     * For example, the qualified class name {@code java/lang/String}
-     * will be parsed into the array {@code {"java", '/', "lang", '/', "String"}}.
-     * 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();
-        Object[] res = null;
-        for (int pass = 0; pass <= 1; pass++) {
-            int fillp = 0;
-            int lasti = 0;
-            for (int i = 0; i <= slen; i++) {
-                int whichDC = -1;
-                if (i < slen) {
-                    whichDC = DANGEROUS_CHARS.indexOf(s.charAt(i));
-                    if (whichDC < DANGEROUS_CHAR_FIRST_INDEX)  continue;
-                }
-                // got to end of string or next dangerous char
-                if (lasti < i) {
-                    // normal component
-                    if (pass != 0)
-                        res[fillp] = toSourceName(s.substring(lasti, i));
-                    fillp++;
-                    lasti = i+1;
-                }
-                if (whichDC >= DANGEROUS_CHAR_FIRST_INDEX) {
-                    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 Object[fillp];
-            if (fillp <= 1 && lasti == 0) {
-                if (fillp != 0)  res[0] = toSourceName(s);
-                break;
-            }
-        }
-        return res;
-    }
-
-    /**
-     * Given a series of components, create a bytecode name for a classfile.
-     * This is the inverse of {@link #parseBytecodeName(java.lang.String)}.
-     * Each component must either be an interned one-character string of
-     * a dangerous character, or else a safe bytecode name.
-     * @param components a series of name components
-     * @return the concatenation of all components
-     * @throws IllegalArgumentException if any component contains an unsafe
-     *          character, and is not an interned one-character string
-     * @throws NullPointerException if any component is null
-     */
-    public static String unparseBytecodeName(Object[] components) {
-        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);
-    }
-    private static String appendAll(Object[] components) {
-        if (components.length <= 1) {
-            if (components.length == 1) {
-                return String.valueOf(components[0]);
-            }
-            return "";
-        }
-        int slen = 0;
-        for (Object c : components) {
-            if (c instanceof String)
-                slen += String.valueOf(c).length();
-            else
-                slen += 1;
-        }
-        StringBuilder sb = new StringBuilder(slen);
-        for (Object c : components) {
-            sb.append(c);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Given a bytecode name, produce the corresponding display name.
-     * This is the source name, plus quotes if needed.
-     * 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
-     */
-    public static String toDisplayName(String s) {
-        Object[] components = parseBytecodeName(s);
-        for (int i = 0; i < components.length; i++) {
-            if (!(components[i] instanceof String))
-                continue;
-            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);
-            }
-        }
-        return appendAll(components);
-    }
-    private static boolean isJavaIdent(String s) {
-        int slen = s.length();
-        if (slen == 0)  return false;
-        if (!Character.isJavaIdentifierStart(s.charAt(0)))
-            return false;
-        for (int i = 1; i < slen; i++) {
-            if (!Character.isJavaIdentifierPart(s.charAt(i)))
-                return false;
-        }
-        return true;
-    }
-    private static String quoteDisplay(String s) {
-        // TO DO:  Replace wierd characters in s by C-style escapes.
-        return "'"+s.replaceAll("['\\\\]", "\\\\$0")+"'";
-    }
-
-    private static void checkSafeBytecodeName(String s)
-            throws IllegalArgumentException {
-        if (!isSafeBytecodeName(s)) {
-            throw new IllegalArgumentException(s);
-        }
-    }
-
-    /**
-     * Report whether a simple name is safe as a bytecode name.
-     * Such names are acceptable in class files as class, method, and field names.
-     * Additionally, they are free of "dangerous" characters, even if those
-     * characters are legal in some (or all) names in class files.
-     * @param s the proposed bytecode name
-     * @return true if the name is non-empty and all of its characters are safe
-     */
-    public static boolean isSafeBytecodeName(String s) {
-        if (s.length() == 0)  return false;
-        // check occurrences of each DANGEROUS char
-        for (char xc : DANGEROUS_CHARS_A) {
-            if (xc == ESCAPE_C)  continue;  // not really that dangerous
-            if (s.indexOf(xc) >= 0)  return false;
-        }
-        return true;
-    }
-
-    /**
-     * Report whether a character is safe in a bytecode name.
-     * This is true of any unicode character except the following
-     * <em>dangerous characters</em>: {@code ".;:$[]<>/"}.
-     * @param s the proposed character
-     * @return true if the character is safe to use in classfiles
-     */
-    public static boolean isSafeBytecodeChar(char c) {
-        return DANGEROUS_CHARS.indexOf(c) < DANGEROUS_CHAR_FIRST_INDEX;
-    }
-
-    private static boolean looksMangled(String s) {
-        return s.charAt(0) == ESCAPE_C;
-    }
-
-    private static String mangle(String s) {
-        if (s.length() == 0)
-            return NULL_ESCAPE;
-
-        // build this lazily, when we first need an escape:
-        StringBuilder sb = null;
-
-        for (int i = 0, slen = s.length(); i < slen; i++) {
-            char c = s.charAt(i);
-
-            boolean needEscape = false;
-            if (c == ESCAPE_C) {
-                if (i+1 < slen) {
-                    char c1 = s.charAt(i+1);
-                    if ((i == 0 && c1 == NULL_ESCAPE_C)
-                        || c1 != originalOfReplacement(c1)) {
-                        // an accidental escape
-                        needEscape = true;
-                    }
-                }
-            } else {
-                needEscape = isDangerous(c);
-            }
-
-            if (!needEscape) {
-                if (sb != null)  sb.append(c);
-                continue;
-            }
-
-            // build sb if this is the first escape
-            if (sb == null) {
-                sb = new StringBuilder(s.length()+10);
-                // mangled names must begin with a backslash:
-                if (s.charAt(0) != ESCAPE_C && i > 0)
-                    sb.append(NULL_ESCAPE);
-                // append the string so far, which is unremarkable:
-                sb.append(s.substring(0, i));
-            }
-
-            // rewrite \ to \-, / to \|, etc.
-            sb.append(ESCAPE_C);
-            sb.append(replacementOf(c));
-        }
-
-        if (sb != null)   return sb.toString();
-
-        return s;
-    }
-
-    private static String demangle(String s) {
-        // build this lazily, when we first meet an escape:
-        StringBuilder sb = null;
-
-        int stringStart = 0;
-        if (s.startsWith(NULL_ESCAPE))
-            stringStart = 2;
-
-        for (int i = stringStart, slen = s.length(); i < slen; i++) {
-            char c = s.charAt(i);
-
-            if (c == ESCAPE_C && i+1 < slen) {
-                // might be an escape sequence
-                char rc = s.charAt(i+1);
-                char oc = originalOfReplacement(rc);
-                if (oc != rc) {
-                    // build sb if this is the first escape
-                    if (sb == null) {
-                        sb = new StringBuilder(s.length());
-                        // append the string so far, which is unremarkable:
-                        sb.append(s.substring(stringStart, i));
-                    }
-                    ++i;  // skip both characters
-                    c = oc;
-                }
-            }
-
-            if (sb != null)
-                sb.append(c);
-        }
-
-        if (sb != null)   return sb.toString();
-
-        return s.substring(stringStart);
-    }
-
-    static char ESCAPE_C = '\\';
-    // empty escape sequence to avoid a null name or illegal prefix
-    static char NULL_ESCAPE_C = '=';
-    static String NULL_ESCAPE = ESCAPE_C+""+NULL_ESCAPE_C;
-
-    static final String DANGEROUS_CHARS   = "\\/.;:$[]<>"; // \\ must be first
-    static final String REPLACEMENT_CHARS =  "-|,?!%{}^_";
-    static final int DANGEROUS_CHAR_FIRST_INDEX = 1; // index after \\
-    static char[] DANGEROUS_CHARS_A   = DANGEROUS_CHARS.toCharArray();
-    static char[] REPLACEMENT_CHARS_A = REPLACEMENT_CHARS.toCharArray();
-    static final Character[] DANGEROUS_CHARS_CA;
-    static {
-        Character[] dcca = new Character[DANGEROUS_CHARS.length()];
-        for (int i = 0; i < dcca.length; i++)
-            dcca[i] = Character.valueOf(DANGEROUS_CHARS.charAt(i));
-        DANGEROUS_CHARS_CA = dcca;
-    }
-
-    static final long[] SPECIAL_BITMAP = new long[2];  // 128 bits
-    static {
-        String SPECIAL = DANGEROUS_CHARS + REPLACEMENT_CHARS;
-        //System.out.println("SPECIAL = "+SPECIAL);
-        for (char c : SPECIAL.toCharArray()) {
-            SPECIAL_BITMAP[c >>> 6] |= 1L << c;
-        }
-    }
-    static boolean isSpecial(char c) {
-        if ((c >>> 6) < SPECIAL_BITMAP.length)
-            return ((SPECIAL_BITMAP[c >>> 6] >> c) & 1) != 0;
-        else
-            return false;
-    }
-    static char replacementOf(char c) {
-        if (!isSpecial(c))  return c;
-        int i = DANGEROUS_CHARS.indexOf(c);
-        if (i < 0)  return c;
-        return REPLACEMENT_CHARS.charAt(i);
-    }
-    static char originalOfReplacement(char c) {
-        if (!isSpecial(c))  return c;
-        int i = REPLACEMENT_CHARS.indexOf(c);
-        if (i < 0)  return c;
-        return DANGEROUS_CHARS.charAt(i);
-    }
-    static boolean isDangerous(char c) {
-        if (!isSpecial(c))  return false;
-        return (DANGEROUS_CHARS.indexOf(c) >= DANGEROUS_CHAR_FIRST_INDEX);
-    }
-    static int indexOfDangerousChar(String s, int from) {
-        for (int i = from, slen = s.length(); i < slen; i++) {
-            if (isDangerous(s.charAt(i)))
-                return i;
-        }
-        return -1;
-    }
-    static int lastIndexOfDangerousChar(String s, int from) {
-        for (int i = Math.min(from, s.length()-1); i >= 0; i--) {
-            if (isDangerous(s.charAt(i)))
-                return i;
-        }
-        return -1;
-    }
-
-
-}
--- a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,807 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-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;
-import static sun.dyn.MemberName.uncaughtException;
-
-public class ValueConversions {
-    private static final Access IMPL_TOKEN = Access.getToken();
-    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++)
-            caches[i] = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
-        return caches;
-    }
-
-    /// Converting references to values.
-
-    static int unboxInteger(Object x) {
-        if (x == null)  return 0;  // never NPE
-        return ((Integer) x).intValue();
-    }
-
-    static byte unboxByte(Object x) {
-        if (x == null)  return 0;  // never NPE
-        return ((Byte) x).byteValue();
-    }
-
-    static short unboxShort(Object x) {
-        if (x == null)  return 0;  // never NPE
-        return ((Short) x).shortValue();
-    }
-
-    static boolean unboxBoolean(Object x) {
-        if (x == null)  return false;  // never NPE
-        return ((Boolean) x).booleanValue();
-    }
-
-    static char unboxCharacter(Object x) {
-        if (x == null)  return 0;  // never NPE
-        return ((Character) x).charValue();
-    }
-
-    static long unboxLong(Object x) {
-        if (x == null)  return 0;  // never NPE
-        return ((Long) x).longValue();
-    }
-
-    static float unboxFloat(Object x) {
-        if (x == null)  return 0;  // never NPE
-        return ((Float) x).floatValue();
-    }
-
-    static double unboxDouble(Object x) {
-        if (x == null)  return 0;  // never NPE
-        return ((Double) x).doubleValue();
-    }
-
-    /// Converting references to "raw" values.
-    /// A raw primitive value is always an int or long.
-
-    static int unboxByteRaw(Object x) {
-        return unboxByte(x);
-    }
-
-    static int unboxShortRaw(Object x) {
-        return unboxShort(x);
-    }
-
-    static int unboxBooleanRaw(Object x) {
-        return unboxBoolean(x) ? 1 : 0;
-    }
-
-    static int unboxCharacterRaw(Object x) {
-        return unboxCharacter(x);
-    }
-
-    static int unboxFloatRaw(Object x) {
-        return Float.floatToIntBits(unboxFloat(x));
-    }
-
-    static long unboxDoubleRaw(Object x) {
-        return Double.doubleToRawLongBits(unboxDouble(x));
-    }
-
-    private static MethodType unboxType(Wrapper wrap, boolean raw) {
-        return MethodType.methodType(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType());
-    }
-
-    private static final EnumMap<Wrapper, MethodHandle>[]
-            UNBOX_CONVERSIONS = newWrapperCaches(4);
-
-    private static MethodHandle unbox(Wrapper wrap, boolean exact, boolean raw) {
-        EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
-        MethodHandle mh = cache.get(wrap);
-        if (mh != null) {
-            return mh;
-        }
-        // slow path
-        switch (wrap) {
-            case OBJECT:
-                mh = IDENTITY; break;
-            case VOID:
-                mh = raw ? ALWAYS_ZERO : IGNORE; break;
-            case INT: case LONG:
-                // these guys don't need separate raw channels
-                if (raw)  mh = unbox(wrap, exact, false);
-                break;
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-        // look up the method
-        String name = "unbox" + wrap.simpleName() + (raw ? "Raw" : "");
-        MethodType type = unboxType(wrap, raw);
-        if (!exact) {
-            try {
-                // actually, type is wrong; the Java method takes Object
-                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase());
-            } catch (ReflectiveOperationException ex) {
-                mh = null;
-            }
-        } else {
-            mh = retype(type, unbox(wrap, !exact, raw));
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-        throw new IllegalArgumentException("cannot find unbox adapter for " + wrap + (raw ? " (raw)" : ""));
-    }
-
-    public static MethodHandle unbox(Wrapper type, boolean exact) {
-        return unbox(type, exact, false);
-    }
-
-    public static MethodHandle unboxRaw(Wrapper type, boolean exact) {
-        return unbox(type, exact, true);
-    }
-
-    public static MethodHandle unbox(Class<?> type, boolean exact) {
-        return unbox(Wrapper.forPrimitiveType(type), exact, false);
-    }
-
-    public static MethodHandle unboxRaw(Class<?> type, boolean exact) {
-        return unbox(Wrapper.forPrimitiveType(type), exact, true);
-    }
-
-    /// Converting primitives to references
-
-    static Integer boxInteger(int x) {
-        return x;
-    }
-
-    static Byte boxByte(byte x) {
-        return x;
-    }
-
-    static Short boxShort(short x) {
-        return x;
-    }
-
-    static Boolean boxBoolean(boolean x) {
-        return x;
-    }
-
-    static Character boxCharacter(char x) {
-        return x;
-    }
-
-    static Long boxLong(long x) {
-        return x;
-    }
-
-    static Float boxFloat(float x) {
-        return x;
-    }
-
-    static Double boxDouble(double x) {
-        return x;
-    }
-
-    /// Converting raw primitives to references
-
-    static Byte boxByteRaw(int x) {
-        return boxByte((byte)x);
-    }
-
-    static Short boxShortRaw(int x) {
-        return boxShort((short)x);
-    }
-
-    static Boolean boxBooleanRaw(int x) {
-        return boxBoolean(x != 0);
-    }
-
-    static Character boxCharacterRaw(int x) {
-        return boxCharacter((char)x);
-    }
-
-    static Float boxFloatRaw(int x) {
-        return boxFloat(Float.intBitsToFloat(x));
-    }
-
-    static Double boxDoubleRaw(long x) {
-        return boxDouble(Double.longBitsToDouble(x));
-    }
-
-    // a raw void value is (arbitrarily) a garbage int
-    static Void boxVoidRaw(int x) {
-        return null;
-    }
-
-    private static MethodType boxType(Wrapper wrap, boolean raw) {
-        // be exact, since return casts are hard to compose
-        Class<?> boxType = wrap.wrapperType();
-        return MethodType.methodType(boxType, rawWrapper(wrap, raw).primitiveType());
-    }
-
-    private static Wrapper rawWrapper(Wrapper wrap, boolean raw) {
-        if (raw)  return wrap.isDoubleWord() ? Wrapper.LONG : Wrapper.INT;
-        return wrap;
-    }
-
-    private static final EnumMap<Wrapper, MethodHandle>[]
-            BOX_CONVERSIONS = newWrapperCaches(4);
-
-    private static MethodHandle box(Wrapper wrap, boolean exact, boolean raw) {
-        EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
-        MethodHandle mh = cache.get(wrap);
-        if (mh != null) {
-            return mh;
-        }
-        // slow path
-        switch (wrap) {
-            case OBJECT:
-                mh = IDENTITY; break;
-            case VOID:
-                if (!raw)  mh = ZERO_OBJECT;
-                break;
-            case INT: case LONG:
-                // these guys don't need separate raw channels
-                if (raw)  mh = box(wrap, exact, false);
-                break;
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-        // look up the method
-        String name = "box" + wrap.simpleName() + (raw ? "Raw" : "");
-        MethodType type = boxType(wrap, raw);
-        if (exact) {
-            try {
-                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
-            } catch (ReflectiveOperationException ex) {
-                mh = null;
-            }
-        } else {
-            mh = retype(type.erase(), box(wrap, !exact, raw));
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-        throw new IllegalArgumentException("cannot find box adapter for " + wrap + (raw ? " (raw)" : ""));
-    }
-
-    public static MethodHandle box(Class<?> type, boolean exact) {
-        return box(Wrapper.forPrimitiveType(type), exact, false);
-    }
-
-    public static MethodHandle boxRaw(Class<?> type, boolean exact) {
-        return box(Wrapper.forPrimitiveType(type), exact, true);
-    }
-
-    public static MethodHandle box(Wrapper type, boolean exact) {
-        return box(type, exact, false);
-    }
-
-    public static MethodHandle boxRaw(Wrapper type, boolean exact) {
-        return box(type, exact, true);
-    }
-
-    /// 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(unboxRawInteger(x));
-    }
-
-    static Short reboxRawShort(Object x) {
-        if (x instanceof Short)  return (Short) x;
-        return boxShortRaw(unboxRawInteger(x));
-    }
-
-    static Boolean reboxRawBoolean(Object x) {
-        if (x instanceof Boolean)  return (Boolean) x;
-        return boxBooleanRaw(unboxRawInteger(x));
-    }
-
-    static Character reboxRawCharacter(Object x) {
-        if (x instanceof Character)  return (Character) x;
-        return boxCharacterRaw(unboxRawInteger(x));
-    }
-
-    static Float reboxRawFloat(Object x) {
-        if (x instanceof Float)  return (Float) x;
-        return boxFloatRaw(unboxRawInteger(x));
-    }
-
-    static Long reboxRawLong(Object x) {
-        return (Long) x;  //never a rebox
-    }
-
-    static Double reboxRawDouble(Object x) {
-        if (x instanceof Double)  return (Double) x;
-        return boxDoubleRaw(unboxLong(x));
-    }
-
-    private static MethodType reboxType(Wrapper wrap) {
-        Class<?> boxType = wrap.wrapperType();
-        return MethodType.methodType(boxType, Object.class);
-    }
-
-    private static final EnumMap<Wrapper, MethodHandle>[]
-            REBOX_CONVERSIONS = newWrapperCaches(2);
-
-    /**
-     * Because 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);
-        if (mh != null) {
-            return mh;
-        }
-        // slow path
-        switch (wrap) {
-            case OBJECT:
-                mh = IDENTITY; break;
-            case VOID:
-                throw new IllegalArgumentException("cannot rebox a void");
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-        // look up the method
-        String name = "reboxRaw" + wrap.simpleName();
-        MethodType type = reboxType(wrap);
-        if (exact) {
-            try {
-                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
-            } catch (ReflectiveOperationException ex) {
-                mh = null;
-            }
-        } else {
-            mh = retype(IDENTITY.type(), rebox(wrap, !exact));
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-        throw new IllegalArgumentException("cannot find rebox adapter for " + wrap);
-    }
-
-    public static MethodHandle rebox(Class<?> type, boolean exact) {
-        return rebox(Wrapper.forPrimitiveType(type), exact);
-    }
-
-    /// Width-changing conversions between int and long.
-
-    static long widenInt(int 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) {
-        // no value to return; this is an unbox of null
-        return;
-    }
-
-    static void empty() {
-        return;
-    }
-
-    static Object zeroObject() {
-        return null;
-    }
-
-    static int zeroInteger() {
-        return 0;
-    }
-
-    static long zeroLong() {
-        return 0;
-    }
-
-    static float zeroFloat() {
-        return 0;
-    }
-
-    static double zeroDouble() {
-        return 0;
-    }
-
-    private static final EnumMap<Wrapper, MethodHandle>[]
-            CONSTANT_FUNCTIONS = newWrapperCaches(2);
-
-    public static MethodHandle zeroConstantFunction(Wrapper wrap) {
-        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
-        MethodHandle mh = cache.get(wrap);
-        if (mh != null) {
-            return mh;
-        }
-        // slow path
-        MethodType type = MethodType.methodType(wrap.primitiveType());
-        switch (wrap) {
-            case VOID:
-                mh = EMPTY;
-                break;
-            case INT: case LONG: case FLOAT: case DOUBLE:
-                try {
-                    mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type);
-                } catch (ReflectiveOperationException ex) {
-                    mh = null;
-                }
-                break;
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-
-        // use the raw method
-        Wrapper rawWrap = wrap.rawPrimitive();
-        if (rawWrap != wrap) {
-            mh = retype(type, zeroConstantFunction(rawWrap));
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-        throw new IllegalArgumentException("cannot find zero constant for " + wrap);
-    }
-
-    /// Converting references to references.
-
-    /**
-     * Value-killing function.
-     * @param x an arbitrary reference value
-     * @return a null
-     */
-    static Object alwaysNull(Object x) {
-        return null;
-    }
-
-    /**
-     * Value-killing function.
-     * @param x an arbitrary reference value
-     * @return a zero
-     */
-    static int alwaysZero(Object x) {
-        return 0;
-    }
-
-    /**
-     * Identity function.
-     * @param x an arbitrary reference value
-     * @return the same value x
-     */
-    static <T> T identity(T x) {
-        return x;
-    }
-
-    /**
-     * Identity function on ints.
-     * @param x an arbitrary int value
-     * @return the same value x
-     */
-    static int identity(int x) {
-        return x;
-    }
-
-    /**
-     * Identity function on longs.
-     * @param x an arbitrary long value
-     * @return the same value x
-     */
-    static long identity(long x) {
-        return x;
-    }
-
-    /**
-     * Identity function, with reference cast.
-     * @param t an arbitrary reference type
-     * @param x an arbitrary reference value
-     * @return the same value x
-     */
-    static <T,U> T castReference(Class<? extends T> t, U x) {
-        return t.cast(x);
-    }
-
-    private static final MethodHandle IDENTITY, IDENTITY_I, IDENTITY_J, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY;
-    static {
-        try {
-            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.genericMethodType(0);
-            IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType);
-            IDENTITY_I = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(int.class, int.class));
-            IDENTITY_J = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(long.class, long.class));
-            //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
-            CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType);
-            ALWAYS_NULL = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysNull", idType);
-            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.dropParameterTypes(0, 1));
-        } catch (Exception ex) {
-            throw uncaughtException(ex);
-        }
-    }
-
-    private static final EnumMap<Wrapper, MethodHandle> WRAPPER_CASTS
-            = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
-
-    private static final EnumMap<Wrapper, MethodHandle> EXACT_WRAPPER_CASTS
-            = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
-
-    /** Return a method that casts its sole argument (an Object) to the given type
-     *  and returns it as the given type (if exact is true), or as plain Object (if erase is true).
-     */
-    public static MethodHandle cast(Class<?> type, boolean exact) {
-        if (type.isPrimitive())  throw new IllegalArgumentException("cannot cast primitive type "+type);
-        MethodHandle mh = null;
-        Wrapper wrap = null;
-        EnumMap<Wrapper, MethodHandle> cache = null;
-        if (Wrapper.isWrapperType(type)) {
-            wrap = Wrapper.forWrapperType(type);
-            cache = (exact ? EXACT_WRAPPER_CASTS : WRAPPER_CASTS);
-            mh = cache.get(wrap);
-            if (mh != null)  return mh;
-        }
-        if (VerifyType.isNullReferenceConversion(Object.class, type))
-            mh = IDENTITY;
-        else if (VerifyType.isNullType(type))
-            mh = ALWAYS_NULL;
-        else
-            mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
-        if (exact) {
-            MethodType xmt = MethodType.methodType(type, Object.class);
-            mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
-        }
-        if (cache != null)
-            cache.put(wrap, mh);
-        return mh;
-    }
-
-    public static MethodHandle identity() {
-        return IDENTITY;
-    }
-
-    public static MethodHandle identity(Class<?> type) {
-        if (type == Object.class)
-            return IDENTITY;
-        else if (!type.isPrimitive())
-            return retype(MethodType.methodType(type, type), IDENTITY);
-        else
-            return identity(Wrapper.forPrimitiveType(type));
-    }
-
-    static MethodHandle identity(Wrapper wrap) {
-        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
-        MethodHandle mh = cache.get(wrap);
-        if (mh != null) {
-            return mh;
-        }
-        // slow path
-        MethodType type = MethodType.methodType(wrap.primitiveType());
-        if (wrap != Wrapper.VOID)
-            type = type.appendParameterTypes(wrap.primitiveType());
-        try {
-            mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", type);
-        } catch (ReflectiveOperationException ex) {
-            mh = null;
-        }
-        if (mh == null && wrap == Wrapper.VOID) {
-            mh = EMPTY;  // #(){} : #()void
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-
-        // use a raw conversion
-        if (wrap.isSingleWord() && wrap != Wrapper.INT) {
-            mh = retype(type, identity(Wrapper.INT));
-        } else if (wrap.isDoubleWord() && wrap != Wrapper.LONG) {
-            mh = retype(type, identity(Wrapper.LONG));
-        }
-        if (mh != null) {
-            cache.put(wrap, mh);
-            return mh;
-        }
-        throw new IllegalArgumentException("cannot find identity for " + wrap);
-    }
-
-    private static MethodHandle retype(MethodType type, MethodHandle mh) {
-        return AdapterMethodHandle.makeRetypeRaw(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 (ReflectiveOperationException 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: cannot form a varargs array of length "+nargs);
-    }
-
-    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 (ReflectiveOperationException 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	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-import java.lang.reflect.Modifier;
-import sun.dyn.MemberName;
-import sun.dyn.MethodHandleImpl;
-import sun.dyn.empty.Empty;
-import static java.lang.reflect.Modifier.*;
-
-/**
- * This class centralizes information about the JVM's linkage access control.
- * @author jrose
- */
-public class VerifyAccess {
-
-    private VerifyAccess() { }  // cannot instantiate
-
-    private static final int PACKAGE_ONLY = 0;
-    private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
-    private static final boolean ALLOW_NESTMATE_ACCESS = false;
-
-    /**
-     * Evaluate the JVM linkage rules for access to the given method
-     * on behalf of a caller class which proposes to perform the access.
-     * Return true if the caller class has privileges to invoke a method
-     * or access a field with the given properties.
-     * This requires an accessibility check of the referencing class,
-     * plus an accessibility check of the member within the class,
-     * which depends on the member's modifier flags.
-     * <p>
-     * The relevant properties include the defining class ({@code defc})
-     * of the member, and its modifier flags ({@code mods}).
-     * Also relevant is the class used to make the initial symbolic reference
-     * to the member ({@code refc}).  If this latter class is not distinguished,
-     * the defining class should be passed for both arguments ({@code defc == refc}).
-     * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
-     * A field or method R is accessible to a class or interface D if
-     * and only if any of the following conditions is true:<ul>
-     * <li>R is public.
-     * <li>R is protected and is declared in a class C, and D is either
-     *     a subclass of C or C itself.  Furthermore, if R is not
-     *     static, then the symbolic reference to R must contain a
-     *     symbolic reference to a class T, such that T is either a
-     *     subclass of D, a superclass of D or D itself.
-     * <li>R is either protected or has default access (that is,
-     *     neither public nor protected nor private), and is declared
-     *     by a class in the same runtime package as D.
-     * <li>R is private and is declared in D.
-     * </ul>
-     * This discussion of access control omits a related restriction
-     * on the target of a protected field access or method invocation
-     * (the target must be of class D or a subtype of D). That
-     * requirement is checked as part of the verification process
-     * (5.4.1); it is not part of link-time access control.
-     * @param refc the class used in the symbolic reference to the proposed member
-     * @param defc the class in which the proposed member is actually defined
-     * @param mods modifier flags for the proposed member
-     * @param lookupClass the class for which the access check is being made
-     * @return true iff the the accessing class can access such a member
-     */
-    public static boolean isMemberAccessible(Class<?> refc,  // symbolic ref class
-                                             Class<?> defc,  // actual def class
-                                             int      mods,  // actual member mods
-                                             Class<?> lookupClass) {
-        // Usually refc and defc are the same, but if they differ, verify them both.
-        if (refc != defc) {
-            if (!isClassAccessible(refc, lookupClass)) {
-                // Note that defc is verified in the switch below.
-                return false;
-            }
-            if ((mods & (ALL_ACCESS_MODES|STATIC)) == (PROTECTED|STATIC)) {
-                // Apply the special rules for refc here.
-                if (!isRelatedClass(refc, lookupClass))
-                    return isSamePackage(defc, lookupClass);
-                // If refc == defc, the call to isPublicSuperClass will do
-                // the whole job, since in that case refc (as defc) will be
-                // a superclass of the lookup class.
-            }
-        }
-        if (defc == lookupClass)
-            return true;        // easy check; all self-access is OK
-        switch (mods & ALL_ACCESS_MODES) {
-        case PUBLIC:
-            if (refc != defc)  return true;  // already checked above
-            return isClassAccessible(refc, lookupClass);
-        case PROTECTED:
-            return isSamePackage(defc, lookupClass) || isPublicSuperClass(defc, lookupClass);
-        case PACKAGE_ONLY:
-            return isSamePackage(defc, lookupClass);
-        case PRIVATE:
-            // Loosened rules for privates follows access rules for inner classes.
-            return (ALLOW_NESTMATE_ACCESS &&
-                    isSamePackageMember(defc, lookupClass));
-        default:
-            throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
-        }
-    }
-
-    static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
-        return (refc == lookupClass ||
-                refc.isAssignableFrom(lookupClass) ||
-                lookupClass.isAssignableFrom(refc));
-    }
-
-    static boolean isPublicSuperClass(Class<?> defc, Class<?> lookupClass) {
-        return isPublic(defc.getModifiers()) && defc.isAssignableFrom(lookupClass);
-    }
-
-    /**
-     * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
-     * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
-     * A class or interface C is accessible to a class or interface D
-     * if and only if either of the following conditions are true:<ul>
-     * <li>C is public.
-     * <li>C and D are members of the same runtime package.
-     * </ul>
-     * @param refc the symbolic reference class to which access is being checked (C)
-     * @param lookupClass the class performing the lookup (D)
-     */
-    public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass) {
-        int mods = refc.getModifiers();
-        if (isPublic(mods))
-            return true;
-        if (isSamePackage(lookupClass, refc))
-            return true;
-        return false;
-    }
-
-    /**
-     * Test if two classes have the same class loader and package qualifier.
-     * @param class1
-     * @param class2
-     * @return whether they are in the same package
-     */
-    public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
-        if (class1 == class2)
-            return true;
-        if (!loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
-            return false;
-        String name1 = class1.getName(), name2 = class2.getName();
-        int dot = name1.lastIndexOf('.');
-        if (dot != name2.lastIndexOf('.'))
-            return false;
-        for (int i = 0; i < dot; i++) {
-            if (name1.charAt(i) != name2.charAt(i))
-                return false;
-        }
-        return true;
-    }
-
-    /**
-     * Test if two classes are defined as part of the same package member (top-level class).
-     * If this is true, they can share private access with each other.
-     * @param class1
-     * @param class2
-     * @return whether they are identical or nested together
-     */
-    public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
-        if (class1 == class2)
-            return true;
-        if (!isSamePackage(class1, class2))
-            return false;
-        if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
-            return false;
-        return true;
-    }
-
-    private static Class<?> getOutermostEnclosingClass(Class<?> c) {
-        Class<?> pkgmem = c;
-        for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
-            pkgmem = enc;
-        return pkgmem;
-    }
-
-    private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2) {
-        if (loader1 == loader2 || loader1 == null || loader2 == null) {
-            return true;
-        }
-        for (ClassLoader scan1 = loader1;
-                scan1 != null; scan1 = scan1.getParent()) {
-            if (scan1 == loader2)  return true;
-        }
-        for (ClassLoader scan2 = loader2;
-                scan2 != null; scan2 = scan2.getParent()) {
-            if (scan2 == loader1)  return true;
-        }
-        return false;
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/util/VerifyType.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-import java.dyn.MethodType;
-import sun.dyn.empty.Empty;
-
-/**
- * This class centralizes information about the JVM verifier
- * and its requirements about type correctness.
- * @author jrose
- */
-public class VerifyType {
-
-    private VerifyType() { }  // cannot instantiate
-
-    /**
-     * True if a value can be stacked as the source type and unstacked as the
-     * destination type, without violating the JVM's type consistency.
-     *
-     * @param call the type of a stacked value
-     * @param recv the type by which we'd like to treat it
-     * @return whether the retyping can be done without motion or reformatting
-     */
-    public static boolean isNullConversion(Class<?> src, Class<?> dst) {
-        if (src == dst)            return true;
-        // Verifier allows any interface to be treated as Object:
-        if (dst.isInterface())     dst = Object.class;
-        if (src.isInterface())     src = Object.class;
-        if (src == dst)            return true;  // check again
-        if (dst == void.class)     return true;  // drop any return value
-        if (isNullType(src))       return !dst.isPrimitive();
-        if (!src.isPrimitive())    return dst.isAssignableFrom(src);
-        // Verifier allows an int to carry byte, short, char, or even boolean:
-        if (dst == int.class)      return Wrapper.forPrimitiveType(src).isSubwordOrInt();
-        return false;
-    }
-
-    /**
-     * Specialization of isNullConversion to reference types.
-
-     * @param call the type of a stacked value
-     * @param recv the reference type by which we'd like to treat it
-     * @return whether the retyping can be done without a cast
-     */
-    public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) {
-        assert(!dst.isPrimitive());
-        if (dst.isInterface())  return true;   // verifier allows this
-        if (isNullType(src))    return true;
-        return dst.isAssignableFrom(src);
-    }
-
-    /**
-     * 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
-            // 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;
-    static {
-        Class<?> nullClass = null;
-        try {
-            nullClass = Class.forName("java.lang.Null");
-        } catch (ClassNotFoundException ex) {
-            // OK, we'll cope
-        }
-        NULL_CLASS = nullClass;
-    }
-
-    /**
-     * True if a method handle can receive a call under a slightly different
-     * method type, without moving or reformatting any stack elements.
-     *
-     * @param call the type of call being made
-     * @param recv the type of the method handle receiving the call
-     * @return whether the retyping can be done without motion or reformatting
-     */
-    public static boolean isNullConversion(MethodType call, MethodType recv) {
-        if (call == recv)  return true;
-        int len = call.parameterCount();
-        if (len != recv.parameterCount())  return false;
-        for (int i = 0; i < len; i++)
-            if (!isNullConversion(call.parameterType(i), recv.parameterType(i)))
-                return false;
-        return isNullConversion(recv.returnType(), call.returnType());
-    }
-
-    //TO DO: isRawConversion
-
-    /**
-     * Determine if the JVM verifier allows a value of type call to be
-     * passed to a formal parameter (or return variable) of type recv.
-     * Returns 1 if the verifier allows the types to match without conversion.
-     * Returns -1 if the types can be made to match by a JVM-supported adapter.
-     * Cases supported are:
-     * <ul><li>checkcast
-     * </li><li>conversion between any two integral types (but not floats)
-     * </li><li>unboxing from a wrapper to its corresponding primitive type
-     * </li><li>conversion in either direction between float and double
-     * </li></ul>
-     * (Autoboxing is not supported here; it must be done via Java code.)
-     * Returns 0 otherwise.
-     */
-    public static int canPassUnchecked(Class<?> src, Class<?> dst) {
-        if (src == dst)
-            return 1;
-
-        if (dst.isPrimitive()) {
-            if (dst == void.class)
-                // Return anything to a caller expecting void.
-                // This is a property of the implementation, which links
-                // return values via a register rather than via a stack push.
-                // This makes it possible to ignore cleanly.
-                return 1;
-            if (src == void.class)
-                return 0;  // void-to-something?
-            if (!src.isPrimitive())
-                // Cannot pass a reference to any primitive type (exc. void).
-                return 0;
-            Wrapper sw = Wrapper.forPrimitiveType(src);
-            Wrapper dw = Wrapper.forPrimitiveType(dst);
-            if (sw.isSubwordOrInt() && dw.isSubwordOrInt()) {
-                if (sw.bitWidth() >= dw.bitWidth())
-                    return -1;   // truncation may be required
-                if (!dw.isSigned() && sw.isSigned())
-                    return -1;   // sign elimination may be required
-            }
-            if (src == float.class || dst == float.class) {
-                if (src == double.class || dst == double.class)
-                    return -1;   // floating conversion may be required
-                else
-                    return 0;    // other primitive conversions NYI
-            } else {
-                // all fixed-point conversions are supported
-                return 0;
-            }
-        } else if (src.isPrimitive()) {
-            // Cannot pass a primitive to any reference type.
-            // (Maybe allow null.class?)
-            return 0;
-        }
-
-        // Handle reference types in the rest of the block:
-
-        // The verifier treats interfaces exactly like Object.
-        if (isNullReferenceConversion(src, dst))
-            // pass any reference to object or an arb. interface
-            return 1;
-        // else it's a definite "maybe" (cast is required)
-        return -1;
-    }
-
-    public static int canPassRaw(Class<?> src, Class<?> dst) {
-        if (dst.isPrimitive()) {
-            if (dst == void.class)
-                // As above, return anything to a caller expecting void.
-                return 1;
-            if (src == void.class)
-                // Special permission for raw conversions: allow a void
-                // 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);
-            Wrapper dw = Wrapper.forPrimitiveType(dst);
-            if (sw.stackSlots() == dw.stackSlots())
-                return 1;  // can do a reinterpret-cast on a stacked primitive
-            if (sw.isSubwordOrInt() && dw == Wrapper.VOID)
-                return 1;  // can drop an outgoing int value
-            return 0;
-        } else if (src.isPrimitive()) {
-            return 0;
-        }
-
-        // Both references.
-        if (isNullReferenceConversion(src, dst))
-            return 1;
-        return -1;
-    }
-
-    public static boolean isSpreadArgType(Class<?> spreadArg) {
-        return spreadArg.isArray();
-    }
-    public static Class<?> spreadArgElementType(Class<?> spreadArg, int i) {
-        return spreadArg.getComponentType();
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/util/Wrapper.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,562 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-public enum Wrapper {
-    BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)),
-    // These must be in the order defined for widening primitive conversions in JLS 5.1.2
-    BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, Format.signed(8)),
-    SHORT(Short.class, short.class, 'S', (Short)(short)0, Format.signed(16)),
-    CHAR(Character.class, char.class, 'C', (Character)(char)0, Format.unsigned(16)),
-    INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)),
-    LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)),
-    FLOAT(Float.class, float.class, 'F', (Float)(float)0, Format.floating(32)),
-    DOUBLE(Double.class, double.class, 'D', (Double)(double)0, Format.floating(64)),
-    //NULL(Null.class, null.class, 'N', null, Format.other(1)),
-    OBJECT(Object.class, Object.class, 'L', null, Format.other(1)),
-    // VOID must be the last type, since it is "assignable" from any other type:
-    VOID(Void.class, void.class, 'V', null, Format.other(0)),
-    ;
-
-    private final Class<?> wrapperType;
-    private final Class<?> primitiveType;
-    private final char     basicTypeChar;
-    private final Object   zero;
-    private final int      format;
-    private final String   simpleName;
-
-    private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, int format) {
-        this.wrapperType = wtype;
-        this.primitiveType = ptype;
-        this.basicTypeChar = tchar;
-        this.zero = zero;
-        this.format = format;
-        this.simpleName = wtype.getSimpleName();
-    }
-
-    private static abstract class Format {
-        static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
-        static final int
-                SIGNED   = (-1) << KIND_SHIFT,
-                UNSIGNED = 0    << KIND_SHIFT,
-                FLOATING = 1    << KIND_SHIFT;
-        static final int
-                SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
-                SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
-        static int format(int kind, int size, int slots) {
-            assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
-            assert((size & (size-1)) == 0); // power of two
-            assert((kind == SIGNED)   ? (size > 0) :
-                   (kind == UNSIGNED) ? (size > 0) :
-                   (kind == FLOATING) ? (size == 32 || size == 64)  :
-                   false);
-            assert((slots == 2) ? (size == 64) :
-                   (slots == 1) ? (size <= 32) :
-                   false);
-            return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
-        }
-        static final int
-                INT      = SIGNED   | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
-                SHORT    = SIGNED   | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
-                BOOLEAN  = UNSIGNED | (1  << SIZE_SHIFT) | (1 << SLOT_SHIFT),
-                CHAR     = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
-                FLOAT    = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
-                VOID     = UNSIGNED | (0  << SIZE_SHIFT) | (0 << SLOT_SHIFT),
-                NUM_MASK = (-1) << SIZE_SHIFT;
-        static int signed(int size)   { return format(SIGNED,   size, (size > 32 ? 2 : 1)); }
-        static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); }
-        static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); }
-        static int other(int slots)   { return slots << SLOT_SHIFT; }
-    }
-
-    /// format queries:
-
-    /** How many bits are in the wrapped value?  Returns 0 for OBJECT or VOID. */
-    public int     bitWidth()      { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; }
-    /** How many JVM stack slots occupied by the wrapped value?  Returns 0 for VOID. */
-    public int     stackSlots()    { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; }
-    /** Does the wrapped value occupy a single JVM stack slot? */
-    public boolean isSingleWord()  { return (format & (1 << Format.SLOT_SHIFT)) != 0; }
-    /** Does the wrapped value occupy two JVM stack slots? */
-    public boolean isDoubleWord()  { return (format & (2 << Format.SLOT_SHIFT)) != 0; }
-    /** Is the wrapped type numeric (not void or object)? */
-    public boolean isNumeric()     { return (format & Format.NUM_MASK) != 0; }
-    /** Is the wrapped type a primitive other than float, double, or void? */
-    public boolean isIntegral()    { return isNumeric() && format < Format.FLOAT; }
-    /** Is the wrapped type one of int, boolean, byte, char, or short? */
-    public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); }
-    /* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */
-    public boolean isSigned()      { return format < Format.VOID; }
-    /* Is the wrapped value an unsigned integral type (one of boolean or char)? */
-    public boolean isUnsigned()    { return format >= Format.BOOLEAN && format < Format.FLOAT; }
-    /** Is the wrapped type either float or double? */
-    public boolean isFloating()    { return format >= Format.FLOAT; }
-
-    /** Does the JVM verifier allow a variable of this wrapper's
-     *  primitive type to be assigned from a value of the given wrapper's primitive type?
-     *  Cases:
-     *  <ul>
-     *  <li>unboxing followed by widening primitive conversion
-     *  <li>any type converted to {@code void}
-     *  <li>boxing conversion followed by widening reference conversion to {@code Object}
-     *  <li>conversion of {@code boolean} to any type
-     *  </ul>
-     */
-    public boolean isConvertibleFrom(Wrapper source) {
-        if (this == source)  return true;
-        if (this.compareTo(source) < 0) {
-            // At best, this is a narrowing conversion.
-            return false;
-        }
-        if ((this.format ^ source.format) == (Format.SHORT ^ Format.CHAR)) {
-            assert (this == SHORT && source == CHAR) || (this == CHAR && source == SHORT);
-            return false;
-        }
-        return true;
-    }
-
-    /** Produce a zero value for the given wrapper type.
-     *  This will be a numeric zero for a number or character,
-     *  false for a boolean, and null for a reference or void.
-     *  The common thread is that this is what is contained
-     *  in a default-initialized variable of the given primitive
-     *  type.  (For void, it is what a reflective method returns
-     *  instead of no value at all.)
-     */
-    public Object zero() { return zero; }
-
-    /** Produce a zero value for the given wrapper type T.
-     *  The optional argument must a type compatible with this wrapper.
-     *  Equivalent to {@code this.cast(this.zero(), type)}.
-     */
-    public <T> T zero(Class<T> type) { return convert(zero, type); }
-
-//    /** Produce a wrapper for the given wrapper or primitive type. */
-//    public static Wrapper valueOf(Class<?> type) {
-//        if (isPrimitiveType(type))
-//            return forPrimitiveType(type);
-//        else
-//            return forWrapperType(type);
-//    }
-
-    /** Return the wrapper that wraps values of the given type.
-     *  The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
-     *  Otherwise, the type must be a primitive.
-     *  @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;
-        }
-        return null;
-    }
-
-    /** Return the wrapper that wraps values into the given wrapper type.
-     *  If it is {@code Object} or an interface, return {@code OBJECT}.
-     *  Otherwise, it must be a wrapper type.
-     *  The type must not be a primitive type.
-     *  @throws IllegalArgumentException for unexpected types
-     */
-    public static Wrapper forWrapperType(Class<?> type) {
-        Wrapper w = findWrapperType(type);
-        if (w != null)  return w;
-        for (Wrapper x : values())
-            if (x.wrapperType == type)
-                throw new InternalError(); // redo hash function
-        throw newIllegalArgumentException("not wrapper: "+type);
-    }
-
-    static Wrapper findWrapperType(Class<?> type) {
-        Wrapper w = FROM_WRAP[hashWrap(type)];
-        if (w != null && w.wrapperType == type) {
-            return w;
-        }
-        if (type.isInterface())
-            return OBJECT;
-        return null;
-    }
-
-    /** Return the wrapper that corresponds to the given bytecode
-     *  signature character.  Return {@code OBJECT} for the character 'L'.
-     *  @throws IllegalArgumentException for any non-signature character or {@code '['}.
-     */
-    public static Wrapper forBasicType(char type) {
-        Wrapper w = FROM_CHAR[hashChar(type)];
-        if (w != null && w.basicTypeChar == type) {
-            return w;
-        }
-        for (Wrapper x : values())
-            if (w.basicTypeChar == type)
-                throw new InternalError(); // redo hash function
-        throw newIllegalArgumentException("not basic type char: "+type);
-    }
-
-    /** Return the wrapper for the given type, if it is
-     *  a primitive type, else return {@code OBJECT}.
-     */
-    public static Wrapper forBasicType(Class<?> type) {
-        if (type.isPrimitive())
-            return forPrimitiveType(type);
-        return OBJECT;  // any reference, including wrappers or arrays
-    }
-
-    // Note on perfect hashes:
-    //   for signature chars c, do (c + (c >> 1)) % 16
-    //   for primitive type names n, do (n[0] + n[2]) % 16
-    // The type name hash works for both primitive and wrapper names.
-    // You can add "java/lang/Object" to the primitive names.
-    // But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
-    private static final Wrapper[] FROM_PRIM = new Wrapper[16];
-    private static final Wrapper[] FROM_WRAP = new Wrapper[16];
-    private static final Wrapper[] FROM_CHAR = new Wrapper[16];
-    private static int hashPrim(Class<?> x) {
-        String xn = x.getName();
-        if (xn.length() < 3)  return 0;
-        return (xn.charAt(0) + xn.charAt(2)) % 16;
-    }
-    private static int hashWrap(Class<?> x) {
-        String xn = x.getName();
-        final int offset = 10; assert(offset == "java.lang.".length());
-        if (xn.length() < offset+3)  return 0;
-        return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
-    }
-    private static int hashChar(char x) {
-        return (x + (x >> 1)) % 16;
-    }
-    static {
-        for (Wrapper w : values()) {
-            int pi = hashPrim(w.primitiveType);
-            int wi = hashWrap(w.wrapperType);
-            int ci = hashChar(w.basicTypeChar);
-            assert(FROM_PRIM[pi] == null);
-            assert(FROM_WRAP[wi] == null);
-            assert(FROM_CHAR[ci] == null);
-            FROM_PRIM[pi] = w;
-            FROM_WRAP[wi] = w;
-            FROM_CHAR[ci] = w;
-        }
-        //assert(jdk.sun.dyn.util.WrapperTest.test(false));
-    }
-
-    /** What is the primitive type wrapped by this wrapper? */
-    public Class<?> primitiveType() { return primitiveType; }
-
-    /** What is the wrapper type for this wrapper? */
-    public Class<?> wrapperType() { return wrapperType; }
-
-    /** What is the wrapper type for this wrapper?
-     * 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) {
-        if (exampleType == wrapperType) {
-            return exampleType;
-        } else if (exampleType == primitiveType ||
-                   wrapperType == Object.class ||
-                   exampleType.isInterface()) {
-            return forceType(wrapperType, exampleType);
-        }
-        throw newClassCastException(exampleType, primitiveType);
-    }
-
-    private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) {
-        return new ClassCastException(actual + " is not compatible with " + expected);
-    }
-
-    /** If {@code type} is a primitive type, return the corresponding
-     *  wrapper type, else return {@code type} unchanged.
-     */
-    public static <T> Class<T> asWrapperType(Class<T> type) {
-        if (type.isPrimitive()) {
-            return forPrimitiveType(type).wrapperType(type);
-        }
-        return type;
-    }
-
-    /** If {@code type} is a wrapper type, return the corresponding
-     *  primitive type, else return {@code type} unchanged.
-     */
-    public static <T> Class<T> asPrimitiveType(Class<T> type) {
-        Wrapper w = findWrapperType(type);
-        if (w != null) {
-            return forceType(w.primitiveType(), type);
-        }
-        return type;
-    }
-
-    /** Query:  Is the given type a wrapper, such as {@code Integer} or {@code Void}? */
-    public static boolean isWrapperType(Class<?> type) {
-        return findWrapperType(type) != null;
-    }
-
-    /** Query:  Is the given type a primitive, such as {@code int} or {@code void}? */
-    public static boolean isPrimitiveType(Class<?> type) {
-        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?
-     */
-    public char basicTypeChar() { return basicTypeChar; }
-
-    /** What is the simple name of the wrapper type?
-     */
-    public String simpleName() { return simpleName; }
-
-//    /** Wrap a value in the given type, which may be either a primitive or wrapper type.
-//     *  Performs standard primitive conversions, including truncation and float conversions.
-//     */
-//    public static <T> T wrap(Object x, Class<T> type) {
-//        return Wrapper.valueOf(type).cast(x, type);
-//    }
-
-    /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
-     *  The given target type must be this wrapper's primitive or wrapper type.
-     *  If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
-     *  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
-     *  it must be the wrapper's primitive type.
-     *  Primitive conversions are only performed if the given type is itself a primitive.
-     *  @throws ClassCastException if the given type is not compatible with this wrapper
-     */
-    public <T> T cast(Object x, Class<T> type) {
-        return convert(x, type, true);
-    }
-
-    /** Convert a wrapped value to the given type.
-     *  The given target type must be this wrapper's primitive or wrapper type.
-     *  This is equivalent to {@link #cast}, except that it refuses to perform
-     *  narrowing primitive conversions.
-     */
-    public <T> T convert(Object x, Class<T> type) {
-        return convert(x, type, false);
-    }
-
-    private <T> T convert(Object x, Class<T> type, boolean isCast) {
-        if (this == OBJECT) {
-            // If the target wrapper is OBJECT, just do a reference cast.
-            // If the target type is an interface, perform no runtime check.
-            // (This loophole is safe, and is allowed by the JVM verifier.)
-            // If the target type is a primitive, change it to a wrapper.
-            @SuppressWarnings("unchecked")
-            T result = (T) x;  // unchecked warning is expected here
-            return result;
-        }
-        Class<T> wtype = wrapperType(type);
-        if (wtype.isInstance(x)) {
-            @SuppressWarnings("unchecked")
-            T result = (T) x;  // unchecked warning is expected here
-            return result;
-        }
-        Class<?> sourceType = x.getClass();  // throw NPE if x is null
-        if (!isCast) {
-            Wrapper source = findWrapperType(sourceType);
-            if (source == null || !this.isConvertibleFrom(source)) {
-                throw newClassCastException(wtype, sourceType);
-            }
-        }
-        @SuppressWarnings("unchecked")
-        T result = (T) wrap(x);  // unchecked warning is expected here
-        assert result.getClass() == wtype;
-        return result;
-    }
-
-    /** Cast a reference type to another reference type.
-     * If the target type is an interface, perform no runtime check.
-     * (This loophole is safe, and is allowed by the JVM verifier.)
-     * 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.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;
-    }
-
-    /** Wrap a value in this wrapper's type.
-     * Performs standard primitive conversions, including truncation and float conversions.
-     * Performs returns the unchanged reference for {@code OBJECT}.
-     * Returns null for {@code VOID}.
-     * Returns a zero value for a null input.
-     * @throws ClassCastException if this wrapper is numeric and the operand
-     *                            is not a number, character, boolean, or null
-     */
-    public Object wrap(Object x) {
-        // do non-numeric wrappers first
-        switch (basicTypeChar) {
-            case 'L': return x;
-            case 'V': return null;
-        }
-        Number xn = numberValue(x);
-        switch (basicTypeChar) {
-            case 'I': return Integer.valueOf(xn.intValue());
-            case 'J': return Long.valueOf(xn.longValue());
-            case 'F': return Float.valueOf(xn.floatValue());
-            case 'D': return Double.valueOf(xn.doubleValue());
-            case 'S': return Short.valueOf((short) xn.intValue());
-            case 'B': return Byte.valueOf((byte) xn.intValue());
-            case 'C': return Character.valueOf((char) xn.intValue());
-            case 'Z': return Boolean.valueOf(boolValue(xn.longValue()));
-        }
-        throw new InternalError("bad wrapper");
-    }
-
-    /** Wrap a value (an int or smaller value) in this wrapper's type.
-     * Performs standard primitive conversions, including truncation and float conversions.
-     * Produces an {@code Integer} for {@code OBJECT}, although the exact type
-     * of the operand is not known.
-     * Returns null for {@code VOID}.
-     */
-    public Object wrap(int x) {
-        if (basicTypeChar == 'L')  return (Integer)x;
-        switch (basicTypeChar) {
-            case 'L': throw newIllegalArgumentException("cannot wrap to object type");
-            case 'V': return null;
-            case 'I': return Integer.valueOf((int)x);
-            case 'J': return Long.valueOf(x);
-            case 'F': return Float.valueOf(x);
-            case 'D': return Double.valueOf(x);
-            case 'S': return Short.valueOf((short) x);
-            case 'B': return Byte.valueOf((byte) x);
-            case 'C': return Character.valueOf((char) x);
-            case 'Z': return Boolean.valueOf(boolValue(x));
-        }
-        throw new InternalError("bad wrapper");
-    }
-
-    /** Wrap a value (a long or smaller value) in this wrapper's type.
-     * Does not perform floating point conversion.
-     * Produces a {@code Long} for {@code OBJECT}, although the exact type
-     * of the operand is not known.
-     * Returns null for {@code VOID}.
-     */
-    public Object wrapRaw(long x) {
-        switch (basicTypeChar) {
-            case 'F':  return Float.valueOf(Float.intBitsToFloat((int)x));
-            case 'D':  return Double.valueOf(Double.longBitsToDouble(x));
-            case 'L':  // same as 'J':
-            case 'J':  return (Long) x;
-        }
-        // Other wrapping operations are just the same, given that the
-        // operand is already promoted to an int.
-        return wrap((int)x);
-    }
-
-    /** Produce bitwise value which encodes the given wrapped value.
-     * Does not perform floating point conversion.
-     * Returns zero for {@code VOID}.
-     */
-    public long unwrapRaw(Object x) {
-        switch (basicTypeChar) {
-            case 'F':  return Float.floatToRawIntBits((Float) x);
-            case 'D':  return Double.doubleToRawLongBits((Double) x);
-
-            case 'L': throw newIllegalArgumentException("cannot unwrap from sobject type");
-            case 'V': return 0;
-            case 'I': return (int)(Integer) x;
-            case 'J': return (long)(Long) x;
-            case 'S': return (short)(Short) x;
-            case 'B': return (byte)(Byte) x;
-            case 'C': return (char)(Character) x;
-            case 'Z': return (boolean)(Boolean) x ? 1 : 0;
-        }
-        throw new InternalError("bad wrapper");
-    }
-
-    /** Report what primitive type holds this guy's raw value. */
-    public Class<?> rawPrimitiveType() {
-        return rawPrimitive().primitiveType();
-    }
-
-    /** Report, as a wrapper, what primitive type holds this guy's raw value.
-     *  Returns self for INT, LONG, OBJECT; returns LONG for DOUBLE,
-     *  else returns INT.
-     */
-    public Wrapper rawPrimitive() {
-        switch (basicTypeChar) {
-            case 'S': case 'B':
-            case 'C': case 'Z':
-            case 'V':
-            case 'F':
-                return INT;
-            case 'D':
-                return LONG;
-        }
-        return this;
-    }
-
-    private static Number numberValue(Object x) {
-        if (x instanceof Number)     return (Number)x;
-        if (x instanceof Character)  return (int)(Character)x;
-        if (x instanceof Boolean)    return (Boolean)x ? 1 : 0;
-        // Remaining allowed case of void:  Must be a null reference.
-        return (Number)x;
-    }
-
-    private static boolean boolValue(long bits) {
-        //bits &= 1;  // simple 31-bit zero extension
-        return (bits != 0);
-    }
-
-    private static RuntimeException newIllegalArgumentException(String message, Object x) {
-        return newIllegalArgumentException(message + x);
-    }
-    private static RuntimeException newIllegalArgumentException(String message) {
-        return new IllegalArgumentException(message);
-    }
-}
--- a/jdk/src/share/classes/sun/dyn/util/package-info.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * Extra support for using JSR 292 RI, package java.dyn.
- * @author jrose
- */
-
-package sun.dyn.util;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/WrapperInstance.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke;
+
+import java.lang.invoke.MethodHandle;
+
+/**
+ * Private API used inside of java.lang.invoke.MethodHandles.
+ * Interface implemented by every object which is produced by
+ * {@link java.lang.invoke.MethodHandles#asInstance MethodHandles.asInstance}.
+ * The methods of this interface allow a caller to recover the parameters
+ * to {@code asInstance}.
+ * This allows applications to repeatedly convert between method handles
+ * and SAM objects, without the risk of creating unbounded delegation chains.
+ */
+public interface WrapperInstance {
+    /** Produce or recover a target method handle which is behaviorally
+     *  equivalent to the SAM method of this object.
+     */
+    public MethodHandle getWrapperInstanceTarget();
+    /** Recover the SAM type for which this object was created.
+     */
+    public Class<?> getWrapperInstanceType();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import sun.misc.IOUtils;
+
+/**
+ * Anonymous class loader.  Will load any valid classfile, producing
+ * a {@link Class} metaobject, without installing that class in the
+ * system dictionary.  Therefore, {@link Class#forName(String)} will never
+ * produce a reference to an anonymous class.
+ * <p>
+ * The access permissions of the anonymous class are borrowed from
+ * a <em>host class</em>.  The new class behaves as if it were an
+ * inner class of the host class.  It can access the host's private
+ * members, if the creator of the class loader has permission to
+ * do so (or to create accessible reflective objects).
+ * <p>
+ * When the anonymous class is loaded, elements of its constant pool
+ * can be patched to new values.  This provides a hook to pre-resolve
+ * named classes in the constant pool to other classes, including
+ * anonymous ones.  Also, string constants can be pre-resolved to
+ * any reference.  (The verifier treats non-string, non-class reference
+ * constants as plain objects.)
+ *  <p>
+ * Why include the patching function?  It makes some use cases much easier.
+ * Second, the constant pool needed some internal patching anyway,
+ * to anonymize the loaded class itself.  Finally, if you are going
+ * to use this seriously, you'll want to build anonymous classes
+ * on top of pre-existing anonymous classes, and that requires patching.
+ *
+ * <p>%%% TO-DO:
+ * <ul>
+ * <li>needs better documentation</li>
+ * <li>needs more security work (for safe delegation)</li>
+ * <li>needs a clearer story about error processing</li>
+ * <li>patch member references also (use ';' as delimiter char)</li>
+ * <li>patch method references to (conforming) method handles</li>
+ * </ul>
+ *
+ * @author jrose
+ * @author Remi Forax
+ * @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
+ *      http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
+ */
+
+public class AnonymousClassLoader {
+    final Class<?> hostClass;
+
+    // Note: Do not refactor the calls to checkHostClass unless you
+    //       also adjust this constant:
+    private static int CHC_CALLERS = 3;
+
+    public AnonymousClassLoader() {
+        this.hostClass = checkHostClass(null);
+    }
+    public AnonymousClassLoader(Class<?> hostClass) {
+        this.hostClass = checkHostClass(hostClass);
+    }
+
+    private static Class<?> getTopLevelClass(Class<?> clazz) {
+      for(Class<?> outer = clazz.getDeclaringClass(); outer != null;
+          outer = outer.getDeclaringClass()) {
+        clazz = outer;
+      }
+      return clazz;
+    }
+
+    private static Class<?> checkHostClass(Class<?> hostClass) {
+        // called only from the constructor
+        // does a context-sensitive check on caller class
+        // CC[0..3] = {Reflection, this.checkHostClass, this.<init>, caller}
+        Class<?> caller = sun.reflect.Reflection.getCallerClass(CHC_CALLERS);
+
+        if (caller == null) {
+            // called from the JVM directly
+            if (hostClass == null)
+                return AnonymousClassLoader.class; // anything central will do
+            return hostClass;
+        }
+
+        if (hostClass == null)
+            hostClass = caller; // default value is caller itself
+
+        // anonymous class will access hostClass on behalf of caller
+        Class<?> callee = hostClass;
+
+        if (caller == callee)
+            // caller can always nominate itself to grant caller's own access rights
+            return hostClass;
+
+        // normalize caller and callee to their top-level classes:
+        caller = getTopLevelClass(caller);
+        callee = getTopLevelClass(callee);
+        if (caller == callee)
+            return caller;
+
+        ClassLoader callerCL = caller.getClassLoader();
+        if (callerCL == null) {
+            // caller is trusted code, so accept the proposed hostClass
+            return hostClass;
+        }
+
+        // %%% should do something with doPrivileged, because trusted
+        // code should have a way to execute on behalf of
+        // partially-trusted clients
+
+        // Does the caller have the right to access the private
+        // members of the callee?  If not, raise an error.
+        final int ACC_PRIVATE = 2;
+        try {
+            sun.reflect.Reflection.ensureMemberAccess(caller, callee, null, ACC_PRIVATE);
+        } catch (IllegalAccessException ee) {
+            throw new IllegalArgumentException(ee);
+        }
+
+        return hostClass;
+    }
+
+    public Class<?> loadClass(byte[] classFile) {
+        if (defineAnonymousClass == null) {
+            // no JVM support; try to fake an approximation
+            try {
+                return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
+            } catch (InvalidConstantPoolFormatException ee) {
+                throw new IllegalArgumentException(ee);
+            }
+        }
+        return loadClass(classFile, null);
+    }
+
+    public Class<?> loadClass(ConstantPoolPatch classPatch) {
+        if (defineAnonymousClass == null) {
+            // no JVM support; try to fake an approximation
+            return fakeLoadClass(classPatch);
+        }
+        Object[] patches = classPatch.patchArray;
+        // Convert class names (this late in the game)
+        // to use slash '/' instead of dot '.'.
+        // Java likes dots, but the JVM likes slashes.
+        for (int i = 0; i < patches.length; i++) {
+            Object value = patches[i];
+            if (value != null) {
+                byte tag = classPatch.getTag(i);
+                switch (tag) {
+                case ConstantPoolVisitor.CONSTANT_Class:
+                    if (value instanceof String) {
+                        if (patches == classPatch.patchArray)
+                            patches = patches.clone();
+                        patches[i] = ((String)value).replace('.', '/');
+                    }
+                    break;
+                case ConstantPoolVisitor.CONSTANT_Fieldref:
+                case ConstantPoolVisitor.CONSTANT_Methodref:
+                case ConstantPoolVisitor.CONSTANT_InterfaceMethodref:
+                case ConstantPoolVisitor.CONSTANT_NameAndType:
+                    // When/if the JVM supports these patches,
+                    // we'll probably need to reformat them also.
+                    // Meanwhile, let the class loader create the error.
+                    break;
+                }
+            }
+        }
+        return loadClass(classPatch.outer.classFile, classPatch.patchArray);
+    }
+
+    private Class<?> loadClass(byte[] classFile, Object[] patchArray) {
+        try {
+            return (Class<?>)
+                defineAnonymousClass.invoke(unsafe,
+                                            hostClass, classFile, patchArray);
+        } catch (Exception ex) {
+            throwReflectedException(ex);
+            throw new RuntimeException("error loading into "+hostClass, ex);
+        }
+    }
+
+    private static void throwReflectedException(Exception ex) {
+        if (ex instanceof InvocationTargetException) {
+            Throwable tex = ((InvocationTargetException)ex).getTargetException();
+            if (tex instanceof Error)
+                throw (Error) tex;
+            ex = (Exception) tex;
+        }
+        if (ex instanceof RuntimeException) {
+            throw (RuntimeException) ex;
+        }
+    }
+
+    private Class<?> fakeLoadClass(ConstantPoolPatch classPatch) {
+        // Implementation:
+        // 1. Make up a new name nobody has used yet.
+        // 2. Inspect the tail-header of the class to find the this_class index.
+        // 3. Patch the CONSTANT_Class for this_class to the new name.
+        // 4. Add other CP entries required by (e.g.) string patches.
+        // 5. Flatten Class constants down to their names, making sure that
+        //    the host class loader can pick them up again accurately.
+        // 6. Generate the edited class file bytes.
+        //
+        // Potential limitations:
+        // * The class won't be truly anonymous, and may interfere with others.
+        // * Flattened class constants might not work, because of loader issues.
+        // * Pseudo-string constants will not flatten down to real strings.
+        // * Method handles will (of course) fail to flatten to linkage strings.
+        if (true)  throw new UnsupportedOperationException("NYI");
+        Object[] cpArray;
+        try {
+            cpArray = classPatch.getOriginalCP();
+        } catch (InvalidConstantPoolFormatException ex) {
+            throw new RuntimeException(ex);
+        }
+        int thisClassIndex = classPatch.getParser().getThisClassIndex();
+        String thisClassName = (String) cpArray[thisClassIndex];
+        synchronized (AnonymousClassLoader.class) {
+            thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
+        }
+        classPatch.putUTF8(thisClassIndex, thisClassName);
+        byte[] classFile = null;
+        return unsafe.defineClass(null, classFile, 0, classFile.length,
+                                  hostClass.getClassLoader(),
+                                  hostClass.getProtectionDomain());
+    }
+    private static int fakeNameCounter = 99999;
+
+    // ignore two warnings on this line:
+    static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+    // preceding line requires that this class be on the boot class path
+
+    static private final Method defineAnonymousClass;
+    static {
+        Method dac = null;
+        Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass();
+        try {
+            dac = unsafeClass.getMethod("defineAnonymousClass",
+                                        Class.class,
+                                        byte[].class,
+                                        Object[].class);
+        } catch (Exception ee) {
+            dac = null;
+        }
+        defineAnonymousClass = dac;
+    }
+
+    private static void noJVMSupport() {
+        throw new UnsupportedOperationException("no JVM support for anonymous classes");
+    }
+
+
+    private static native Class<?> loadClassInternal(Class<?> hostClass,
+                                                     byte[] classFile,
+                                                     Object[] patchArray);
+
+    public static byte[] readClassFile(Class<?> templateClass) throws IOException {
+        String templateName = templateClass.getName();
+        int lastDot = templateName.lastIndexOf('.');
+        java.net.URL url = templateClass.getResource(templateName.substring(lastDot+1)+".class");
+        java.net.URLConnection connection = url.openConnection();
+        int contentLength = connection.getContentLength();
+        if (contentLength < 0)
+            throw new IOException("invalid content length "+contentLength);
+
+        return IOUtils.readFully(connection.getInputStream(), contentLength, true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolParser.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+
+import static sun.invoke.anon.ConstantPoolVisitor.*;
+
+/** A constant pool parser.
+ */
+public class ConstantPoolParser {
+    final byte[] classFile;
+    final byte[] tags;
+    final char[] firstHeader;  // maghi, maglo, minor, major, cplen
+
+    // these are filled in on first parse:
+    int endOffset;
+    char[] secondHeader;       // flags, this_class, super_class, intlen
+
+    // used to decode UTF8 array
+    private char[] charArray = new char[80];
+
+    /** Creates a constant pool parser.
+     * @param classFile an array of bytes containing a class.
+     * @throws InvalidConstantPoolFormatException if the header of the class has errors.
+     */
+    public ConstantPoolParser(byte[] classFile) throws InvalidConstantPoolFormatException {
+        this.classFile = classFile;
+        this.firstHeader = parseHeader(classFile);
+        this.tags = new byte[firstHeader[4]];
+    }
+
+    /** Create a constant pool parser by loading the bytecodes of the
+     *  class taken as argument.
+     *
+     * @param templateClass the class to parse.
+     *
+     * @throws IOException raised if an I/O occurs when loading
+     *  the bytecode of the template class.
+     * @throws InvalidConstantPoolFormatException if the header of the class has errors.
+     *
+     * @see #ConstantPoolParser(byte[])
+     * @see AnonymousClassLoader#readClassFile(Class)
+     */
+    public ConstantPoolParser(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
+        this(AnonymousClassLoader.readClassFile(templateClass));
+    }
+
+    /** Creates an empty patch to patch the class file
+     *  used by the current parser.
+     * @return a new class patch.
+     */
+    public ConstantPoolPatch createPatch() {
+        return new ConstantPoolPatch(this);
+    }
+
+    /** Report the tag of the indicated CP entry.
+     * @param index
+     * @return one of {@link ConstantPoolVisitor#CONSTANT_Utf8}, etc.
+     */
+    public byte getTag(int index) {
+        getEndOffset();  // trigger an exception if we haven't parsed yet
+        return tags[index];
+    }
+
+    /** Report the length of the constant pool. */
+    public int getLength() {
+        return firstHeader[4];
+    }
+
+    /** Report the offset, within the class file, of the start of the constant pool. */
+    public int getStartOffset() {
+        return firstHeader.length * 2;
+    }
+
+    /** Report the offset, within the class file, of the end of the constant pool. */
+    public int getEndOffset() {
+        if (endOffset == 0)
+            throw new IllegalStateException("class file has not yet been parsed");
+        return endOffset;
+    }
+
+    /** Report the CP index of this class's own name. */
+    public int getThisClassIndex() {
+        getEndOffset();   // provoke exception if not yet parsed
+        return secondHeader[1];
+    }
+
+    /** Report the total size of the class file. */
+    public int getTailLength() {
+        return classFile.length - getEndOffset();
+    }
+
+    /** Write the head (header plus constant pool)
+     *  of the class file to the indicated stream.
+     */
+    public void writeHead(OutputStream out) throws IOException {
+        out.write(classFile, 0, getEndOffset());
+    }
+
+    /** Write the head (header plus constant pool)
+     *  of the class file to the indicated stream,
+     *  incorporating the non-null entries of the given array
+     *  as patches.
+     */
+    void writePatchedHead(OutputStream out, Object[] patchArray) {
+        // this will be useful to partially emulate the class loader on old JVMs
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    /** Write the tail (everything after the constant pool)
+     *  of the class file to the indicated stream.
+     */
+    public void writeTail(OutputStream out) throws IOException {
+        out.write(classFile, getEndOffset(), getTailLength());
+    }
+
+    private static char[] parseHeader(byte[] classFile) throws InvalidConstantPoolFormatException {
+        char[] result = new char[5];
+        ByteBuffer buffer = ByteBuffer.wrap(classFile);
+        for (int i = 0; i < result.length; i++)
+            result[i] = (char) getUnsignedShort(buffer);
+        int magic = result[0] << 16 | result[1] << 0;
+        if (magic != 0xCAFEBABE)
+            throw new InvalidConstantPoolFormatException("invalid magic number "+magic);
+        // skip major, minor version
+        int len = result[4];
+        if (len < 1)
+            throw new InvalidConstantPoolFormatException("constant pool length < 1");
+        return result;
+    }
+
+    /** Parse the constant pool of the class
+     *  calling a method visit* each time a constant pool entry is parsed.
+     *
+     *  The order of the calls to visit* is not guaranteed to be the same
+     *  than the order of the constant pool entry in the bytecode array.
+     *
+     * @param visitor
+     * @throws InvalidConstantPoolFormatException
+     */
+    public void parse(ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
+        ByteBuffer buffer = ByteBuffer.wrap(classFile);
+        buffer.position(getStartOffset()); //skip header
+
+        Object[] values = new Object[getLength()];
+        try {
+            parseConstantPool(buffer, values, visitor);
+        } catch(BufferUnderflowException e) {
+            throw new InvalidConstantPoolFormatException(e);
+        }
+        if (endOffset == 0) {
+            endOffset = buffer.position();
+            secondHeader = new char[4];
+            for (int i = 0; i < secondHeader.length; i++) {
+                secondHeader[i] = (char) getUnsignedShort(buffer);
+            }
+        }
+        resolveConstantPool(values, visitor);
+    }
+
+    private char[] getCharArray(int utfLength) {
+        if (utfLength <= charArray.length)
+            return charArray;
+        return charArray = new char[utfLength];
+    }
+
+    private void parseConstantPool(ByteBuffer buffer, Object[] values, ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
+        for (int i = 1; i < tags.length; ) {
+            byte tag = (byte) getUnsignedByte(buffer);
+            assert(tags[i] == 0 || tags[i] == tag);
+            tags[i] = tag;
+            switch (tag) {
+                case CONSTANT_Utf8:
+                    int utfLen = getUnsignedShort(buffer);
+                    String value = getUTF8(buffer, utfLen, getCharArray(utfLen));
+                    visitor.visitUTF8(i, CONSTANT_Utf8, value);
+                    tags[i] = tag;
+                    values[i++] = value;
+                    break;
+                case CONSTANT_Integer:
+                    visitor.visitConstantValue(i, tag, buffer.getInt());
+                    i++;
+                    break;
+                case CONSTANT_Float:
+                    visitor.visitConstantValue(i, tag, buffer.getFloat());
+                    i++;
+                    break;
+                case CONSTANT_Long:
+                    visitor.visitConstantValue(i, tag, buffer.getLong());
+                    i+=2;
+                    break;
+                case CONSTANT_Double:
+                    visitor.visitConstantValue(i, tag, buffer.getDouble());
+                    i+=2;
+                    break;
+
+                case CONSTANT_Class:    // fall through:
+                case CONSTANT_String:
+                    tags[i] = tag;
+                    values[i++] = new int[] { getUnsignedShort(buffer) };
+                    break;
+
+                case CONSTANT_Fieldref:           // fall through:
+                case CONSTANT_Methodref:          // fall through:
+                case CONSTANT_InterfaceMethodref: // fall through:
+                case CONSTANT_NameAndType:
+                    tags[i] = tag;
+                    values[i++] = new int[] { getUnsignedShort(buffer), getUnsignedShort(buffer) };
+                    break;
+                default:
+                    throw new AssertionError("invalid constant "+tag);
+            }
+        }
+    }
+
+    private void resolveConstantPool(Object[] values, ConstantPoolVisitor visitor) {
+        // clean out the int[] values, which are temporary
+        for (int beg = 1, end = values.length-1, beg2, end2;
+             beg <= end;
+             beg = beg2, end = end2) {
+             beg2 = end; end2 = beg-1;
+             //System.out.println("CP resolve pass: "+beg+".."+end);
+             for (int i = beg; i <= end; i++) {
+                  Object value = values[i];
+                  if (!(value instanceof int[]))
+                      continue;
+                  int[] array = (int[]) value;
+                  byte tag = tags[i];
+                  switch (tag) {
+                      case CONSTANT_String:
+                          String stringBody = (String) values[array[0]];
+                          visitor.visitConstantString(i, tag, stringBody, array[0]);
+                          values[i] = null;
+                          break;
+                      case CONSTANT_Class: {
+                          String className = (String) values[array[0]];
+                          // use the external form favored by Class.forName:
+                          className = className.replace('/', '.');
+                          visitor.visitConstantString(i, tag, className, array[0]);
+                          values[i] = className;
+                          break;
+                      }
+                      case CONSTANT_NameAndType: {
+                          String memberName = (String) values[array[0]];
+                          String signature  = (String) values[array[1]];
+                          visitor.visitDescriptor(i, tag, memberName, signature,
+                                                  array[0], array[1]);
+                          values[i] = new String[] {memberName, signature};
+                          break;
+                      }
+                      case CONSTANT_Fieldref:           // fall through:
+                      case CONSTANT_Methodref:          // fall through:
+                      case CONSTANT_InterfaceMethodref: {
+                              Object className   = values[array[0]];
+                              Object nameAndType = values[array[1]];
+                              if (!(className instanceof String) ||
+                                  !(nameAndType instanceof String[])) {
+                                   // one more pass is needed
+                                   if (beg2 > i)  beg2 = i;
+                                   if (end2 < i)  end2 = i;
+                                   continue;
+                              }
+                              String[] nameAndTypeArray = (String[]) nameAndType;
+                              visitor.visitMemberRef(i, tag,
+                                  (String)className,
+                                  nameAndTypeArray[0],
+                                  nameAndTypeArray[1],
+                                  array[0], array[1]);
+                              values[i] = null;
+                          }
+                          break;
+                      default:
+                          continue;
+                }
+            }
+        }
+    }
+
+    private static int getUnsignedByte(ByteBuffer buffer) {
+        return buffer.get() & 0xFF;
+    }
+
+    private static int getUnsignedShort(ByteBuffer buffer) {
+        int b1 = getUnsignedByte(buffer);
+        int b2 = getUnsignedByte(buffer);
+        return (b1 << 8) + (b2 << 0);
+    }
+
+    private static String getUTF8(ByteBuffer buffer, int utfLen, char[] charArray) throws InvalidConstantPoolFormatException {
+      int utfLimit = buffer.position() + utfLen;
+      int index = 0;
+      while (buffer.position() < utfLimit) {
+          int c = buffer.get() & 0xff;
+          if (c > 127) {
+              buffer.position(buffer.position() - 1);
+              return getUTF8Extended(buffer, utfLimit, charArray, index);
+          }
+          charArray[index++] = (char)c;
+      }
+      return new String(charArray, 0, index);
+    }
+
+    private static String getUTF8Extended(ByteBuffer buffer, int utfLimit, char[] charArray, int index) throws InvalidConstantPoolFormatException {
+        int c, c2, c3;
+        while (buffer.position() < utfLimit) {
+            c = buffer.get() & 0xff;
+            switch (c >> 4) {
+                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+                    /* 0xxxxxxx*/
+                    charArray[index++] = (char)c;
+                    break;
+                case 12: case 13:
+                    /* 110x xxxx   10xx xxxx*/
+                    c2 = buffer.get();
+                    if ((c2 & 0xC0) != 0x80)
+                        throw new InvalidConstantPoolFormatException(
+                            "malformed input around byte " + buffer.position());
+                     charArray[index++] = (char)(((c  & 0x1F) << 6) |
+                                                  (c2 & 0x3F));
+                    break;
+                case 14:
+                    /* 1110 xxxx  10xx xxxx  10xx xxxx */
+                    c2 = buffer.get();
+                    c3 = buffer.get();
+                    if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80))
+                       throw new InvalidConstantPoolFormatException(
+                          "malformed input around byte " + (buffer.position()));
+                    charArray[index++] = (char)(((c  & 0x0F) << 12) |
+                                                ((c2 & 0x3F) << 6)  |
+                                                ((c3 & 0x3F) << 0));
+                    break;
+                default:
+                    /* 10xx xxxx,  1111 xxxx */
+                    throw new InvalidConstantPoolFormatException(
+                        "malformed input around byte " + buffer.position());
+            }
+        }
+        // The number of chars produced may be less than utflen
+        return new String(charArray, 0, index);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolPatch.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import static sun.invoke.anon.ConstantPoolVisitor.*;
+
+/** A class and its patched constant pool.
+ *
+ *  This class allow to modify (patch) a constant pool
+ *  by changing the value of its entry.
+ *  Entry are referenced using index that can be get
+ *  by parsing the constant pool using
+ *  {@link ConstantPoolParser#parse(ConstantPoolVisitor)}.
+ *
+ * @see ConstantPoolVisitor
+ * @see ConstantPoolParser#createPatch()
+ */
+public class ConstantPoolPatch {
+    final ConstantPoolParser outer;
+    final Object[] patchArray;
+
+    ConstantPoolPatch(ConstantPoolParser outer) {
+        this.outer      = outer;
+        this.patchArray = new Object[outer.getLength()];
+    }
+
+    /** Create a {@link ConstantPoolParser} and
+     *  a {@link ConstantPoolPatch} in one step.
+     *  Equivalent to {@code new ConstantPoolParser(classFile).createPatch()}.
+     *
+     * @param classFile an array of bytes containing a class.
+     * @see #ConstantPoolParser(Class)
+     */
+    public ConstantPoolPatch(byte[] classFile) throws InvalidConstantPoolFormatException {
+        this(new ConstantPoolParser(classFile));
+    }
+
+    /** Create a {@link ConstantPoolParser} and
+     *  a {@link ConstantPoolPatch} in one step.
+     *  Equivalent to {@code new ConstantPoolParser(templateClass).createPatch()}.
+     *
+     * @param templateClass the class to parse.
+     * @see #ConstantPoolParser(Class)
+     */
+    public ConstantPoolPatch(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
+        this(new ConstantPoolParser(templateClass));
+    }
+
+
+    /** Creates a patch from an existing patch.
+     *  All changes are copied from that patch.
+     * @param patch a patch
+     *
+     * @see ConstantPoolParser#createPatch()
+     */
+    public ConstantPoolPatch(ConstantPoolPatch patch) {
+        outer      = patch.outer;
+        patchArray = patch.patchArray.clone();
+    }
+
+    /** Which parser built this patch? */
+    public ConstantPoolParser getParser() {
+        return outer;
+    }
+
+    /** Report the tag at the given index in the constant pool. */
+    public byte getTag(int index) {
+        return outer.getTag(index);
+    }
+
+    /** Report the current patch at the given index of the constant pool.
+     *  Null means no patch will be made.
+     *  To observe the unpatched entry at the given index, use
+     *  {@link #getParser()}{@code .}@link ConstantPoolParser#parse(ConstantPoolVisitor)}
+     */
+    public Object getPatch(int index) {
+        Object value = patchArray[index];
+        if (value == null)  return null;
+        switch (getTag(index)) {
+        case CONSTANT_Fieldref:
+        case CONSTANT_Methodref:
+        case CONSTANT_InterfaceMethodref:
+            if (value instanceof String)
+                value = stripSemis(2, (String) value);
+            break;
+        case CONSTANT_NameAndType:
+            if (value instanceof String)
+                value = stripSemis(1, (String) value);
+            break;
+        }
+        return value;
+    }
+
+    /** Clear all patches. */
+    public void clear() {
+        Arrays.fill(patchArray, null);
+    }
+
+    /** Clear one patch. */
+    public void clear(int index) {
+        patchArray[index] = null;
+    }
+
+    /** Produce the patches as an array. */
+    public Object[] getPatches() {
+        return patchArray.clone();
+    }
+
+    /** Produce the original constant pool as an array. */
+    public Object[] getOriginalCP() throws InvalidConstantPoolFormatException {
+        return getOriginalCP(0, patchArray.length, -1);
+    }
+
+    /** Walk the constant pool, applying patches using the given map.
+     *
+     * @param utf8Map Utf8 strings to modify, if encountered
+     * @param classMap Classes (or their names) to modify, if encountered
+     * @param valueMap Constant values to modify, if encountered
+     * @param deleteUsedEntries if true, delete map entries that are used
+     */
+    public void putPatches(final Map<String,String> utf8Map,
+                           final Map<String,Object> classMap,
+                           final Map<Object,Object> valueMap,
+                           boolean deleteUsedEntries) throws InvalidConstantPoolFormatException {
+        final HashSet<String> usedUtf8Keys;
+        final HashSet<String> usedClassKeys;
+        final HashSet<Object> usedValueKeys;
+        if (deleteUsedEntries) {
+            usedUtf8Keys  = (utf8Map  == null) ? null : new HashSet<String>();
+            usedClassKeys = (classMap == null) ? null : new HashSet<String>();
+            usedValueKeys = (valueMap == null) ? null : new HashSet<Object>();
+        } else {
+            usedUtf8Keys = null;
+            usedClassKeys = null;
+            usedValueKeys = null;
+        }
+
+        outer.parse(new ConstantPoolVisitor() {
+
+            @Override
+            public void visitUTF8(int index, byte tag, String utf8) {
+                putUTF8(index, utf8Map.get(utf8));
+                if (usedUtf8Keys != null)  usedUtf8Keys.add(utf8);
+            }
+
+            @Override
+            public void visitConstantValue(int index, byte tag, Object value) {
+                putConstantValue(index, tag, valueMap.get(value));
+                if (usedValueKeys != null)  usedValueKeys.add(value);
+            }
+
+            @Override
+            public void visitConstantString(int index, byte tag, String name, int nameIndex) {
+                if (tag == CONSTANT_Class) {
+                    putConstantValue(index, tag, classMap.get(name));
+                    if (usedClassKeys != null)  usedClassKeys.add(name);
+                } else {
+                    assert(tag == CONSTANT_String);
+                    visitConstantValue(index, tag, name);
+                }
+            }
+        });
+        if (usedUtf8Keys != null)   utf8Map.keySet().removeAll(usedUtf8Keys);
+        if (usedClassKeys != null)  classMap.keySet().removeAll(usedClassKeys);
+        if (usedValueKeys != null)  valueMap.keySet().removeAll(usedValueKeys);
+    }
+
+    Object[] getOriginalCP(final int startIndex,
+                           final int endIndex,
+                           final int tagMask) throws InvalidConstantPoolFormatException {
+        final Object[] cpArray = new Object[endIndex - startIndex];
+        outer.parse(new ConstantPoolVisitor() {
+
+            void show(int index, byte tag, Object value) {
+                if (index < startIndex || index >= endIndex)  return;
+                if (((1 << tag) & tagMask) == 0)  return;
+                cpArray[index - startIndex] = value;
+            }
+
+            @Override
+            public void visitUTF8(int index, byte tag, String utf8) {
+                show(index, tag, utf8);
+            }
+
+            @Override
+            public void visitConstantValue(int index, byte tag, Object value) {
+                assert(tag != CONSTANT_String);
+                show(index, tag, value);
+            }
+
+            @Override
+            public void visitConstantString(int index, byte tag,
+                                            String value, int j) {
+                show(index, tag, value);
+            }
+
+            @Override
+            public void visitMemberRef(int index, byte tag,
+                    String className, String memberName,
+                    String signature,
+                    int j, int k) {
+                show(index, tag, new String[]{ className, memberName, signature });
+            }
+
+            @Override
+            public void visitDescriptor(int index, byte tag,
+                    String memberName, String signature,
+                    int j, int k) {
+                show(index, tag, new String[]{ memberName, signature });
+            }
+        });
+        return cpArray;
+    }
+
+    /** Write the head (header plus constant pool)
+     *  of the patched class file to the indicated stream.
+     */
+    void writeHead(OutputStream out) throws IOException {
+        outer.writePatchedHead(out, patchArray);
+    }
+
+    /** Write the tail (everything after the constant pool)
+     *  of the patched class file to the indicated stream.
+     */
+    void writeTail(OutputStream out) throws IOException {
+        outer.writeTail(out);
+    }
+
+    private void checkConstantTag(byte tag, Object value) {
+        if (value == null)
+            throw new IllegalArgumentException(
+                    "invalid null constant value");
+        if (classForTag(tag) != value.getClass())
+            throw new IllegalArgumentException(
+                    "invalid constant value"
+                    + (tag == CONSTANT_None ? ""
+                        : " for tag "+tagName(tag))
+                    + " of class "+value.getClass());
+    }
+
+    private void checkTag(int index, byte putTag) {
+        byte tag = outer.tags[index];
+        if (tag != putTag)
+            throw new IllegalArgumentException(
+                "invalid put operation"
+                + " for " + tagName(putTag)
+                + " at index " + index + " found " + tagName(tag));
+    }
+
+    private void checkTagMask(int index, int tagBitMask) {
+        byte tag = outer.tags[index];
+        int tagBit = ((tag & 0x1F) == tag) ? (1 << tag) : 0;
+        if ((tagBit & tagBitMask) == 0)
+            throw new IllegalArgumentException(
+                "invalid put operation"
+                + " at index " + index + " found " + tagName(tag));
+    }
+
+    private static void checkMemberName(String memberName) {
+        if (memberName.indexOf(';') >= 0)
+            throw new IllegalArgumentException("memberName " + memberName + " contains a ';'");
+    }
+
+    /** Set the entry of the constant pool indexed by index to
+     *  a new string.
+     *
+     * @param index an index to a constant pool entry containing a
+     *        {@link ConstantPoolVisitor#CONSTANT_Utf8} value.
+     * @param utf8 a string
+     *
+     * @see ConstantPoolVisitor#visitUTF8(int, byte, String)
+     */
+    public void putUTF8(int index, String utf8) {
+        if (utf8 == null) { clear(index); return; }
+        checkTag(index, CONSTANT_Utf8);
+        patchArray[index] = utf8;
+    }
+
+    /** Set the entry of the constant pool indexed by index to
+     *  a new value, depending on its dynamic type.
+     *
+     * @param index an index to a constant pool entry containing a
+     *        one of the following structures:
+     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
+     *        {@link ConstantPoolVisitor#CONSTANT_Float},
+     *        {@link ConstantPoolVisitor#CONSTANT_Long},
+     *        {@link ConstantPoolVisitor#CONSTANT_Double},
+     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
+     *        {@link ConstantPoolVisitor#CONSTANT_Class}
+     * @param value a boxed int, float, long or double; or a string or class object
+     * @throws IllegalArgumentException if the type of the constant does not
+     *         match the constant pool entry type,
+     *         as reported by {@link #getTag(int)}
+     *
+     * @see #putConstantValue(int, byte, Object)
+     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
+     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
+     */
+    public void putConstantValue(int index, Object value) {
+        if (value == null) { clear(index); return; }
+        byte tag = tagForConstant(value.getClass());
+        checkConstantTag(tag, value);
+        checkTag(index, tag);
+        patchArray[index] = value;
+    }
+
+    /** Set the entry of the constant pool indexed by index to
+     *  a new value.
+     *
+     * @param index an index to a constant pool entry matching the given tag
+     * @param tag one of the following values:
+     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
+     *        {@link ConstantPoolVisitor#CONSTANT_Float},
+     *        {@link ConstantPoolVisitor#CONSTANT_Long},
+     *        {@link ConstantPoolVisitor#CONSTANT_Double},
+     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
+     *        {@link ConstantPoolVisitor#CONSTANT_Class}
+     * @param value a boxed number, string, or class object
+     * @throws IllegalArgumentException if the type of the constant does not
+     *         match the constant pool entry type, or if a class name contains
+     *         '/' or ';'
+     *
+     * @see #putConstantValue(int, Object)
+     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
+     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
+     */
+    public void putConstantValue(int index, byte tag, Object value) {
+        if (value == null) { clear(index); return; }
+        checkTag(index, tag);
+        if (tag == CONSTANT_Class && value instanceof String) {
+            checkClassName((String) value);
+        } else if (tag == CONSTANT_String) {
+            // the JVM accepts any object as a patch for a string
+        } else {
+            // make sure the incoming value is the right type
+            checkConstantTag(tag, value);
+        }
+        checkTag(index, tag);
+        patchArray[index] = value;
+    }
+
+    /** Set the entry of the constant pool indexed by index to
+     *  a new {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
+     *
+     * @param index an index to a constant pool entry containing a
+     *        {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
+     * @param memberName a memberName
+     * @param signature a signature
+     * @throws IllegalArgumentException if memberName contains the character ';'
+     *
+     * @see ConstantPoolVisitor#visitDescriptor(int, byte, String, String, int, int)
+     */
+    public void putDescriptor(int index, String memberName, String signature) {
+        checkTag(index, CONSTANT_NameAndType);
+        checkMemberName(memberName);
+        patchArray[index] = addSemis(memberName, signature);
+    }
+
+    /** Set the entry of the constant pool indexed by index to
+     *  a new {@link ConstantPoolVisitor#CONSTANT_Fieldref},
+     *  {@link ConstantPoolVisitor#CONSTANT_Methodref}, or
+     *  {@link ConstantPoolVisitor#CONSTANT_InterfaceMethodref} value.
+     *
+     * @param index an index to a constant pool entry containing a member reference
+     * @param className a class name
+     * @param memberName a field or method name
+     * @param signature a field or method signature
+     * @throws IllegalArgumentException if memberName contains the character ';'
+     *             or signature is not a correct signature
+     *
+     * @see ConstantPoolVisitor#visitMemberRef(int, byte, String, String, String, int, int)
+     */
+    public void putMemberRef(int index, byte tag,
+                    String className, String memberName, String signature) {
+        checkTagMask(tag, CONSTANT_MemberRef_MASK);
+        checkTag(index, tag);
+        checkClassName(className);
+        checkMemberName(memberName);
+        if (signature.startsWith("(") == (tag == CONSTANT_Fieldref))
+            throw new IllegalArgumentException("bad signature: "+signature);
+        patchArray[index] = addSemis(className, memberName, signature);
+    }
+
+    static private final int CONSTANT_MemberRef_MASK =
+              CONSTANT_Fieldref
+            | CONSTANT_Methodref
+            | CONSTANT_InterfaceMethodref;
+
+    private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
+        = new IdentityHashMap<Class<?>, Byte>();
+    private static final Class[] CONSTANT_VALUE_CLASS = new Class[16];
+    static {
+        Object[][] values = {
+            {Integer.class, CONSTANT_Integer},
+            {Long.class, CONSTANT_Long},
+            {Float.class, CONSTANT_Float},
+            {Double.class, CONSTANT_Double},
+            {String.class, CONSTANT_String},
+            {Class.class, CONSTANT_Class}
+        };
+        for (Object[] value : values) {
+            Class<?> cls = (Class<?>)value[0];
+            Byte     tag = (Byte) value[1];
+            CONSTANT_VALUE_CLASS_TAG.put(cls, tag);
+            CONSTANT_VALUE_CLASS[(byte)tag] = cls;
+        }
+    }
+
+    static Class<?> classForTag(byte tag) {
+        if ((tag & 0xFF) >= CONSTANT_VALUE_CLASS.length)
+            return null;
+        return CONSTANT_VALUE_CLASS[tag];
+    }
+
+    static byte tagForConstant(Class<?> cls) {
+        Byte tag = CONSTANT_VALUE_CLASS_TAG.get(cls);
+        return (tag == null) ? CONSTANT_None : (byte)tag;
+    }
+
+    private static void checkClassName(String className) {
+        if (className.indexOf('/') >= 0 || className.indexOf(';') >= 0)
+            throw new IllegalArgumentException("invalid class name " + className);
+    }
+
+    static String addSemis(String name, String... names) {
+        StringBuilder buf = new StringBuilder(name.length() * 5);
+        buf.append(name);
+        for (String name2 : names) {
+            buf.append(';').append(name2);
+        }
+        String res = buf.toString();
+        assert(stripSemis(names.length, res)[0].equals(name));
+        assert(stripSemis(names.length, res)[1].equals(names[0]));
+        assert(names.length == 1 ||
+               stripSemis(names.length, res)[2].equals(names[1]));
+        return res;
+    }
+
+    static String[] stripSemis(int count, String string) {
+        String[] res = new String[count+1];
+        int pos = 0;
+        for (int i = 0; i < count; i++) {
+            int pos2 = string.indexOf(';', pos);
+            if (pos2 < 0)  pos2 = string.length();  // yuck
+            res[i] = string.substring(pos, pos2);
+            pos = pos2;
+        }
+        res[count] = string.substring(pos);
+        return res;
+    }
+
+    public String toString() {
+        StringBuilder buf = new StringBuilder(this.getClass().getName());
+        buf.append("{");
+        Object[] origCP = null;
+        for (int i = 0; i < patchArray.length; i++) {
+            if (patchArray[i] == null)  continue;
+            if (origCP != null) {
+                buf.append(", ");
+            } else {
+                try {
+                    origCP = getOriginalCP();
+                } catch (InvalidConstantPoolFormatException ee) {
+                    origCP = new Object[0];
+                }
+            }
+            Object orig = (i < origCP.length) ? origCP[i] : "?";
+            buf.append(orig).append("=").append(patchArray[i]);
+        }
+        buf.append("}");
+        return buf.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolVisitor.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+/**
+ * A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
+ * when a constant pool entry is parsed.
+ * <p>
+ * A visit* method is called when a constant pool entry is parsed.
+ * The first argument is always the constant pool index.
+ * The second argument is always the constant pool tag,
+ * even for methods like {@link #visitUTF8(int, byte, String)} which only apply to one tag.
+ * String arguments refer to Utf8 or NameAndType entries declared elsewhere,
+ * and are always accompanied by the indexes of those entries.
+ * <p>
+ * The order of the calls to the visit* methods is not necessarily related
+ * to the order of the entries in the constant pool.
+ * If one entry has a reference to another entry, the latter (lower-level)
+ * entry will be visited first.
+ * <p>
+ * The following table shows the relation between constant pool entry
+ * types and the corresponding visit* methods:
+ *
+ * <table border=1 cellpadding=5 summary="constant pool visitor methods">
+ * <tr><th>Tag(s)</th><th>Method</th></tr>
+ * <tr>
+ *   <td>{@link #CONSTANT_Utf8}</td>
+ *   <td>{@link #visitUTF8(int, byte, String)}</td>
+ * </tr><tr>
+ *   <td>{@link #CONSTANT_Integer}, {@link #CONSTANT_Float},
+ *       {@link #CONSTANT_Long}, {@link #CONSTANT_Double}</td>
+ *   <td>{@link #visitConstantValue(int, byte, Object)}</td>
+ * </tr><tr>
+ *   <td>{@link #CONSTANT_String}, {@link #CONSTANT_Class}</td>
+ *   <td>{@link #visitConstantString(int, byte, String, int)}</td>
+ * </tr><tr>
+ *   <td>{@link #CONSTANT_NameAndType}</td>
+ *   <td>{@link #visitDescriptor(int, byte, String, String, int, int)}</td>
+ * </tr><tr>
+ *   <td>{@link #CONSTANT_Fieldref},
+ *       {@link #CONSTANT_Methodref},
+ *       {@link #CONSTANT_InterfaceMethodref}</td>
+ *   <td>{@link #visitMemberRef(int, byte, String, String, String, int, int)}</td>
+ * </tr>
+ * </table>
+ *
+ * @see ConstantPoolPatch
+ * @author Remi Forax
+ * @author jrose
+ */
+public class ConstantPoolVisitor {
+  /** Called each time an UTF8 constant pool entry is found.
+   * @param index the constant pool index
+   * @param tag always {@link #CONSTANT_Utf8}
+   * @param utf8 string encoded in modified UTF-8 format passed as a {@code String}
+   *
+   * @see ConstantPoolPatch#putUTF8(int, String)
+   */
+  public void visitUTF8(int index, byte tag, String utf8) {
+    // do nothing
+  }
+
+  /** Called for each constant pool entry that encodes an integer,
+   *  a float, a long, or a double.
+   *  Constant strings and classes are not managed by this method but
+   *  by {@link #visitConstantString(int, byte, String, int)}.
+   *
+   * @param index the constant pool index
+   * @param tag one of {@link #CONSTANT_Integer},
+   *            {@link #CONSTANT_Float},
+   *            {@link #CONSTANT_Long},
+   *            or {@link #CONSTANT_Double}
+   * @param value encoded value
+   *
+   * @see ConstantPoolPatch#putConstantValue(int, Object)
+   */
+  public void visitConstantValue(int index, byte tag, Object value) {
+    // do nothing
+  }
+
+  /** Called for each constant pool entry that encodes a string or a class.
+   * @param index the constant pool index
+   * @param tag one of {@link #CONSTANT_String},
+   *            {@link #CONSTANT_Class},
+   * @param name string body or class name (using dot separator)
+   * @param nameIndex the index of the Utf8 string for the name
+   *
+   * @see ConstantPoolPatch#putConstantValue(int, byte, Object)
+   */
+  public void visitConstantString(int index, byte tag,
+                                  String name, int nameIndex) {
+    // do nothing
+  }
+
+  /** Called for each constant pool entry that encodes a name and type.
+   * @param index the constant pool index
+   * @param tag always {@link #CONSTANT_NameAndType}
+   * @param memberName a field or method name
+   * @param signature the member signature
+   * @param memberNameIndex index of the Utf8 string for the member name
+   * @param signatureIndex index of the Utf8 string for the signature
+   *
+   * @see ConstantPoolPatch#putDescriptor(int, String, String)
+   */
+  public void visitDescriptor(int index, byte tag,
+                              String memberName, String signature,
+                              int memberNameIndex, int signatureIndex) {
+    // do nothing
+  }
+
+  /** Called for each constant pool entry that encodes a field or method.
+   * @param index the constant pool index
+   * @param tag one of {@link #CONSTANT_Fieldref},
+   *            or {@link #CONSTANT_Methodref},
+   *            or {@link #CONSTANT_InterfaceMethodref}
+   * @param className the class name (using dot separator)
+   * @param memberName name of the field or method
+   * @param signature the field or method signature
+   * @param classNameIndex index of the Utf8 string for the class name
+   * @param descriptorIndex index of the NameAndType descriptor constant
+   *
+   * @see ConstantPoolPatch#putMemberRef(int, byte, String, String, String)
+   */
+  public void visitMemberRef(int index, byte tag,
+                             String className, String memberName, String signature,
+                             int classNameIndex, int descriptorIndex) {
+    // do nothing
+  }
+
+    public static final byte
+      CONSTANT_None = 0,
+      CONSTANT_Utf8 = 1,
+      //CONSTANT_Unicode = 2,               /* unused */
+      CONSTANT_Integer = 3,
+      CONSTANT_Float = 4,
+      CONSTANT_Long = 5,
+      CONSTANT_Double = 6,
+      CONSTANT_Class = 7,
+      CONSTANT_String = 8,
+      CONSTANT_Fieldref = 9,
+      CONSTANT_Methodref = 10,
+      CONSTANT_InterfaceMethodref = 11,
+      CONSTANT_NameAndType = 12;
+
+    private static String[] TAG_NAMES = {
+        "Empty",
+        "Utf8",
+        null, //"Unicode",
+        "Integer",
+        "Float",
+        "Long",
+        "Double",
+        "Class",
+        "String",
+        "Fieldref",
+        "Methodref",
+        "InterfaceMethodref",
+        "NameAndType"
+    };
+
+    public static String tagName(byte tag) {
+        String name = null;
+        if ((tag & 0xFF) < TAG_NAMES.length)
+            name = TAG_NAMES[tag];
+        if (name == null)
+            name = "Unknown#"+(tag&0xFF);
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/InvalidConstantPoolFormatException.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+/** Exception used when there is an error in the constant pool
+ *  format.
+ */
+public class InvalidConstantPoolFormatException extends Exception {
+    private static final long serialVersionUID=-6103888330523770949L;
+
+    public InvalidConstantPoolFormatException(String message,Throwable cause) {
+        super(message,cause);
+    }
+
+    public InvalidConstantPoolFormatException(String message) {
+        super(message);
+    }
+
+    public InvalidConstantPoolFormatException(Throwable cause) {
+        super(cause);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/empty/Empty.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.empty;
+
+/**
+ * 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.invoke) 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 {
+    private Empty() { throw new InternalError(); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/package-info.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Implementation details for JSR 292 RI, package java.lang.invoke.
+ * @author jrose
+ */
+
+package sun.invoke;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/BytecodeDescriptor.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+import java.lang.invoke.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(';');
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/BytecodeName.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,627 @@
+/*
+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+/**
+ * Utility routines for dealing with bytecode-level names.
+ * Includes universal mangling rules for the JVM.
+ *
+ * <h3>Avoiding Dangerous Characters </h3>
+ *
+ * <p>
+ * The JVM defines a very small set of characters which are illegal
+ * in name spellings.  We will slightly extend and regularize this set
+ * into a group of <cite>dangerous characters</cite>.
+ * These characters will then be replaced, in mangled names, by escape sequences.
+ * In addition, accidental escape sequences must be further escaped.
+ * Finally, a special prefix will be applied if and only if
+ * the mangling would otherwise fail to begin with the escape character.
+ * This happens to cover the corner case of the null string,
+ * and also clearly marks symbols which need demangling.
+ * </p>
+ * <p>
+ * Dangerous characters are the union of all characters forbidden
+ * or otherwise restricted by the JVM specification,
+ * plus their mates, if they are brackets
+ * (<code><big><b>[</b></big></code> and <code><big><b>]</b></big></code>,
+ * <code><big><b>&lt;</b></big></code> and <code><big><b>&gt;</b></big></code>),
+ * plus, arbitrarily, the colon character <code><big><b>:</b></big></code>.
+ * There is no distinction between type, method, and field names.
+ * This makes it easier to convert between mangled names of different
+ * types, since they do not need to be decoded (demangled).
+ * </p>
+ * <p>
+ * The escape character is backslash <code><big><b>\</b></big></code>
+ * (also known as reverse solidus).
+ * This character is, until now, unheard of in bytecode names,
+ * but traditional in the proposed role.
+ *
+ * </p>
+ * <h3> Replacement Characters </h3>
+ *
+ *
+ * <p>
+ * Every escape sequence is two characters
+ * (in fact, two UTF8 bytes) beginning with
+ * the escape character and followed by a
+ * <cite>replacement character</cite>.
+ * (Since the replacement character is never a backslash,
+ * iterated manglings do not double in size.)
+ * </p>
+ * <p>
+ * Each dangerous character has some rough visual similarity
+ * to its corresponding replacement character.
+ * This makes mangled symbols easier to recognize by sight.
+ * </p>
+ * <p>
+ * The dangerous characters are
+ * <code><big><b>/</b></big></code> (forward slash, used to delimit package components),
+ * <code><big><b>.</b></big></code> (dot, also a package delimiter),
+ * <code><big><b>;</b></big></code> (semicolon, used in signatures),
+ * <code><big><b>$</b></big></code> (dollar, used in inner classes and synthetic members),
+ * <code><big><b>&lt;</b></big></code> (left angle),
+ * <code><big><b>&gt;</b></big></code> (right angle),
+ * <code><big><b>[</b></big></code> (left square bracket, used in array types),
+ * <code><big><b>]</b></big></code> (right square bracket, reserved in this scheme for language use),
+ * and <code><big><b>:</b></big></code> (colon, reserved in this scheme for language use).
+ * Their replacements are, respectively,
+ * <code><big><b>|</b></big></code> (vertical bar),
+ * <code><big><b>,</b></big></code> (comma),
+ * <code><big><b>?</b></big></code> (question mark),
+ * <code><big><b>%</b></big></code> (percent),
+ * <code><big><b>^</b></big></code> (caret),
+ * <code><big><b>_</b></big></code> (underscore), and
+ * <code><big><b>{</b></big></code> (left curly bracket),
+ * <code><big><b>}</b></big></code> (right curly bracket),
+ * <code><big><b>!</b></big></code> (exclamation mark).
+ * In addition, the replacement character for the escape character itself is
+ * <code><big><b>-</b></big></code> (hyphen),
+ * and the replacement character for the null prefix is
+ * <code><big><b>=</b></big></code> (equal sign).
+ * </p>
+ * <p>
+ * An escape character <code><big><b>\</b></big></code>
+ * followed by any of these replacement characters
+ * is an escape sequence, and there are no other escape sequences.
+ * An equal sign is only part of an escape sequence
+ * if it is the second character in the whole string, following a backslash.
+ * Two consecutive backslashes do <em>not</em> form an escape sequence.
+ * </p>
+ * <p>
+ * Each escape sequence replaces a so-called <cite>original character</cite>
+ * which is either one of the dangerous characters or the escape character.
+ * A null prefix replaces an initial null string, not a character.
+ * </p>
+ * <p>
+ * All this implies that escape sequences cannot overlap and may be
+ * determined all at once for a whole string.  Note that a spelling
+ * string can contain <cite>accidental escapes</cite>, apparent escape
+ * sequences which must not be interpreted as manglings.
+ * These are disabled by replacing their leading backslash with an
+ * escape sequence (<code><big><b>\-</b></big></code>).  To mangle a string, three logical steps
+ * are required, though they may be carried out in one pass:
+ * </p>
+ * <ol>
+ *   <li>In each accidental escape, replace the backslash with an escape sequence
+ * (<code><big><b>\-</b></big></code>).</li>
+ *   <li>Replace each dangerous character with an escape sequence
+ * (<code><big><b>\|</b></big></code> for <code><big><b>/</b></big></code>, etc.).</li>
+ *   <li>If the first two steps introduced any change, <em>and</em>
+ * if the string does not already begin with a backslash, prepend a null prefix (<code><big><b>\=</b></big></code>).</li>
+ * </ol>
+ *
+ * To demangle a mangled string that begins with an escape,
+ * remove any null prefix, and then replace (in parallel)
+ * each escape sequence by its original character.
+ * <p>Spelling strings which contain accidental
+ * escapes <em>must</em> have them replaced, even if those
+ * strings do not contain dangerous characters.
+ * This restriction means that mangling a string always
+ * requires a scan of the string for escapes.
+ * But then, a scan would be required anyway,
+ * to check for dangerous characters.
+ *
+ * </p>
+ * <h3> Nice Properties </h3>
+ *
+ * <p>
+ * If a bytecode name does not contain any escape sequence,
+ * demangling is a no-op:  The string demangles to itself.
+ * Such a string is called <cite>self-mangling</cite>.
+ * Almost all strings are self-mangling.
+ * In practice, to demangle almost any name &ldquo;found in nature&rdquo;,
+ * simply verify that it does not begin with a backslash.
+ * </p>
+ * <p>
+ * Mangling is a one-to-one function, while demangling
+ * is a many-to-one function.
+ * A mangled string is defined as <cite>validly mangled</cite> if
+ * it is in fact the unique mangling of its spelling string.
+ * Three examples of invalidly mangled strings are <code><big><b>\=foo</b></big></code>,
+ * <code><big><b>\-bar</b></big></code>, and <code><big><b>baz\!</b></big></code>, which demangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and
+ * <code><big><b>baz\!</b></big></code>, but then remangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and <code><big><b>\=baz\-!</b></big></code>.
+ * If a language back-end or runtime is using mangled names,
+ * it should never present an invalidly mangled bytecode
+ * name to the JVM.  If the runtime encounters one,
+ * it should also report an error, since such an occurrence
+ * probably indicates a bug in name encoding which
+ * will lead to errors in linkage.
+ * However, this note does not propose that the JVM verifier
+ * detect invalidly mangled names.
+ * </p>
+ * <p>
+ * As a result of these rules, it is a simple matter to
+ * compute validly mangled substrings and concatenations
+ * of validly mangled strings, and (with a little care)
+ * these correspond to corresponding operations on their
+ * spelling strings.
+ * </p>
+ * <ul>
+ *   <li>Any prefix of a validly mangled string is also validly mangled,
+ * although a null prefix may need to be removed.</li>
+ *   <li>Any suffix of a validly mangled string is also validly mangled,
+ * although a null prefix may need to be added.</li>
+ *   <li>Two validly mangled strings, when concatenated,
+ * are also validly mangled, although any null prefix
+ * must be removed from the second string,
+ * and a trailing backslash on the first string may need escaping,
+ * if it would participate in an accidental escape when followed
+ * by the first character of the second string.</li>
+ * </ul>
+ * <p>If languages that include non-Java symbol spellings use this
+ * mangling convention, they will enjoy the following advantages:
+ * </p>
+ * <ul>
+ *   <li>They can interoperate via symbols they share in common.</li>
+ *   <li>Low-level tools, such as backtrace printers, will have readable displays.</li>
+ *   <li>Future JVM and language extensions can safely use the dangerous characters
+ * for structuring symbols, but will never interfere with valid spellings.</li>
+ *   <li>Runtimes and compilers can use standard libraries for mangling and demangling.</li>
+ *   <li>Occasional transliterations and name composition will be simple and regular,
+ * for classes, methods, and fields.</li>
+ *   <li>Bytecode names will continue to be compact.
+ * When mangled, spellings will at most double in length, either in
+ * UTF8 or UTF16 format, and most will not change at all.</li>
+ * </ul>
+ *
+ *
+ * <h3> Suggestions for Human Readable Presentations </h3>
+ *
+ *
+ * <p>
+ * For human readable displays of symbols,
+ * it will be better to present a string-like quoted
+ * representation of the spelling, because JVM users
+ * are generally familiar with such tokens.
+ * We suggest using single or double quotes before and after
+ * mangled symbols which are not valid Java identifiers,
+ * with quotes, backslashes, and non-printing characters
+ * escaped as if for literals in the Java language.
+ * </p>
+ * <p>
+ * For example, an HTML-like spelling
+ * <code><big><b>&lt;pre&gt;</b></big></code> mangles to
+ * <code><big><b>\^pre\_</b></big></code> and could
+ * display more cleanly as
+ * <code><big><b>'&lt;pre&gt;'</b></big></code>,
+ * with the quotes included.
+ * Such string-like conventions are <em>not</em> suitable
+ * for mangled bytecode names, in part because
+ * dangerous characters must be eliminated, rather
+ * than just quoted.  Otherwise internally structured
+ * strings like package prefixes and method signatures
+ * could not be reliably parsed.
+ * </p>
+ * <p>
+ * In such human-readable displays, invalidly mangled
+ * names should <em>not</em> be demangled and quoted,
+ * for this would be misleading.  Likewise, JVM symbols
+ * which contain dangerous characters (like dots in field
+ * names or brackets in method names) should not be
+ * simply quoted.  The bytecode names
+ * <code><big><b>\=phase\,1</b></big></code> and
+ * <code><big><b>phase.1</b></big></code> are distinct,
+ * and in demangled displays they should be presented as
+ * <code><big><b>'phase.1'</b></big></code> and something like
+ * <code><big><b>'phase'.1</b></big></code>, respectively.
+ * </p>
+ *
+ * @author John Rose
+ * @version 1.2, 02/06/2008
+ * @see http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm
+ */
+public class BytecodeName {
+    private BytecodeName() { }  // static only class
+
+    /** Given a source name, produce the corresponding bytecode name.
+     * The source name should not be qualified, because any syntactic
+     * markers (dots, slashes, dollar signs, colons, etc.) will be mangled.
+     * @param s the source name
+     * @return a valid bytecode name which represents the source name
+     */
+    public static String toBytecodeName(String s) {
+        String bn = mangle(s);
+        assert((Object)bn == s || looksMangled(bn)) : bn;
+        assert(s.equals(toSourceName(bn))) : s;
+        return bn;
+    }
+
+    /** Given an unqualified bytecode name, produce the corresponding source name.
+     * The bytecode name must not contain dangerous characters.
+     * In particular, it must not be qualified or segmented by colon {@code ':'}.
+     * @param s the bytecode name
+     * @return the source name, which may possibly have unsafe characters
+     * @throws IllegalArgumentException if the bytecode name is not {@link #isSafeBytecodeName safe}
+     * @see #isSafeBytecodeName(java.lang.String)
+     */
+    public static String toSourceName(String s) {
+        checkSafeBytecodeName(s);
+        String sn = s;
+        if (looksMangled(s)) {
+            sn = demangle(s);
+            assert(s.equals(mangle(sn))) : s+" => "+sn+" => "+mangle(sn);
+        }
+        return sn;
+    }
+
+    /**
+     * Given a bytecode name from a classfile, separate it into
+     * components delimited by dangerous characters.
+     * Each resulting array element will be either a dangerous character,
+     * or else a safe bytecode name.
+     * (The safe name might possibly be mangled to hide further dangerous characters.)
+     * For example, the qualified class name {@code java/lang/String}
+     * will be parsed into the array {@code {"java", '/', "lang", '/', "String"}}.
+     * 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();
+        Object[] res = null;
+        for (int pass = 0; pass <= 1; pass++) {
+            int fillp = 0;
+            int lasti = 0;
+            for (int i = 0; i <= slen; i++) {
+                int whichDC = -1;
+                if (i < slen) {
+                    whichDC = DANGEROUS_CHARS.indexOf(s.charAt(i));
+                    if (whichDC < DANGEROUS_CHAR_FIRST_INDEX)  continue;
+                }
+                // got to end of string or next dangerous char
+                if (lasti < i) {
+                    // normal component
+                    if (pass != 0)
+                        res[fillp] = toSourceName(s.substring(lasti, i));
+                    fillp++;
+                    lasti = i+1;
+                }
+                if (whichDC >= DANGEROUS_CHAR_FIRST_INDEX) {
+                    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 Object[fillp];
+            if (fillp <= 1 && lasti == 0) {
+                if (fillp != 0)  res[0] = toSourceName(s);
+                break;
+            }
+        }
+        return res;
+    }
+
+    /**
+     * Given a series of components, create a bytecode name for a classfile.
+     * This is the inverse of {@link #parseBytecodeName(java.lang.String)}.
+     * Each component must either be an interned one-character string of
+     * a dangerous character, or else a safe bytecode name.
+     * @param components a series of name components
+     * @return the concatenation of all components
+     * @throws IllegalArgumentException if any component contains an unsafe
+     *          character, and is not an interned one-character string
+     * @throws NullPointerException if any component is null
+     */
+    public static String unparseBytecodeName(Object[] components) {
+        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);
+    }
+    private static String appendAll(Object[] components) {
+        if (components.length <= 1) {
+            if (components.length == 1) {
+                return String.valueOf(components[0]);
+            }
+            return "";
+        }
+        int slen = 0;
+        for (Object c : components) {
+            if (c instanceof String)
+                slen += String.valueOf(c).length();
+            else
+                slen += 1;
+        }
+        StringBuilder sb = new StringBuilder(slen);
+        for (Object c : components) {
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Given a bytecode name, produce the corresponding display name.
+     * This is the source name, plus quotes if needed.
+     * 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
+     */
+    public static String toDisplayName(String s) {
+        Object[] components = parseBytecodeName(s);
+        for (int i = 0; i < components.length; i++) {
+            if (!(components[i] instanceof String))
+                continue;
+            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);
+            }
+        }
+        return appendAll(components);
+    }
+    private static boolean isJavaIdent(String s) {
+        int slen = s.length();
+        if (slen == 0)  return false;
+        if (!Character.isJavaIdentifierStart(s.charAt(0)))
+            return false;
+        for (int i = 1; i < slen; i++) {
+            if (!Character.isJavaIdentifierPart(s.charAt(i)))
+                return false;
+        }
+        return true;
+    }
+    private static String quoteDisplay(String s) {
+        // TO DO:  Replace wierd characters in s by C-style escapes.
+        return "'"+s.replaceAll("['\\\\]", "\\\\$0")+"'";
+    }
+
+    private static void checkSafeBytecodeName(String s)
+            throws IllegalArgumentException {
+        if (!isSafeBytecodeName(s)) {
+            throw new IllegalArgumentException(s);
+        }
+    }
+
+    /**
+     * Report whether a simple name is safe as a bytecode name.
+     * Such names are acceptable in class files as class, method, and field names.
+     * Additionally, they are free of "dangerous" characters, even if those
+     * characters are legal in some (or all) names in class files.
+     * @param s the proposed bytecode name
+     * @return true if the name is non-empty and all of its characters are safe
+     */
+    public static boolean isSafeBytecodeName(String s) {
+        if (s.length() == 0)  return false;
+        // check occurrences of each DANGEROUS char
+        for (char xc : DANGEROUS_CHARS_A) {
+            if (xc == ESCAPE_C)  continue;  // not really that dangerous
+            if (s.indexOf(xc) >= 0)  return false;
+        }
+        return true;
+    }
+
+    /**
+     * Report whether a character is safe in a bytecode name.
+     * This is true of any unicode character except the following
+     * <em>dangerous characters</em>: {@code ".;:$[]<>/"}.
+     * @param s the proposed character
+     * @return true if the character is safe to use in classfiles
+     */
+    public static boolean isSafeBytecodeChar(char c) {
+        return DANGEROUS_CHARS.indexOf(c) < DANGEROUS_CHAR_FIRST_INDEX;
+    }
+
+    private static boolean looksMangled(String s) {
+        return s.charAt(0) == ESCAPE_C;
+    }
+
+    private static String mangle(String s) {
+        if (s.length() == 0)
+            return NULL_ESCAPE;
+
+        // build this lazily, when we first need an escape:
+        StringBuilder sb = null;
+
+        for (int i = 0, slen = s.length(); i < slen; i++) {
+            char c = s.charAt(i);
+
+            boolean needEscape = false;
+            if (c == ESCAPE_C) {
+                if (i+1 < slen) {
+                    char c1 = s.charAt(i+1);
+                    if ((i == 0 && c1 == NULL_ESCAPE_C)
+                        || c1 != originalOfReplacement(c1)) {
+                        // an accidental escape
+                        needEscape = true;
+                    }
+                }
+            } else {
+                needEscape = isDangerous(c);
+            }
+
+            if (!needEscape) {
+                if (sb != null)  sb.append(c);
+                continue;
+            }
+
+            // build sb if this is the first escape
+            if (sb == null) {
+                sb = new StringBuilder(s.length()+10);
+                // mangled names must begin with a backslash:
+                if (s.charAt(0) != ESCAPE_C && i > 0)
+                    sb.append(NULL_ESCAPE);
+                // append the string so far, which is unremarkable:
+                sb.append(s.substring(0, i));
+            }
+
+            // rewrite \ to \-, / to \|, etc.
+            sb.append(ESCAPE_C);
+            sb.append(replacementOf(c));
+        }
+
+        if (sb != null)   return sb.toString();
+
+        return s;
+    }
+
+    private static String demangle(String s) {
+        // build this lazily, when we first meet an escape:
+        StringBuilder sb = null;
+
+        int stringStart = 0;
+        if (s.startsWith(NULL_ESCAPE))
+            stringStart = 2;
+
+        for (int i = stringStart, slen = s.length(); i < slen; i++) {
+            char c = s.charAt(i);
+
+            if (c == ESCAPE_C && i+1 < slen) {
+                // might be an escape sequence
+                char rc = s.charAt(i+1);
+                char oc = originalOfReplacement(rc);
+                if (oc != rc) {
+                    // build sb if this is the first escape
+                    if (sb == null) {
+                        sb = new StringBuilder(s.length());
+                        // append the string so far, which is unremarkable:
+                        sb.append(s.substring(stringStart, i));
+                    }
+                    ++i;  // skip both characters
+                    c = oc;
+                }
+            }
+
+            if (sb != null)
+                sb.append(c);
+        }
+
+        if (sb != null)   return sb.toString();
+
+        return s.substring(stringStart);
+    }
+
+    static char ESCAPE_C = '\\';
+    // empty escape sequence to avoid a null name or illegal prefix
+    static char NULL_ESCAPE_C = '=';
+    static String NULL_ESCAPE = ESCAPE_C+""+NULL_ESCAPE_C;
+
+    static final String DANGEROUS_CHARS   = "\\/.;:$[]<>"; // \\ must be first
+    static final String REPLACEMENT_CHARS =  "-|,?!%{}^_";
+    static final int DANGEROUS_CHAR_FIRST_INDEX = 1; // index after \\
+    static char[] DANGEROUS_CHARS_A   = DANGEROUS_CHARS.toCharArray();
+    static char[] REPLACEMENT_CHARS_A = REPLACEMENT_CHARS.toCharArray();
+    static final Character[] DANGEROUS_CHARS_CA;
+    static {
+        Character[] dcca = new Character[DANGEROUS_CHARS.length()];
+        for (int i = 0; i < dcca.length; i++)
+            dcca[i] = Character.valueOf(DANGEROUS_CHARS.charAt(i));
+        DANGEROUS_CHARS_CA = dcca;
+    }
+
+    static final long[] SPECIAL_BITMAP = new long[2];  // 128 bits
+    static {
+        String SPECIAL = DANGEROUS_CHARS + REPLACEMENT_CHARS;
+        //System.out.println("SPECIAL = "+SPECIAL);
+        for (char c : SPECIAL.toCharArray()) {
+            SPECIAL_BITMAP[c >>> 6] |= 1L << c;
+        }
+    }
+    static boolean isSpecial(char c) {
+        if ((c >>> 6) < SPECIAL_BITMAP.length)
+            return ((SPECIAL_BITMAP[c >>> 6] >> c) & 1) != 0;
+        else
+            return false;
+    }
+    static char replacementOf(char c) {
+        if (!isSpecial(c))  return c;
+        int i = DANGEROUS_CHARS.indexOf(c);
+        if (i < 0)  return c;
+        return REPLACEMENT_CHARS.charAt(i);
+    }
+    static char originalOfReplacement(char c) {
+        if (!isSpecial(c))  return c;
+        int i = REPLACEMENT_CHARS.indexOf(c);
+        if (i < 0)  return c;
+        return DANGEROUS_CHARS.charAt(i);
+    }
+    static boolean isDangerous(char c) {
+        if (!isSpecial(c))  return false;
+        return (DANGEROUS_CHARS.indexOf(c) >= DANGEROUS_CHAR_FIRST_INDEX);
+    }
+    static int indexOfDangerousChar(String s, int from) {
+        for (int i = from, slen = s.length(); i < slen; i++) {
+            if (isDangerous(s.charAt(i)))
+                return i;
+        }
+        return -1;
+    }
+    static int lastIndexOfDangerousChar(String s, int from) {
+        for (int i = Math.min(from, s.length()-1); i >= 0; i--) {
+            if (isDangerous(s.charAt(i)))
+                return i;
+        }
+        return -1;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,817 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.List;
+
+public class ValueConversions {
+    private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
+
+    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++)
+            caches[i] = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
+        return caches;
+    }
+
+    /// Converting references to values.
+
+    static int unboxInteger(Object x) {
+        if (x == null)  return 0;  // never NPE
+        return ((Integer) x).intValue();
+    }
+
+    static byte unboxByte(Object x) {
+        if (x == null)  return 0;  // never NPE
+        return ((Byte) x).byteValue();
+    }
+
+    static short unboxShort(Object x) {
+        if (x == null)  return 0;  // never NPE
+        return ((Short) x).shortValue();
+    }
+
+    static boolean unboxBoolean(Object x) {
+        if (x == null)  return false;  // never NPE
+        return ((Boolean) x).booleanValue();
+    }
+
+    static char unboxCharacter(Object x) {
+        if (x == null)  return 0;  // never NPE
+        return ((Character) x).charValue();
+    }
+
+    static long unboxLong(Object x) {
+        if (x == null)  return 0;  // never NPE
+        return ((Long) x).longValue();
+    }
+
+    static float unboxFloat(Object x) {
+        if (x == null)  return 0;  // never NPE
+        return ((Float) x).floatValue();
+    }
+
+    static double unboxDouble(Object x) {
+        if (x == null)  return 0;  // never NPE
+        return ((Double) x).doubleValue();
+    }
+
+    /// Converting references to "raw" values.
+    /// A raw primitive value is always an int or long.
+
+    static int unboxByteRaw(Object x) {
+        return unboxByte(x);
+    }
+
+    static int unboxShortRaw(Object x) {
+        return unboxShort(x);
+    }
+
+    static int unboxBooleanRaw(Object x) {
+        return unboxBoolean(x) ? 1 : 0;
+    }
+
+    static int unboxCharacterRaw(Object x) {
+        return unboxCharacter(x);
+    }
+
+    static int unboxFloatRaw(Object x) {
+        return Float.floatToIntBits(unboxFloat(x));
+    }
+
+    static long unboxDoubleRaw(Object x) {
+        return Double.doubleToRawLongBits(unboxDouble(x));
+    }
+
+    private static MethodType unboxType(Wrapper wrap, boolean raw) {
+        return MethodType.methodType(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType());
+    }
+
+    private static final EnumMap<Wrapper, MethodHandle>[]
+            UNBOX_CONVERSIONS = newWrapperCaches(4);
+
+    private static MethodHandle unbox(Wrapper wrap, boolean exact, boolean raw) {
+        EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
+        MethodHandle mh = cache.get(wrap);
+        if (mh != null) {
+            return mh;
+        }
+        // slow path
+        switch (wrap) {
+            case OBJECT:
+                mh = IDENTITY; break;
+            case VOID:
+                mh = raw ? ALWAYS_ZERO : IGNORE; break;
+            case INT: case LONG:
+                // these guys don't need separate raw channels
+                if (raw)  mh = unbox(wrap, exact, false);
+                break;
+        }
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+        // look up the method
+        String name = "unbox" + wrap.simpleName() + (raw ? "Raw" : "");
+        MethodType type = unboxType(wrap, raw);
+        if (!exact) {
+            try {
+                // actually, type is wrong; the Java method takes Object
+                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase());
+            } catch (ReflectiveOperationException ex) {
+                mh = null;
+            }
+        } else {
+            mh = unbox(wrap, !exact, raw).asType(type);
+        }
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+        throw new IllegalArgumentException("cannot find unbox adapter for " + wrap + (raw ? " (raw)" : ""));
+    }
+
+    public static MethodHandle unbox(Wrapper type, boolean exact) {
+        return unbox(type, exact, false);
+    }
+
+    public static MethodHandle unboxRaw(Wrapper type, boolean exact) {
+        return unbox(type, exact, true);
+    }
+
+    public static MethodHandle unbox(Class<?> type, boolean exact) {
+        return unbox(Wrapper.forPrimitiveType(type), exact, false);
+    }
+
+    public static MethodHandle unboxRaw(Class<?> type, boolean exact) {
+        return unbox(Wrapper.forPrimitiveType(type), exact, true);
+    }
+
+    /// Converting primitives to references
+
+    static Integer boxInteger(int x) {
+        return x;
+    }
+
+    static Byte boxByte(byte x) {
+        return x;
+    }
+
+    static Short boxShort(short x) {
+        return x;
+    }
+
+    static Boolean boxBoolean(boolean x) {
+        return x;
+    }
+
+    static Character boxCharacter(char x) {
+        return x;
+    }
+
+    static Long boxLong(long x) {
+        return x;
+    }
+
+    static Float boxFloat(float x) {
+        return x;
+    }
+
+    static Double boxDouble(double x) {
+        return x;
+    }
+
+    /// Converting raw primitives to references
+
+    static Byte boxByteRaw(int x) {
+        return boxByte((byte)x);
+    }
+
+    static Short boxShortRaw(int x) {
+        return boxShort((short)x);
+    }
+
+    static Boolean boxBooleanRaw(int x) {
+        return boxBoolean(x != 0);
+    }
+
+    static Character boxCharacterRaw(int x) {
+        return boxCharacter((char)x);
+    }
+
+    static Float boxFloatRaw(int x) {
+        return boxFloat(Float.intBitsToFloat(x));
+    }
+
+    static Double boxDoubleRaw(long x) {
+        return boxDouble(Double.longBitsToDouble(x));
+    }
+
+    // a raw void value is (arbitrarily) a garbage int
+    static Void boxVoidRaw(int x) {
+        return null;
+    }
+
+    private static MethodType boxType(Wrapper wrap, boolean raw) {
+        // be exact, since return casts are hard to compose
+        Class<?> boxType = wrap.wrapperType();
+        return MethodType.methodType(boxType, rawWrapper(wrap, raw).primitiveType());
+    }
+
+    private static Wrapper rawWrapper(Wrapper wrap, boolean raw) {
+        if (raw)  return wrap.isDoubleWord() ? Wrapper.LONG : Wrapper.INT;
+        return wrap;
+    }
+
+    private static final EnumMap<Wrapper, MethodHandle>[]
+            BOX_CONVERSIONS = newWrapperCaches(4);
+
+    private static MethodHandle box(Wrapper wrap, boolean exact, boolean raw) {
+        EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
+        MethodHandle mh = cache.get(wrap);
+        if (mh != null) {
+            return mh;
+        }
+        // slow path
+        switch (wrap) {
+            case OBJECT:
+                mh = IDENTITY; break;
+            case VOID:
+                if (!raw)  mh = ZERO_OBJECT;
+                break;
+            case INT: case LONG:
+                // these guys don't need separate raw channels
+                if (raw)  mh = box(wrap, exact, false);
+                break;
+        }
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+        // look up the method
+        String name = "box" + wrap.simpleName() + (raw ? "Raw" : "");
+        MethodType type = boxType(wrap, raw);
+        if (exact) {
+            try {
+                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
+            } catch (ReflectiveOperationException ex) {
+                mh = null;
+            }
+        } else {
+            mh = box(wrap, !exact, raw).asType(type.erase());
+        }
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+        throw new IllegalArgumentException("cannot find box adapter for " + wrap + (raw ? " (raw)" : ""));
+    }
+
+    public static MethodHandle box(Class<?> type, boolean exact) {
+        return box(Wrapper.forPrimitiveType(type), exact, false);
+    }
+
+    public static MethodHandle boxRaw(Class<?> type, boolean exact) {
+        return box(Wrapper.forPrimitiveType(type), exact, true);
+    }
+
+    public static MethodHandle box(Wrapper type, boolean exact) {
+        return box(type, exact, false);
+    }
+
+    public static MethodHandle boxRaw(Wrapper type, boolean exact) {
+        return box(type, exact, true);
+    }
+
+    /// 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(unboxRawInteger(x));
+    }
+
+    static Short reboxRawShort(Object x) {
+        if (x instanceof Short)  return (Short) x;
+        return boxShortRaw(unboxRawInteger(x));
+    }
+
+    static Boolean reboxRawBoolean(Object x) {
+        if (x instanceof Boolean)  return (Boolean) x;
+        return boxBooleanRaw(unboxRawInteger(x));
+    }
+
+    static Character reboxRawCharacter(Object x) {
+        if (x instanceof Character)  return (Character) x;
+        return boxCharacterRaw(unboxRawInteger(x));
+    }
+
+    static Float reboxRawFloat(Object x) {
+        if (x instanceof Float)  return (Float) x;
+        return boxFloatRaw(unboxRawInteger(x));
+    }
+
+    static Long reboxRawLong(Object x) {
+        return (Long) x;  //never a rebox
+    }
+
+    static Double reboxRawDouble(Object x) {
+        if (x instanceof Double)  return (Double) x;
+        return boxDoubleRaw(unboxLong(x));
+    }
+
+    private static MethodType reboxType(Wrapper wrap) {
+        Class<?> boxType = wrap.wrapperType();
+        return MethodType.methodType(boxType, Object.class);
+    }
+
+    private static final EnumMap<Wrapper, MethodHandle>[]
+            REBOX_CONVERSIONS = newWrapperCaches(2);
+
+    /**
+     * Because 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);
+        if (mh != null) {
+            return mh;
+        }
+        // slow path
+        switch (wrap) {
+            case OBJECT:
+                mh = IDENTITY; break;
+            case VOID:
+                throw new IllegalArgumentException("cannot rebox a void");
+        }
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+        // look up the method
+        String name = "reboxRaw" + wrap.simpleName();
+        MethodType type = reboxType(wrap);
+        if (exact) {
+            try {
+                mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
+            } catch (ReflectiveOperationException ex) {
+                mh = null;
+            }
+        } else {
+            mh = rebox(wrap, !exact).asType(IDENTITY.type());
+        }
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+        throw new IllegalArgumentException("cannot find rebox adapter for " + wrap);
+    }
+
+    public static MethodHandle rebox(Class<?> type, boolean exact) {
+        return rebox(Wrapper.forPrimitiveType(type), exact);
+    }
+
+    /// Width-changing conversions between int and long.
+
+    static long widenInt(int 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) {
+        // no value to return; this is an unbox of null
+        return;
+    }
+
+    static void empty() {
+        return;
+    }
+
+    static Object zeroObject() {
+        return null;
+    }
+
+    static int zeroInteger() {
+        return 0;
+    }
+
+    static long zeroLong() {
+        return 0;
+    }
+
+    static float zeroFloat() {
+        return 0;
+    }
+
+    static double zeroDouble() {
+        return 0;
+    }
+
+    private static final EnumMap<Wrapper, MethodHandle>[]
+            CONSTANT_FUNCTIONS = newWrapperCaches(2);
+
+    public static MethodHandle zeroConstantFunction(Wrapper wrap) {
+        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
+        MethodHandle mh = cache.get(wrap);
+        if (mh != null) {
+            return mh;
+        }
+        // slow path
+        MethodType type = MethodType.methodType(wrap.primitiveType());
+        switch (wrap) {
+            case VOID:
+                mh = EMPTY;
+                break;
+            case INT: case LONG: case FLOAT: case DOUBLE:
+                try {
+                    mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type);
+                } catch (ReflectiveOperationException ex) {
+                    mh = null;
+                }
+                break;
+        }
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+
+        // use the raw method
+        Wrapper rawWrap = wrap.rawPrimitive();
+        if (mh == null && rawWrap != wrap) {
+            mh = MethodHandles.explicitCastArguments(zeroConstantFunction(rawWrap), type);
+        }
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+        throw new IllegalArgumentException("cannot find zero constant for " + wrap);
+    }
+
+    /// Converting references to references.
+
+    /**
+     * Value-killing function.
+     * @param x an arbitrary reference value
+     * @return a null
+     */
+    static Object alwaysNull(Object x) {
+        return null;
+    }
+
+    /**
+     * Value-killing function.
+     * @param x an arbitrary reference value
+     * @return a zero
+     */
+    static int alwaysZero(Object x) {
+        return 0;
+    }
+
+    /**
+     * Identity function.
+     * @param x an arbitrary reference value
+     * @return the same value x
+     */
+    static <T> T identity(T x) {
+        return x;
+    }
+
+    /**
+     * Identity function on ints.
+     * @param x an arbitrary int value
+     * @return the same value x
+     */
+    static int identity(int x) {
+        return x;
+    }
+
+    static byte identity(byte x) {
+        return x;
+    }
+
+    static short identity(short x) {
+        return x;
+    }
+
+    static boolean identity(boolean x) {
+        return x;
+    }
+
+    static char identity(char x) {
+        return x;
+    }
+
+    /**
+     * Identity function on longs.
+     * @param x an arbitrary long value
+     * @return the same value x
+     */
+    static long identity(long x) {
+        return x;
+    }
+
+    static float identity(float x) {
+        return x;
+    }
+
+    static double identity(double x) {
+        return x;
+    }
+
+    /**
+     * Identity function, with reference cast.
+     * @param t an arbitrary reference type
+     * @param x an arbitrary reference value
+     * @return the same value x
+     */
+    static <T,U> T castReference(Class<? extends T> t, U x) {
+        return t.cast(x);
+    }
+
+    private static final MethodHandle IDENTITY, IDENTITY_I, IDENTITY_J, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY;
+    static {
+        try {
+            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.genericMethodType(0);
+            IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType);
+            IDENTITY_I = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(int.class, int.class));
+            IDENTITY_J = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(long.class, long.class));
+            //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
+            CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType);
+            ALWAYS_NULL = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysNull", idType);
+            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.dropParameterTypes(0, 1));
+        } catch (Exception ex) {
+            Error err = new InternalError("uncaught exception");
+            err.initCause(ex);
+            throw err;
+        }
+    }
+
+    private static final EnumMap<Wrapper, MethodHandle> WRAPPER_CASTS
+            = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
+
+    private static final EnumMap<Wrapper, MethodHandle> EXACT_WRAPPER_CASTS
+            = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
+
+    /** Return a method that casts its sole argument (an Object) to the given type
+     *  and returns it as the given type (if exact is true), or as plain Object (if erase is true).
+     */
+    public static MethodHandle cast(Class<?> type, boolean exact) {
+        if (type.isPrimitive())  throw new IllegalArgumentException("cannot cast primitive type "+type);
+        MethodHandle mh = null;
+        Wrapper wrap = null;
+        EnumMap<Wrapper, MethodHandle> cache = null;
+        if (Wrapper.isWrapperType(type)) {
+            wrap = Wrapper.forWrapperType(type);
+            cache = (exact ? EXACT_WRAPPER_CASTS : WRAPPER_CASTS);
+            mh = cache.get(wrap);
+            if (mh != null)  return mh;
+        }
+        if (VerifyType.isNullReferenceConversion(Object.class, type))
+            mh = IDENTITY;
+        else if (VerifyType.isNullType(type))
+            mh = ALWAYS_NULL;
+        else
+            mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
+        if (exact) {
+            MethodType xmt = MethodType.methodType(type, Object.class);
+            mh = MethodHandles.explicitCastArguments(mh, xmt);
+            //mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
+        }
+        if (cache != null)
+            cache.put(wrap, mh);
+        return mh;
+    }
+
+    public static MethodHandle identity() {
+        return IDENTITY;
+    }
+
+    public static MethodHandle identity(Class<?> type) {
+        // This stuff has been moved into MethodHandles:
+        return MethodHandles.identity(type);
+    }
+
+    public static MethodHandle identity(Wrapper wrap) {
+        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
+        MethodHandle mh = cache.get(wrap);
+        if (mh != null) {
+            return mh;
+        }
+        // slow path
+        MethodType type = MethodType.methodType(wrap.primitiveType());
+        if (wrap != Wrapper.VOID)
+            type = type.appendParameterTypes(wrap.primitiveType());
+        try {
+            mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", type);
+        } catch (ReflectiveOperationException ex) {
+            mh = null;
+        }
+        if (mh == null && wrap == Wrapper.VOID) {
+            mh = EMPTY;  // #(){} : #()void
+        }
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+
+        if (mh != null) {
+            cache.put(wrap, mh);
+            return mh;
+        }
+        throw new IllegalArgumentException("cannot find identity for " + wrap);
+    }
+
+    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 (ReflectiveOperationException 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: cannot form a varargs array of length "+nargs);
+    }
+
+    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 (ReflectiveOperationException 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");
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+import java.lang.reflect.Modifier;
+import static java.lang.reflect.Modifier.*;
+
+/**
+ * This class centralizes information about the JVM's linkage access control.
+ * @author jrose
+ */
+public class VerifyAccess {
+
+    private VerifyAccess() { }  // cannot instantiate
+
+    private static final int PACKAGE_ONLY = 0;
+    private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
+    private static final boolean ALLOW_NESTMATE_ACCESS = false;
+
+    /**
+     * Evaluate the JVM linkage rules for access to the given method
+     * on behalf of a caller class which proposes to perform the access.
+     * Return true if the caller class has privileges to invoke a method
+     * or access a field with the given properties.
+     * This requires an accessibility check of the referencing class,
+     * plus an accessibility check of the member within the class,
+     * which depends on the member's modifier flags.
+     * <p>
+     * The relevant properties include the defining class ({@code defc})
+     * of the member, and its modifier flags ({@code mods}).
+     * Also relevant is the class used to make the initial symbolic reference
+     * to the member ({@code refc}).  If this latter class is not distinguished,
+     * the defining class should be passed for both arguments ({@code defc == refc}).
+     * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
+     * A field or method R is accessible to a class or interface D if
+     * and only if any of the following conditions is true:<ul>
+     * <li>R is public.
+     * <li>R is protected and is declared in a class C, and D is either
+     *     a subclass of C or C itself.  Furthermore, if R is not
+     *     static, then the symbolic reference to R must contain a
+     *     symbolic reference to a class T, such that T is either a
+     *     subclass of D, a superclass of D or D itself.
+     * <li>R is either protected or has default access (that is,
+     *     neither public nor protected nor private), and is declared
+     *     by a class in the same runtime package as D.
+     * <li>R is private and is declared in D.
+     * </ul>
+     * This discussion of access control omits a related restriction
+     * on the target of a protected field access or method invocation
+     * (the target must be of class D or a subtype of D). That
+     * requirement is checked as part of the verification process
+     * (5.4.1); it is not part of link-time access control.
+     * @param refc the class used in the symbolic reference to the proposed member
+     * @param defc the class in which the proposed member is actually defined
+     * @param mods modifier flags for the proposed member
+     * @param lookupClass the class for which the access check is being made
+     * @return true iff the the accessing class can access such a member
+     */
+    public static boolean isMemberAccessible(Class<?> refc,  // symbolic ref class
+                                             Class<?> defc,  // actual def class
+                                             int      mods,  // actual member mods
+                                             Class<?> lookupClass) {
+        // Usually refc and defc are the same, but if they differ, verify them both.
+        if (refc != defc) {
+            if (!isClassAccessible(refc, lookupClass)) {
+                // Note that defc is verified in the switch below.
+                return false;
+            }
+            if ((mods & (ALL_ACCESS_MODES|STATIC)) == (PROTECTED|STATIC)) {
+                // Apply the special rules for refc here.
+                if (!isRelatedClass(refc, lookupClass))
+                    return isSamePackage(defc, lookupClass);
+                // If refc == defc, the call to isPublicSuperClass will do
+                // the whole job, since in that case refc (as defc) will be
+                // a superclass of the lookup class.
+            }
+        }
+        if (defc == lookupClass)
+            return true;        // easy check; all self-access is OK
+        switch (mods & ALL_ACCESS_MODES) {
+        case PUBLIC:
+            if (refc != defc)  return true;  // already checked above
+            return isClassAccessible(refc, lookupClass);
+        case PROTECTED:
+            return isSamePackage(defc, lookupClass) || isPublicSuperClass(defc, lookupClass);
+        case PACKAGE_ONLY:
+            return isSamePackage(defc, lookupClass);
+        case PRIVATE:
+            // Loosened rules for privates follows access rules for inner classes.
+            return (ALLOW_NESTMATE_ACCESS &&
+                    isSamePackageMember(defc, lookupClass));
+        default:
+            throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
+        }
+    }
+
+    static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
+        return (refc == lookupClass ||
+                refc.isAssignableFrom(lookupClass) ||
+                lookupClass.isAssignableFrom(refc));
+    }
+
+    static boolean isPublicSuperClass(Class<?> defc, Class<?> lookupClass) {
+        return isPublic(defc.getModifiers()) && defc.isAssignableFrom(lookupClass);
+    }
+
+    /**
+     * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
+     * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
+     * A class or interface C is accessible to a class or interface D
+     * if and only if either of the following conditions are true:<ul>
+     * <li>C is public.
+     * <li>C and D are members of the same runtime package.
+     * </ul>
+     * @param refc the symbolic reference class to which access is being checked (C)
+     * @param lookupClass the class performing the lookup (D)
+     */
+    public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass) {
+        int mods = refc.getModifiers();
+        if (isPublic(mods))
+            return true;
+        if (isSamePackage(lookupClass, refc))
+            return true;
+        return false;
+    }
+
+    /**
+     * Test if two classes have the same class loader and package qualifier.
+     * @param class1
+     * @param class2
+     * @return whether they are in the same package
+     */
+    public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+        if (class1 == class2)
+            return true;
+        if (!loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
+            return false;
+        String name1 = class1.getName(), name2 = class2.getName();
+        int dot = name1.lastIndexOf('.');
+        if (dot != name2.lastIndexOf('.'))
+            return false;
+        for (int i = 0; i < dot; i++) {
+            if (name1.charAt(i) != name2.charAt(i))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Test if two classes are defined as part of the same package member (top-level class).
+     * If this is true, they can share private access with each other.
+     * @param class1
+     * @param class2
+     * @return whether they are identical or nested together
+     */
+    public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
+        if (class1 == class2)
+            return true;
+        if (!isSamePackage(class1, class2))
+            return false;
+        if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
+            return false;
+        return true;
+    }
+
+    private static Class<?> getOutermostEnclosingClass(Class<?> c) {
+        Class<?> pkgmem = c;
+        for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
+            pkgmem = enc;
+        return pkgmem;
+    }
+
+    private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2) {
+        if (loader1 == loader2 || loader1 == null || loader2 == null) {
+            return true;
+        }
+        for (ClassLoader scan1 = loader1;
+                scan1 != null; scan1 = scan1.getParent()) {
+            if (scan1 == loader2)  return true;
+        }
+        for (ClassLoader scan2 = loader2;
+                scan2 != null; scan2 = scan2.getParent()) {
+            if (scan2 == loader1)  return true;
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/VerifyType.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+import java.lang.invoke.MethodType;
+import sun.invoke.empty.Empty;
+
+/**
+ * This class centralizes information about the JVM verifier
+ * and its requirements about type correctness.
+ * @author jrose
+ */
+public class VerifyType {
+
+    private VerifyType() { }  // cannot instantiate
+
+    /**
+     * True if a value can be stacked as the source type and unstacked as the
+     * destination type, without violating the JVM's type consistency.
+     *
+     * @param call the type of a stacked value
+     * @param recv the type by which we'd like to treat it
+     * @return whether the retyping can be done without motion or reformatting
+     */
+    public static boolean isNullConversion(Class<?> src, Class<?> dst) {
+        if (src == dst)            return true;
+        // Verifier allows any interface to be treated as Object:
+        if (dst.isInterface())     dst = Object.class;
+        if (src.isInterface())     src = Object.class;
+        if (src == dst)            return true;  // check again
+        if (dst == void.class)     return true;  // drop any return value
+        if (isNullType(src))       return !dst.isPrimitive();
+        if (!src.isPrimitive())    return dst.isAssignableFrom(src);
+        // Verifier allows an int to carry byte, short, char, or even boolean:
+        if (dst == int.class)      return Wrapper.forPrimitiveType(src).isSubwordOrInt();
+        return false;
+    }
+
+    /**
+     * Specialization of isNullConversion to reference types.
+
+     * @param call the type of a stacked value
+     * @param recv the reference type by which we'd like to treat it
+     * @return whether the retyping can be done without a cast
+     */
+    public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) {
+        assert(!dst.isPrimitive());
+        if (dst.isInterface())  return true;   // verifier allows this
+        if (isNullType(src))    return true;
+        return dst.isAssignableFrom(src);
+    }
+
+    /**
+     * 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
+            // 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;
+    static {
+        Class<?> nullClass = null;
+        try {
+            nullClass = Class.forName("java.lang.Null");
+        } catch (ClassNotFoundException ex) {
+            // OK, we'll cope
+        }
+        NULL_CLASS = nullClass;
+    }
+
+    /**
+     * True if a method handle can receive a call under a slightly different
+     * method type, without moving or reformatting any stack elements.
+     *
+     * @param call the type of call being made
+     * @param recv the type of the method handle receiving the call
+     * @return whether the retyping can be done without motion or reformatting
+     */
+    public static boolean isNullConversion(MethodType call, MethodType recv) {
+        if (call == recv)  return true;
+        int len = call.parameterCount();
+        if (len != recv.parameterCount())  return false;
+        for (int i = 0; i < len; i++)
+            if (!isNullConversion(call.parameterType(i), recv.parameterType(i)))
+                return false;
+        return isNullConversion(recv.returnType(), call.returnType());
+    }
+
+    //TO DO: isRawConversion
+
+    /**
+     * Determine if the JVM verifier allows a value of type call to be
+     * passed to a formal parameter (or return variable) of type recv.
+     * Returns 1 if the verifier allows the types to match without conversion.
+     * Returns -1 if the types can be made to match by a JVM-supported adapter.
+     * Cases supported are:
+     * <ul><li>checkcast
+     * </li><li>conversion between any two integral types (but not floats)
+     * </li><li>unboxing from a wrapper to its corresponding primitive type
+     * </li><li>conversion in either direction between float and double
+     * </li></ul>
+     * (Autoboxing is not supported here; it must be done via Java code.)
+     * Returns 0 otherwise.
+     */
+    public static int canPassUnchecked(Class<?> src, Class<?> dst) {
+        if (src == dst)
+            return 1;
+
+        if (dst.isPrimitive()) {
+            if (dst == void.class)
+                // Return anything to a caller expecting void.
+                // This is a property of the implementation, which links
+                // return values via a register rather than via a stack push.
+                // This makes it possible to ignore cleanly.
+                return 1;
+            if (src == void.class)
+                return 0;  // void-to-something?
+            if (!src.isPrimitive())
+                // Cannot pass a reference to any primitive type (exc. void).
+                return 0;
+            Wrapper sw = Wrapper.forPrimitiveType(src);
+            Wrapper dw = Wrapper.forPrimitiveType(dst);
+            if (sw.isSubwordOrInt() && dw.isSubwordOrInt()) {
+                if (sw.bitWidth() >= dw.bitWidth())
+                    return -1;   // truncation may be required
+                if (!dw.isSigned() && sw.isSigned())
+                    return -1;   // sign elimination may be required
+            }
+            if (src == float.class || dst == float.class) {
+                if (src == double.class || dst == double.class)
+                    return -1;   // floating conversion may be required
+                else
+                    return 0;    // other primitive conversions NYI
+            } else {
+                // all fixed-point conversions are supported
+                return 0;
+            }
+        } else if (src.isPrimitive()) {
+            // Cannot pass a primitive to any reference type.
+            // (Maybe allow null.class?)
+            return 0;
+        }
+
+        // Handle reference types in the rest of the block:
+
+        // The verifier treats interfaces exactly like Object.
+        if (isNullReferenceConversion(src, dst))
+            // pass any reference to object or an arb. interface
+            return 1;
+        // else it's a definite "maybe" (cast is required)
+        return -1;
+    }
+
+    public static int canPassRaw(Class<?> src, Class<?> dst) {
+        if (dst.isPrimitive()) {
+            if (dst == void.class)
+                // As above, return anything to a caller expecting void.
+                return 1;
+            if (src == void.class)
+                // Special permission for raw conversions: allow a void
+                // 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);
+            Wrapper dw = Wrapper.forPrimitiveType(dst);
+            if (sw.stackSlots() == dw.stackSlots())
+                return 1;  // can do a reinterpret-cast on a stacked primitive
+            if (sw.isSubwordOrInt() && dw == Wrapper.VOID)
+                return 1;  // can drop an outgoing int value
+            return 0;
+        } else if (src.isPrimitive()) {
+            return 0;
+        }
+
+        // Both references.
+        if (isNullReferenceConversion(src, dst))
+            return 1;
+        return -1;
+    }
+
+    public static boolean isSpreadArgType(Class<?> spreadArg) {
+        return spreadArg.isArray();
+    }
+    public static Class<?> spreadArgElementType(Class<?> spreadArg, int i) {
+        return spreadArg.getComponentType();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/Wrapper.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+public enum Wrapper {
+    BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)),
+    // These must be in the order defined for widening primitive conversions in JLS 5.1.2
+    BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, Format.signed(8)),
+    SHORT(Short.class, short.class, 'S', (Short)(short)0, Format.signed(16)),
+    CHAR(Character.class, char.class, 'C', (Character)(char)0, Format.unsigned(16)),
+    INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)),
+    LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)),
+    FLOAT(Float.class, float.class, 'F', (Float)(float)0, Format.floating(32)),
+    DOUBLE(Double.class, double.class, 'D', (Double)(double)0, Format.floating(64)),
+    //NULL(Null.class, null.class, 'N', null, Format.other(1)),
+    OBJECT(Object.class, Object.class, 'L', null, Format.other(1)),
+    // VOID must be the last type, since it is "assignable" from any other type:
+    VOID(Void.class, void.class, 'V', null, Format.other(0)),
+    ;
+
+    private final Class<?> wrapperType;
+    private final Class<?> primitiveType;
+    private final char     basicTypeChar;
+    private final Object   zero;
+    private final int      format;
+    private final String   simpleName;
+
+    private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, int format) {
+        this.wrapperType = wtype;
+        this.primitiveType = ptype;
+        this.basicTypeChar = tchar;
+        this.zero = zero;
+        this.format = format;
+        this.simpleName = wtype.getSimpleName();
+    }
+
+    private static abstract class Format {
+        static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
+        static final int
+                SIGNED   = (-1) << KIND_SHIFT,
+                UNSIGNED = 0    << KIND_SHIFT,
+                FLOATING = 1    << KIND_SHIFT;
+        static final int
+                SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
+                SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
+        static int format(int kind, int size, int slots) {
+            assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
+            assert((size & (size-1)) == 0); // power of two
+            assert((kind == SIGNED)   ? (size > 0) :
+                   (kind == UNSIGNED) ? (size > 0) :
+                   (kind == FLOATING) ? (size == 32 || size == 64)  :
+                   false);
+            assert((slots == 2) ? (size == 64) :
+                   (slots == 1) ? (size <= 32) :
+                   false);
+            return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
+        }
+        static final int
+                INT      = SIGNED   | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+                SHORT    = SIGNED   | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+                BOOLEAN  = UNSIGNED | (1  << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+                CHAR     = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+                FLOAT    = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+                VOID     = UNSIGNED | (0  << SIZE_SHIFT) | (0 << SLOT_SHIFT),
+                NUM_MASK = (-1) << SIZE_SHIFT;
+        static int signed(int size)   { return format(SIGNED,   size, (size > 32 ? 2 : 1)); }
+        static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); }
+        static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); }
+        static int other(int slots)   { return slots << SLOT_SHIFT; }
+    }
+
+    /// format queries:
+
+    /** How many bits are in the wrapped value?  Returns 0 for OBJECT or VOID. */
+    public int     bitWidth()      { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; }
+    /** How many JVM stack slots occupied by the wrapped value?  Returns 0 for VOID. */
+    public int     stackSlots()    { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; }
+    /** Does the wrapped value occupy a single JVM stack slot? */
+    public boolean isSingleWord()  { return (format & (1 << Format.SLOT_SHIFT)) != 0; }
+    /** Does the wrapped value occupy two JVM stack slots? */
+    public boolean isDoubleWord()  { return (format & (2 << Format.SLOT_SHIFT)) != 0; }
+    /** Is the wrapped type numeric (not void or object)? */
+    public boolean isNumeric()     { return (format & Format.NUM_MASK) != 0; }
+    /** Is the wrapped type a primitive other than float, double, or void? */
+    public boolean isIntegral()    { return isNumeric() && format < Format.FLOAT; }
+    /** Is the wrapped type one of int, boolean, byte, char, or short? */
+    public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); }
+    /* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */
+    public boolean isSigned()      { return format < Format.VOID; }
+    /* Is the wrapped value an unsigned integral type (one of boolean or char)? */
+    public boolean isUnsigned()    { return format >= Format.BOOLEAN && format < Format.FLOAT; }
+    /** Is the wrapped type either float or double? */
+    public boolean isFloating()    { return format >= Format.FLOAT; }
+
+    /** Does the JVM verifier allow a variable of this wrapper's
+     *  primitive type to be assigned from a value of the given wrapper's primitive type?
+     *  Cases:
+     *  <ul>
+     *  <li>unboxing followed by widening primitive conversion
+     *  <li>any type converted to {@code void}
+     *  <li>boxing conversion followed by widening reference conversion to {@code Object}
+     *  <li>conversion of {@code boolean} to any type
+     *  </ul>
+     */
+    public boolean isConvertibleFrom(Wrapper source) {
+        if (this == source)  return true;
+        if (this.compareTo(source) < 0) {
+            // At best, this is a narrowing conversion.
+            return false;
+        }
+        if ((this.format ^ source.format) == (Format.SHORT ^ Format.CHAR)) {
+            assert (this == SHORT && source == CHAR) || (this == CHAR && source == SHORT);
+            return false;
+        }
+        return true;
+    }
+
+    /** Produce a zero value for the given wrapper type.
+     *  This will be a numeric zero for a number or character,
+     *  false for a boolean, and null for a reference or void.
+     *  The common thread is that this is what is contained
+     *  in a default-initialized variable of the given primitive
+     *  type.  (For void, it is what a reflective method returns
+     *  instead of no value at all.)
+     */
+    public Object zero() { return zero; }
+
+    /** Produce a zero value for the given wrapper type T.
+     *  The optional argument must a type compatible with this wrapper.
+     *  Equivalent to {@code this.cast(this.zero(), type)}.
+     */
+    public <T> T zero(Class<T> type) { return convert(zero, type); }
+
+//    /** Produce a wrapper for the given wrapper or primitive type. */
+//    public static Wrapper valueOf(Class<?> type) {
+//        if (isPrimitiveType(type))
+//            return forPrimitiveType(type);
+//        else
+//            return forWrapperType(type);
+//    }
+
+    /** Return the wrapper that wraps values of the given type.
+     *  The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
+     *  Otherwise, the type must be a primitive.
+     *  @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;
+        }
+        return null;
+    }
+
+    /** Return the wrapper that wraps values into the given wrapper type.
+     *  If it is {@code Object} or an interface, return {@code OBJECT}.
+     *  Otherwise, it must be a wrapper type.
+     *  The type must not be a primitive type.
+     *  @throws IllegalArgumentException for unexpected types
+     */
+    public static Wrapper forWrapperType(Class<?> type) {
+        Wrapper w = findWrapperType(type);
+        if (w != null)  return w;
+        for (Wrapper x : values())
+            if (x.wrapperType == type)
+                throw new InternalError(); // redo hash function
+        throw newIllegalArgumentException("not wrapper: "+type);
+    }
+
+    static Wrapper findWrapperType(Class<?> type) {
+        Wrapper w = FROM_WRAP[hashWrap(type)];
+        if (w != null && w.wrapperType == type) {
+            return w;
+        }
+        if (type.isInterface())
+            return OBJECT;
+        return null;
+    }
+
+    /** Return the wrapper that corresponds to the given bytecode
+     *  signature character.  Return {@code OBJECT} for the character 'L'.
+     *  @throws IllegalArgumentException for any non-signature character or {@code '['}.
+     */
+    public static Wrapper forBasicType(char type) {
+        Wrapper w = FROM_CHAR[hashChar(type)];
+        if (w != null && w.basicTypeChar == type) {
+            return w;
+        }
+        for (Wrapper x : values())
+            if (w.basicTypeChar == type)
+                throw new InternalError(); // redo hash function
+        throw newIllegalArgumentException("not basic type char: "+type);
+    }
+
+    /** Return the wrapper for the given type, if it is
+     *  a primitive type, else return {@code OBJECT}.
+     */
+    public static Wrapper forBasicType(Class<?> type) {
+        if (type.isPrimitive())
+            return forPrimitiveType(type);
+        return OBJECT;  // any reference, including wrappers or arrays
+    }
+
+    // Note on perfect hashes:
+    //   for signature chars c, do (c + (c >> 1)) % 16
+    //   for primitive type names n, do (n[0] + n[2]) % 16
+    // The type name hash works for both primitive and wrapper names.
+    // You can add "java/lang/Object" to the primitive names.
+    // But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
+    private static final Wrapper[] FROM_PRIM = new Wrapper[16];
+    private static final Wrapper[] FROM_WRAP = new Wrapper[16];
+    private static final Wrapper[] FROM_CHAR = new Wrapper[16];
+    private static int hashPrim(Class<?> x) {
+        String xn = x.getName();
+        if (xn.length() < 3)  return 0;
+        return (xn.charAt(0) + xn.charAt(2)) % 16;
+    }
+    private static int hashWrap(Class<?> x) {
+        String xn = x.getName();
+        final int offset = 10; assert(offset == "java.lang.".length());
+        if (xn.length() < offset+3)  return 0;
+        return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
+    }
+    private static int hashChar(char x) {
+        return (x + (x >> 1)) % 16;
+    }
+    static {
+        for (Wrapper w : values()) {
+            int pi = hashPrim(w.primitiveType);
+            int wi = hashWrap(w.wrapperType);
+            int ci = hashChar(w.basicTypeChar);
+            assert(FROM_PRIM[pi] == null);
+            assert(FROM_WRAP[wi] == null);
+            assert(FROM_CHAR[ci] == null);
+            FROM_PRIM[pi] = w;
+            FROM_WRAP[wi] = w;
+            FROM_CHAR[ci] = w;
+        }
+        //assert(jdk.sun.invoke.util.WrapperTest.test(false));
+    }
+
+    /** What is the primitive type wrapped by this wrapper? */
+    public Class<?> primitiveType() { return primitiveType; }
+
+    /** What is the wrapper type for this wrapper? */
+    public Class<?> wrapperType() { return wrapperType; }
+
+    /** What is the wrapper type for this wrapper?
+     * 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) {
+        if (exampleType == wrapperType) {
+            return exampleType;
+        } else if (exampleType == primitiveType ||
+                   wrapperType == Object.class ||
+                   exampleType.isInterface()) {
+            return forceType(wrapperType, exampleType);
+        }
+        throw newClassCastException(exampleType, primitiveType);
+    }
+
+    private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) {
+        return new ClassCastException(actual + " is not compatible with " + expected);
+    }
+
+    /** If {@code type} is a primitive type, return the corresponding
+     *  wrapper type, else return {@code type} unchanged.
+     */
+    public static <T> Class<T> asWrapperType(Class<T> type) {
+        if (type.isPrimitive()) {
+            return forPrimitiveType(type).wrapperType(type);
+        }
+        return type;
+    }
+
+    /** If {@code type} is a wrapper type, return the corresponding
+     *  primitive type, else return {@code type} unchanged.
+     */
+    public static <T> Class<T> asPrimitiveType(Class<T> type) {
+        Wrapper w = findWrapperType(type);
+        if (w != null) {
+            return forceType(w.primitiveType(), type);
+        }
+        return type;
+    }
+
+    /** Query:  Is the given type a wrapper, such as {@code Integer} or {@code Void}? */
+    public static boolean isWrapperType(Class<?> type) {
+        return findWrapperType(type) != null;
+    }
+
+    /** Query:  Is the given type a primitive, such as {@code int} or {@code void}? */
+    public static boolean isPrimitiveType(Class<?> type) {
+        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?
+     */
+    public char basicTypeChar() { return basicTypeChar; }
+
+    /** What is the simple name of the wrapper type?
+     */
+    public String simpleName() { return simpleName; }
+
+//    /** Wrap a value in the given type, which may be either a primitive or wrapper type.
+//     *  Performs standard primitive conversions, including truncation and float conversions.
+//     */
+//    public static <T> T wrap(Object x, Class<T> type) {
+//        return Wrapper.valueOf(type).cast(x, type);
+//    }
+
+    /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
+     *  The given target type must be this wrapper's primitive or wrapper type.
+     *  If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
+     *  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
+     *  it must be the wrapper's primitive type.
+     *  Primitive conversions are only performed if the given type is itself a primitive.
+     *  @throws ClassCastException if the given type is not compatible with this wrapper
+     */
+    public <T> T cast(Object x, Class<T> type) {
+        return convert(x, type, true);
+    }
+
+    /** Convert a wrapped value to the given type.
+     *  The given target type must be this wrapper's primitive or wrapper type.
+     *  This is equivalent to {@link #cast}, except that it refuses to perform
+     *  narrowing primitive conversions.
+     */
+    public <T> T convert(Object x, Class<T> type) {
+        return convert(x, type, false);
+    }
+
+    private <T> T convert(Object x, Class<T> type, boolean isCast) {
+        if (this == OBJECT) {
+            // If the target wrapper is OBJECT, just do a reference cast.
+            // If the target type is an interface, perform no runtime check.
+            // (This loophole is safe, and is allowed by the JVM verifier.)
+            // If the target type is a primitive, change it to a wrapper.
+            @SuppressWarnings("unchecked")
+            T result = (T) x;  // unchecked warning is expected here
+            return result;
+        }
+        Class<T> wtype = wrapperType(type);
+        if (wtype.isInstance(x)) {
+            @SuppressWarnings("unchecked")
+            T result = (T) x;  // unchecked warning is expected here
+            return result;
+        }
+        Class<?> sourceType = x.getClass();  // throw NPE if x is null
+        if (!isCast) {
+            Wrapper source = findWrapperType(sourceType);
+            if (source == null || !this.isConvertibleFrom(source)) {
+                throw newClassCastException(wtype, sourceType);
+            }
+        }
+        @SuppressWarnings("unchecked")
+        T result = (T) wrap(x);  // unchecked warning is expected here
+        assert result.getClass() == wtype;
+        return result;
+    }
+
+    /** Cast a reference type to another reference type.
+     * If the target type is an interface, perform no runtime check.
+     * (This loophole is safe, and is allowed by the JVM verifier.)
+     * 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.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;
+    }
+
+    /** Wrap a value in this wrapper's type.
+     * Performs standard primitive conversions, including truncation and float conversions.
+     * Performs returns the unchanged reference for {@code OBJECT}.
+     * Returns null for {@code VOID}.
+     * Returns a zero value for a null input.
+     * @throws ClassCastException if this wrapper is numeric and the operand
+     *                            is not a number, character, boolean, or null
+     */
+    public Object wrap(Object x) {
+        // do non-numeric wrappers first
+        switch (basicTypeChar) {
+            case 'L': return x;
+            case 'V': return null;
+        }
+        Number xn = numberValue(x);
+        switch (basicTypeChar) {
+            case 'I': return Integer.valueOf(xn.intValue());
+            case 'J': return Long.valueOf(xn.longValue());
+            case 'F': return Float.valueOf(xn.floatValue());
+            case 'D': return Double.valueOf(xn.doubleValue());
+            case 'S': return Short.valueOf((short) xn.intValue());
+            case 'B': return Byte.valueOf((byte) xn.intValue());
+            case 'C': return Character.valueOf((char) xn.intValue());
+            case 'Z': return Boolean.valueOf(boolValue(xn.longValue()));
+        }
+        throw new InternalError("bad wrapper");
+    }
+
+    /** Wrap a value (an int or smaller value) in this wrapper's type.
+     * Performs standard primitive conversions, including truncation and float conversions.
+     * Produces an {@code Integer} for {@code OBJECT}, although the exact type
+     * of the operand is not known.
+     * Returns null for {@code VOID}.
+     */
+    public Object wrap(int x) {
+        if (basicTypeChar == 'L')  return (Integer)x;
+        switch (basicTypeChar) {
+            case 'L': throw newIllegalArgumentException("cannot wrap to object type");
+            case 'V': return null;
+            case 'I': return Integer.valueOf((int)x);
+            case 'J': return Long.valueOf(x);
+            case 'F': return Float.valueOf(x);
+            case 'D': return Double.valueOf(x);
+            case 'S': return Short.valueOf((short) x);
+            case 'B': return Byte.valueOf((byte) x);
+            case 'C': return Character.valueOf((char) x);
+            case 'Z': return Boolean.valueOf(boolValue(x));
+        }
+        throw new InternalError("bad wrapper");
+    }
+
+    /** Wrap a value (a long or smaller value) in this wrapper's type.
+     * Does not perform floating point conversion.
+     * Produces a {@code Long} for {@code OBJECT}, although the exact type
+     * of the operand is not known.
+     * Returns null for {@code VOID}.
+     */
+    public Object wrapRaw(long x) {
+        switch (basicTypeChar) {
+            case 'F':  return Float.valueOf(Float.intBitsToFloat((int)x));
+            case 'D':  return Double.valueOf(Double.longBitsToDouble(x));
+            case 'L':  // same as 'J':
+            case 'J':  return (Long) x;
+        }
+        // Other wrapping operations are just the same, given that the
+        // operand is already promoted to an int.
+        return wrap((int)x);
+    }
+
+    /** Produce bitwise value which encodes the given wrapped value.
+     * Does not perform floating point conversion.
+     * Returns zero for {@code VOID}.
+     */
+    public long unwrapRaw(Object x) {
+        switch (basicTypeChar) {
+            case 'F':  return Float.floatToRawIntBits((Float) x);
+            case 'D':  return Double.doubleToRawLongBits((Double) x);
+
+            case 'L': throw newIllegalArgumentException("cannot unwrap from sobject type");
+            case 'V': return 0;
+            case 'I': return (int)(Integer) x;
+            case 'J': return (long)(Long) x;
+            case 'S': return (short)(Short) x;
+            case 'B': return (byte)(Byte) x;
+            case 'C': return (char)(Character) x;
+            case 'Z': return (boolean)(Boolean) x ? 1 : 0;
+        }
+        throw new InternalError("bad wrapper");
+    }
+
+    /** Report what primitive type holds this guy's raw value. */
+    public Class<?> rawPrimitiveType() {
+        return rawPrimitive().primitiveType();
+    }
+
+    /** Report, as a wrapper, what primitive type holds this guy's raw value.
+     *  Returns self for INT, LONG, OBJECT; returns LONG for DOUBLE,
+     *  else returns INT.
+     */
+    public Wrapper rawPrimitive() {
+        switch (basicTypeChar) {
+            case 'S': case 'B':
+            case 'C': case 'Z':
+            case 'V':
+            case 'F':
+                return INT;
+            case 'D':
+                return LONG;
+        }
+        return this;
+    }
+
+    private static Number numberValue(Object x) {
+        if (x instanceof Number)     return (Number)x;
+        if (x instanceof Character)  return (int)(Character)x;
+        if (x instanceof Boolean)    return (Boolean)x ? 1 : 0;
+        // Remaining allowed case of void:  Must be a null reference.
+        return (Number)x;
+    }
+
+    private static boolean boolValue(long bits) {
+        //bits &= 1;  // simple 31-bit zero extension
+        return (bits != 0);
+    }
+
+    private static RuntimeException newIllegalArgumentException(String message, Object x) {
+        return newIllegalArgumentException(message + x);
+    }
+    private static RuntimeException newIllegalArgumentException(String message) {
+        return new IllegalArgumentException(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/package-info.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Extra support for using JSR 292 RI, package java.lang.invoke.
+ * @author jrose
+ */
+
+package sun.invoke.util;
--- a/jdk/src/share/native/common/check_code.c	Wed Jul 05 17:38:31 2017 +0200
+++ b/jdk/src/share/native/common/check_code.c	Thu Mar 24 00:17:59 2011 -0700
@@ -2685,11 +2685,11 @@
                     switch (type_table[operand]) {
                     case JVM_CONSTANT_MethodType:
                       full_info = make_class_info_from_name(context,
-                                                            "java/dyn/MethodType");
+                                                            "java/lang/invoke/MethodType");
                       break;
                     default: //JVM_CONSTANT_MethodHandle
                       full_info = make_class_info_from_name(context,
-                                                            "java/dyn/MethodHandle");
+                                                            "java/lang/invoke/MethodHandle");
                       break;
                     }
                     break;
--- a/jdk/test/java/dyn/ClassValueTest.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary tests for class-specific values
- * @compile ClassValueTest.java
- * @run junit/othervm test.java.dyn.ClassValueTest
- */
-
-/*
-  Manually:
-   $ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/dyn/ClassValueTest.java
-   $ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.dyn.ClassValueTest
-  Output: .testAdd => 1000 : Integer
- */
-
-package test.java.dyn;
-
-import java.util.*;
-
-import java.dyn.*;
-
-import org.junit.*;
-import static org.junit.Assert.*;
-
-/**
- * @author jrose
- */
-public class ClassValueTest {
-    static String nameForCV1(Class<?> type) {
-        return "CV1:" + type.getName();
-    }
-    static int countForCV1;
-    static final ClassValue<String> CV1 = new CV1();
-    private static class CV1 extends ClassValue<String> {
-        protected String computeValue(Class<?> type) {
-            countForCV1++;
-            return nameForCV1(type);
-        }
-    }
-
-    static final Class[] CLASSES = {
-        String.class,
-        Integer.class,
-        int.class,
-        boolean[].class,
-        char[][].class,
-        ClassValueTest.class
-    };
-
-    @Test
-    public void testGet() {
-        countForCV1 = 0;
-        for (Class c : CLASSES) {
-            assertEquals(nameForCV1(c), CV1.get(c));
-        }
-        assertEquals(CLASSES.length, countForCV1);
-        for (Class c : CLASSES) {
-            assertEquals(nameForCV1(c), CV1.get(c));
-        }
-        assertEquals(CLASSES.length, countForCV1);
-    }
-
-    @Test
-    public void testRemove() {
-        for (Class c : CLASSES) {
-            CV1.get(c);
-        }
-        countForCV1 = 0;
-        int REMCOUNT = 3;
-        for (int i = 0; i < REMCOUNT; i++) {
-            CV1.remove(CLASSES[i]);
-        }
-        assertEquals(0, countForCV1);  // no change
-        for (Class c : CLASSES) {
-            assertEquals(nameForCV1(c), CV1.get(c));
-        }
-        assertEquals(REMCOUNT, countForCV1);
-    }
-
-    static String nameForCVN(Class<?> type, int n) {
-        return "CV[" + n + "]" + type.getName();
-    }
-    static int countForCVN;
-    static class CVN extends ClassValue<String> {
-        final int n;
-        CVN(int n) { this.n = n; }
-        protected String computeValue(Class<?> type) {
-            countForCVN++;
-            return nameForCVN(type, n);
-        }
-    };
-
-    @Test
-    public void testGetMany() {
-        int CVN_COUNT1 = 100, CVN_COUNT2 = 100;
-        CVN cvns[] = new CVN[CVN_COUNT1 * CVN_COUNT2];
-        for (int n = 0; n < cvns.length; n++) {
-            cvns[n] = new CVN(n);
-        }
-        countForCVN = 0;
-        for (int pass = 0; pass <= 2; pass++) {
-            for (int i1 = 0; i1 < CVN_COUNT1; i1++) {
-                eachClass:
-                for (Class c : CLASSES) {
-                    for (int i2 = 0; i2 < CVN_COUNT2; i2++) {
-                        int n = i1*CVN_COUNT2 + i2;
-                        assertEquals(0, countForCVN);
-                        assertEquals(nameForCVN(c, n), cvns[n].get(c));
-                        cvns[n].get(c);  //get it again
-                        //System.out.println("getting "+n+":"+cvns[n].get(c));
-                        boolean doremove = (((i1 + i2) & 3) == 0);
-                        switch (pass) {
-                        case 0:
-                            assertEquals(1, countForCVN);
-                            break;
-                        case 1:
-                            // remove on middle pass
-                            assertEquals(0, countForCVN);
-                            if (doremove) {
-                                //System.out.println("removing "+n+":"+cvns[n].get(c));
-                                cvns[n].remove(c);
-                                assertEquals(0, countForCVN);
-                            }
-                            break;
-                        case 2:
-                            assertEquals(doremove ? 1 : 0, countForCVN);
-                            break;
-                        }
-                        countForCVN = 0;
-                        if (i1 > i2 && i1 < i2+5)  continue eachClass;  // leave diagonal gap
-                    }
-                }
-            }
-        }
-        assertEquals(countForCVN, 0);
-        for (int n = 0; n < cvns.length; n++) {
-            for (Class c : CLASSES) {
-                assertEquals(nameForCVN(c, n), cvns[n].get(c));
-            }
-        }
-    }
-}
--- a/jdk/test/java/dyn/InvokeDynamicPrintArgs.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary smoke test for invokedynamic instructions
- * @build indify.Indify
- * @compile InvokeDynamicPrintArgs.java
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic
- *      indify.Indify
- *      --verify-specifier-count=3 --transitionalJSR292=false
- *      --expand-properties --classpath ${test.classes}
- *      --java test.java.dyn.InvokeDynamicPrintArgs --check-output
- */
-
-package test.java.dyn;
-
-import org.junit.Test;
-
-import java.util.*;
-import java.io.*;
-
-import java.dyn.*;
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-
-public class InvokeDynamicPrintArgs {
-    public static void main(String... av) throws Throwable {
-        if (av.length > 0)  openBuf();  // --check-output mode
-        System.out.println("Printing some argument lists, starting with a empty one:");
-        INDY_nothing().invokeExact();                 // BSM specifier #0 = {bsm}
-        INDY_bar().invokeExact("bar arg", 1);         // BSM specifier #1 = {bsm2, Void.class, "void type"}
-        INDY_bar2().invokeExact("bar2 arg", 222);     // BSM specifier #1 = (same)
-        INDY_baz().invokeExact("baz arg", 2, 3.14);   // BSM specifier #2 = {bsm2, 1234.5}
-        INDY_foo().invokeExact("foo arg");            // BSM specifier #0 = (same)
-        // Hence, BSM specifier count should be 3.  See "--verify-specifier-count=3" above.
-        System.out.println("Done printing argument lists.");
-        closeBuf();
-    }
-
-    @Test
-    public void testInvokeDynamicPrintArgs() throws IOException {
-        System.err.println(System.getProperties());
-        String testClassPath = System.getProperty("build.test.classes.dir");
-        if (testClassPath == null)  throw new RuntimeException();
-        String[] args = new String[]{
-            "--verify-specifier-count=3", "--transitionalJSR292=false",
-            "--expand-properties", "--classpath", testClassPath,
-            "--java", "test.java.dyn.InvokeDynamicPrintArgs", "--check-output"
-        };
-        System.err.println("Indify: "+Arrays.toString(args));
-        indify.Indify.main(args);
-    }
-
-    private static PrintStream oldOut;
-    private static ByteArrayOutputStream buf;
-    private static void openBuf() {
-        oldOut = System.out;
-        buf = new ByteArrayOutputStream();
-        System.setOut(new PrintStream(buf));
-    }
-    private static void closeBuf() {
-        if (buf == null)  return;
-        System.out.flush();
-        System.setOut(oldOut);
-        String[] haveLines = new String(buf.toByteArray()).split("[\n\r]+");
-        for (String line : haveLines)  System.out.println(line);
-        Iterator<String> iter = Arrays.asList(haveLines).iterator();
-        for (String want : EXPECT_OUTPUT) {
-            String have = iter.hasNext() ? iter.next() : "[EOF]";
-            if (want.equals(have))  continue;
-            System.err.println("want line: "+want);
-            System.err.println("have line: "+have);
-            throw new AssertionError("unexpected output: "+have);
-        }
-        if (iter.hasNext())
-            throw new AssertionError("unexpected output: "+iter.next());
-    }
-    private static final String[] EXPECT_OUTPUT = {
-        "Printing some argument lists, starting with a empty one:",
-        "[test.java.dyn.InvokeDynamicPrintArgs, nothing, ()void][]",
-        "[test.java.dyn.InvokeDynamicPrintArgs, bar, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]",
-        "[test.java.dyn.InvokeDynamicPrintArgs, bar2, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]",
-        "[test.java.dyn.InvokeDynamicPrintArgs, baz, (String,int,double)void, 1234.5][baz arg, 2, 3.14]",
-        "[test.java.dyn.InvokeDynamicPrintArgs, foo, (String)void][foo arg]",
-        "Done printing argument lists."
-    };
-
-    private static void printArgs(Object bsmInfo, Object... args) {
-        System.out.println(bsmInfo+Arrays.deepToString(args));
-    }
-    private static MethodHandle MH_printArgs() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(lookup().lookupClass(),
-                                   "printArgs", methodType(void.class, Object.class, Object[].class));
-    }
-
-    private static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
-        // ignore caller and name, but match the type:
-        Object bsmInfo = Arrays.asList(caller, name, type);
-        return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
-    }
-    private static MethodType MT_bsm() {
-        shouldNotCallThis();
-        return methodType(CallSite.class, Lookup.class, String.class, MethodType.class);
-    }
-    private static MethodHandle MH_bsm() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());
-    }
-
-    private static CallSite bsm2(Lookup caller, String name, MethodType type, Object... arg) throws ReflectiveOperationException {
-        // ignore caller and name, but match the type:
-        List<Object> bsmInfo = new ArrayList<>(Arrays.asList(caller, name, type));
-        bsmInfo.addAll(Arrays.asList((Object[])arg));
-        return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
-    }
-    private static MethodType MT_bsm2() {
-        shouldNotCallThis();
-        return methodType(CallSite.class, Lookup.class, String.class, MethodType.class, Object[].class);
-    }
-    private static MethodHandle MH_bsm2() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(lookup().lookupClass(), "bsm2", MT_bsm2());
-    }
-
-    private static MethodHandle INDY_nothing() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invokeGeneric(lookup(),
-                                                  "nothing", methodType(void.class)
-                                                  )).dynamicInvoker();
-    }
-    private static MethodHandle INDY_foo() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invokeGeneric(lookup(),
-                                                  "foo", methodType(void.class, String.class)
-                                                  )).dynamicInvoker();
-    }
-    private static MethodHandle INDY_bar() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
-                                                  "bar", methodType(void.class, String.class, int.class)
-                                                  , new Object[] { Void.class, "void type!",
-                                                                   1, 234.5F, 67.5, (long)89 }
-                                                  )).dynamicInvoker();
-    }
-    private static MethodHandle INDY_bar2() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
-                                                  "bar2", methodType(void.class, String.class, int.class)
-                                                  , new Object[] { Void.class, "void type!",
-                                                                   1, 234.5F, 67.5, (long)89 }
-                                                  )).dynamicInvoker();
-    }
-    private static MethodHandle INDY_baz() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
-                                                  "baz", methodType(void.class, String.class, int.class, double.class)
-                                                  , 1234.5
-                                                  )).dynamicInvoker();
-    }
-
-    private static void shouldNotCallThis() {
-        // if this gets called, the transformation has not taken place
-        if (System.getProperty("InvokeDynamicPrintArgs.allow-untransformed") != null)  return;
-        throw new AssertionError("this code should be statically transformed away by Indify");
-    }
-}
--- a/jdk/test/java/dyn/InvokeGenericTest.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,484 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary unit tests for java.dyn.MethodHandle.invokeGeneric
- * @compile -XDallowTransitionalJSR292=no -target 7 InvokeGenericTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.InvokeGenericTest
- */
-
-package test.java.dyn;
-
-import java.dyn.*;
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-import java.lang.reflect.*;
-import java.util.*;
-import org.junit.*;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-
-
-/**
- *
- * @author jrose
- */
-public class InvokeGenericTest {
-    // How much output?
-    static int verbosity = 0;
-    static {
-        String vstr = System.getProperty("test.java.dyn.InvokeGenericTest.verbosity");
-        if (vstr != null)  verbosity = Integer.parseInt(vstr);
-    }
-
-    @Test
-    public void testFirst() throws Throwable {
-        verbosity += 9; try {
-            // left blank for debugging
-        } finally { printCounts(); verbosity -= 9; }
-    }
-
-    public InvokeGenericTest() {
-    }
-
-    @Before
-    public void checkImplementedPlatform() {
-        boolean platformOK = false;
-        Properties properties = System.getProperties();
-        String vers = properties.getProperty("java.vm.version");
-        String name = properties.getProperty("java.vm.name");
-        String arch = properties.getProperty("os.arch");
-        if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
-             arch.equals("sparc") || arch.equals("sparcv9")) &&
-            (name.contains("Client") || name.contains("Server"))
-            ) {
-            platformOK = true;
-        } else {
-            System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
-        }
-        assumeTrue(platformOK);
-    }
-
-    String testName;
-    static int allPosTests, allNegTests;
-    int posTests, negTests;
-    @After
-    public void printCounts() {
-        if (verbosity >= 2 && (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");
-            allPosTests += posTests;
-            allNegTests += negTests;
-            posTests = negTests = 0;
-        }
-    }
-    void countTest(boolean positive) {
-        if (positive) ++posTests;
-        else          ++negTests;
-    }
-    void countTest() { countTest(true); }
-    void startTest(String name) {
-        if (testName != null)  printCounts();
-        if (verbosity >= 1)
-            System.out.println(name);
-        posTests = negTests = 0;
-        testName = name;
-    }
-
-    @BeforeClass
-    public static void setUpClass() throws Exception {
-        calledLog.clear();
-        calledLog.add(null);
-        nextArgVal = INITIAL_ARG_VAL;
-    }
-
-    @AfterClass
-    public static void tearDownClass() throws Exception {
-        int posTests = allPosTests, negTests = allNegTests;
-        if (verbosity >= 2 && (posTests | negTests) != 0) {
-            System.out.println();
-            if (posTests != 0)  System.out.println("=== "+posTests+" total positive test cases");
-            if (negTests != 0)  System.out.println("=== "+negTests+" total negative test cases");
-        }
-    }
-
-    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) && verbosity < 9)  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", expected, actual);
-    }
-    static void printCalled(MethodHandle target, String name, Object... args) {
-        if (verbosity >= 3)
-            System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
-    }
-
-    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 final int ONE_MILLION = (1000*1000),  // first int value
-                     TEN_BILLION = (10*1000*1000*1000),  // scale factor to reach upper 32 bits
-                     INITIAL_ARG_VAL = ONE_MILLION << 1;  // <<1 makes space for sign bit;
-    static long nextArgVal;
-    static long nextArg(boolean moreBits) {
-        long val = nextArgVal++;
-        long sign = -(val & 1); // alternate signs
-        val >>= 1;
-        if (moreBits)
-            // Guarantee some bits in the high word.
-            // In any case keep the decimal representation simple-looking,
-            // with lots of zeroes, so as not to make the printed decimal
-            // strings unnecessarily noisy.
-            val += (val % ONE_MILLION) * TEN_BILLION;
-        return val ^ sign;
-    }
-    static int nextArg() {
-        // Produce a 32-bit result something like ONE_MILLION+(smallint).
-        // Example: 1_000_042.
-        return (int) nextArg(false);
-    }
-    static long nextArg(Class<?> kind) {
-        if (kind == long.class   || kind == Long.class ||
-            kind == double.class || kind == Double.class)
-            // produce a 64-bit result something like
-            // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
-            // Example: 10_000_420_001_000_042.
-            return nextArg(true);
-        return (long) nextArg();
-    }
-
-    static Object randomArg(Class<?> param) {
-        Object wrap = castToWrapperOrNull(nextArg(param), param);
-        if (wrap != null) {
-            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()) {
-            for (Class<?> c : param.getClasses()) {
-                if (param.isAssignableFrom(c) && !c.isInterface())
-                    { param = c; break; }
-            }
-        }
-        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 final Object ANON_OBJ = new Object();
-    static Object zeroArg(Class<?> param) {
-        Object x = castToWrapperOrNull(0L, param);
-        if (x != null)  return x;
-        if (param.isInterface() || param.isAssignableFrom(String.class))  return "\"\"";
-        if (param == Object.class)  return ANON_OBJ;
-        if (param.getComponentType() != null)  return Array.newInstance(param.getComponentType(), 0);
-        return null;
-    }
-    static Object[] zeroArgs(Class<?>... params) {
-        Object[] args = new Object[params.length];
-        for (int i = 0; i < args.length; i++)
-            args[i] = zeroArg(params[i]);
-        return args;
-    }
-    static Object[] zeroArgs(List<Class<?>> params) {
-        return zeroArgs(params.toArray(new Class<?>[0]));
-    }
-
-    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 InvokeGenericTest.
-    static final Lookup LOOKUP = MethodHandles.lookup();
-
-    Map<List<Class<?>>, MethodHandle> CALLABLES = new HashMap<List<Class<?>>, MethodHandle>();
-    MethodHandle callable(List<Class<?>> params) {
-        MethodHandle mh = CALLABLES.get(params);
-        if (mh == null) {
-            mh = collector_MH.asType(methodType(Object.class, params));
-            CALLABLES.put(params, mh);
-        }
-        return mh;
-    }
-    MethodHandle callable(Class<?>... params) {
-        return callable(Arrays.asList(params));
-    }
-    private static Object collector(Object... args) {
-        return Arrays.asList(args);
-    }
-    private static final MethodHandle collector_MH;
-    static {
-        try {
-            collector_MH
-                = LOOKUP.findStatic(LOOKUP.lookupClass(),
-                                    "collector",
-                                    methodType(Object.class, Object[].class));
-        } catch (ReflectiveOperationException ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    @Test
-    public void testSimple() throws Throwable {
-        startTest("testSimple");
-        countTest();
-        String[] args = { "one", "two" };
-        MethodHandle mh = callable(Object.class, String.class);
-        Object res; List resl;
-        res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]);
-        //System.out.println(res);
-        assertEquals(Arrays.asList(args), res);
-    }
-
-    @Test
-    public void testWrongArgumentCount() throws Throwable {
-        startTest("testWrongArgumentCount");
-        for (int i = 0; i <= 10; i++) {
-            testWrongArgumentCount(Collections.<Class<?>>nCopies(i, Integer.class));
-            if (i <= 4) {
-                testWrongArgumentCount(Collections.<Class<?>>nCopies(i, int.class));
-                testWrongArgumentCount(Collections.<Class<?>>nCopies(i, long.class));
-            }
-        }
-    }
-    public void testWrongArgumentCount(List<Class<?>> params) throws Throwable {
-        int max = params.size();
-        for (int i = 0; i < max; i++) {
-            List<Class<?>> params2 = params.subList(0, i);
-            for (int k = 0; k <= 2; k++) {
-                if (k == 1)  params  = methodType(Object.class,  params).generic().parameterList();
-                if (k == 2)  params2 = methodType(Object.class, params2).generic().parameterList();
-                testWrongArgumentCount(params, params2);
-                testWrongArgumentCount(params2, params);
-            }
-        }
-    }
-    public void testWrongArgumentCount(List<Class<?>> expect, List<Class<?>> observe) throws Throwable {
-        countTest(false);
-        if (expect.equals(observe))
-            assert(false);
-        MethodHandle target = callable(expect);
-        Object[] args = zeroArgs(observe);
-        Object junk;
-        try {
-            switch (args.length) {
-            case 0:
-                junk = target.invokeGeneric(); break;
-            case 1:
-                junk = target.invokeGeneric(args[0]); break;
-            case 2:
-                junk = target.invokeGeneric(args[0], args[1]); break;
-            case 3:
-                junk = target.invokeGeneric(args[0], args[1], args[2]); break;
-            case 4:
-                junk = target.invokeGeneric(args[0], args[1], args[2], args[3]); break;
-            default:
-                junk = target.invokeWithArguments(args); break;
-            }
-        } catch (WrongMethodTypeException ex) {
-            return;
-        } catch (Exception ex) {
-            throw new RuntimeException("wrong exception calling "+target+target.type()+" on "+Arrays.asList(args)+" : "+ex);
-        }
-        throw new RuntimeException("bad success calling "+target+target.type()+" on "+Arrays.asList(args));
-    }
-
-    /** Make a list of all combinations of the given types, with the given arities.
-     *  A void return type is possible iff the first type is void.class.
-     */
-    static List<MethodType> allMethodTypes(int minargc, int maxargc, Class<?>... types) {
-        ArrayList<MethodType> result = new ArrayList<MethodType>();
-        if (types.length > 0) {
-            ArrayList<MethodType> argcTypes = new ArrayList<MethodType>();
-            // build arity-zero types first
-            for (Class<?> rtype : types) {
-                argcTypes.add(MethodType.methodType(rtype));
-            }
-            if (types[0] == void.class)
-                // void is not an argument type
-                types = Arrays.copyOfRange(types, 1, types.length);
-            for (int argc = 0; argc <= maxargc; argc++) {
-                if (argc >= minargc)
-                    result.addAll(argcTypes);
-                if (argc >= maxargc)
-                    break;
-                ArrayList<MethodType> prevTypes = argcTypes;
-                argcTypes = new ArrayList<MethodType>();
-                for (MethodType prevType : prevTypes) {
-                    for (Class<?> ptype : types) {
-                        argcTypes.add(prevType.insertParameterTypes(argc, ptype));
-                    }
-                }
-            }
-        }
-        return Collections.unmodifiableList(result);
-    }
-    static List<MethodType> allMethodTypes(int argc, Class<?>... types) {
-        return allMethodTypes(argc, argc, types);
-    }
-
-    interface RandomInterface { }
-
-    MethodHandle toString_MH;
-
-    @Test
-    public void testReferenceConversions() throws Throwable {
-        startTest("testReferenceConversions");
-        toString_MH = LOOKUP.
-            findVirtual(Object.class, "toString", MethodType.methodType(String.class));
-        String[] args = { "one", "two" };
-        for (MethodType type : allMethodTypes(2, Object.class, String.class, RandomInterface.class)) {
-            testReferenceConversions(type, args);
-        }
-    }
-    public void testReferenceConversions(MethodType type, Object... args) throws Throwable {
-        countTest();
-        if (verbosity > 3)  System.out.println("target type: "+type);
-        MethodHandle mh = callable(type.parameterList());
-        MethodHandle tsdrop = MethodHandles.dropArguments(toString_MH, 1, type.parameterList());
-        mh = MethodHandles.foldArguments(tsdrop, mh);
-        mh = mh.asType(type);
-        Object res = mh.invokeGeneric((String)args[0], (Object)args[1]);
-        //System.out.println(res);
-        assertEquals(Arrays.asList(args).toString(), res);
-    }
-
-
-    @Test @Ignore("known failure pending 6939861")
-    public void testBoxConversions() throws Throwable {
-        startTest("testBoxConversions");
-        countTest();
-        Integer[] args = { 1, 2 };
-        MethodHandle mh = callable(Object.class, int.class);
-        Object res; List resl;
-        res = resl = (List) mh.invokeGeneric((int)args[0], (Object)args[1]);
-        //System.out.println(res);
-        assertEquals(Arrays.asList(args), res);
-    }
-
-}
--- a/jdk/test/java/dyn/JavaDocExamplesTest.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary example code used in javadoc for java.dyn API
- * @compile -XDallowTransitionalJSR292=no JavaDocExamplesTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamplesTest
- */
-
-/*
----- To run outside jtreg:
-$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
-   $DAVINCI/sources/jdk/test/java/dyn/JavaDocExamplesTest.java
-$ $JAVA7X_HOME/bin/java   -cp $JUNIT4_JAR:/tmp/Classes \
-   -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
-   -Dtest.java.dyn.JavaDocExamplesTest.verbosity=1 \
-     test.java.dyn.JavaDocExamplesTest
-----
-*/
-
-package test.java.dyn;
-
-import java.dyn.*;
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.junit.*;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-
-
-/**
- * @author jrose
- */
-public class JavaDocExamplesTest {
-    /** Wrapper for running the JUnit tests in this module.
-     *  Put JUnit on the classpath!
-     */
-    public static void main(String... ignore) {
-        org.junit.runner.JUnitCore.runClasses(JavaDocExamplesTest.class);
-    }
-    // How much output?
-    static int verbosity = Integer.getInteger("test.java.dyn.JavaDocExamplesTest.verbosity", 0);
-
-{}
-static final private Lookup LOOKUP = lookup();
-// static final private MethodHandle CONCAT_1 = LOOKUP.findVirtual(String.class,
-//     "concat", methodType(String.class, String.class));
-// static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class,
-//     "hashCode", methodType(int.class));
-
-// form required if ReflectiveOperationException is intercepted:
-static final private MethodHandle CONCAT_2, HASHCODE_2;
-static {
-  try {
-    CONCAT_2 = LOOKUP.findVirtual(String.class,
-      "concat", methodType(String.class, String.class));
-    HASHCODE_2 = LOOKUP.findVirtual(Object.class,
-      "hashCode", methodType(int.class));
-   } catch (ReflectiveOperationException ex) {
-     throw new RuntimeException(ex);
-   }
-}
-{}
-
-    @Test public void testFindVirtual() throws Throwable {
-{}
-MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class,
-  "concat", methodType(String.class, String.class));
-MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class,
-  "hashCode", methodType(int.class));
-//assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y"));
-assertEquals("xy", (String) CONCAT_2.invokeExact("x", "y"));
-assertEquals("xy", (String) CONCAT_3.invokeExact("x", "y"));
-//assertEquals("xy".hashCode(), (int) HASHCODE_1.invokeExact((Object)"xy"));
-assertEquals("xy".hashCode(), (int) HASHCODE_2.invokeExact((Object)"xy"));
-assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy"));
-{}
-    }
-    @Test public void testDropArguments() throws Throwable {
-        {{
-{} /// JAVADOC
-MethodHandle cat = lookup().findVirtual(String.class,
-  "concat", methodType(String.class, String.class));
-assertEquals("xy", (String) cat.invokeExact("x", "y"));
-MethodHandle d0 = dropArguments(cat, 0, String.class);
-assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
-MethodHandle d1 = dropArguments(cat, 1, String.class);
-assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
-MethodHandle d2 = dropArguments(cat, 2, String.class);
-assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
-MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
-assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
-            }}
-    }
-
-    @Test public void testFilterArguments() throws Throwable {
-        {{
-{} /// JAVADOC
-MethodHandle cat = lookup().findVirtual(String.class,
-  "concat", methodType(String.class, String.class));
-MethodHandle upcase = lookup().findVirtual(String.class,
-  "toUpperCase", methodType(String.class));
-assertEquals("xy", (String) cat.invokeExact("x", "y"));
-MethodHandle f0 = filterArguments(cat, 0, upcase);
-assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
-MethodHandle f1 = filterArguments(cat, 1, upcase);
-assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
-MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
-assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
-            }}
-    }
-
-    static void assertEquals(Object exp, Object act) {
-        if (verbosity > 0)
-            System.out.println("result: "+act);
-        Assert.assertEquals(exp, act);
-    }
-
-    @Test public void testMethodHandlesSummary() throws Throwable {
-        {{
-{} /// JAVADOC
-Object x, y; String s; int i;
-MethodType mt; MethodHandle mh;
-MethodHandles.Lookup lookup = MethodHandles.lookup();
-// mt is (char,char)String
-mt = MethodType.methodType(String.class, char.class, char.class);
-mh = lookup.findVirtual(String.class, "replace", mt);
-s = (String) mh.invokeExact("daddy",'d','n');
-// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
-assert(s.equals("nanny"));
-// weakly typed invocation (using MHs.invoke)
-s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
-assert(s.equals("savvy"));
-// mt is (Object[])List
-mt = MethodType.methodType(java.util.List.class, Object[].class);
-mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
-assert(mh.isVarargsCollector());
-x = mh.invokeGeneric("one", "two");
-// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
-assert(x.equals(java.util.Arrays.asList("one","two")));
-// mt is (Object,Object,Object)Object
-mt = MethodType.genericMethodType(3);
-mh = mh.asType(mt);
-x = mh.invokeExact((Object)1, (Object)2, (Object)3);
-// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-assert(x.equals(java.util.Arrays.asList(1,2,3)));
-// mt is { =&gt; int}
-mt = MethodType.methodType(int.class);
-mh = lookup.findVirtual(java.util.List.class, "size", mt);
-i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
-// invokeExact(Ljava/util/List;)I
-assert(i == 3);
-mt = MethodType.methodType(void.class, String.class);
-mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
-mh.invokeExact(System.out, "Hello, world.");
-// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
-{}
-            }}
-    }
-
-    @Test public void testAsVarargsCollector() throws Throwable {
-        {{
-{} /// JAVADOC
-MethodHandle asList = publicLookup()
-  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
-  .asVarargsCollector(Object[].class);
-assertEquals("[]", asList.invokeGeneric().toString());
-assertEquals("[1]", asList.invokeGeneric(1).toString());
-assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString());
-Object[] argv = { "three", "thee", "tee" };
-assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString());
-List ls = (List) asList.invokeGeneric((Object)argv);
-assertEquals(1, ls.size());
-assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
-            }}
-    }
-
-    @Test public void testVarargsCollectorSuppression() throws Throwable {
-        {{
-{} /// JAVADOC
-MethodHandle vamh = publicLookup()
-  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
-  .asVarargsCollector(Object[].class);
-MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
-assert(vamh.type().equals(mh.type()));
-assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString());
-boolean failed = false;
-try { mh.invokeGeneric(1,2,3); }
-catch (WrongMethodTypeException ex) { failed = true; }
-assert(failed);
-{}
-            }}
-    }
-}
--- a/jdk/test/java/dyn/MethodHandlesTest.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2400 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary unit tests for java.dyn.MethodHandles
- * @compile -source 7 -target 7 -XDallowTransitionalJSR292=no MethodHandlesTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.MethodHandlesTest
- */
-
-package test.java.dyn;
-
-import java.dyn.*;
-import java.dyn.MethodHandles.Lookup;
-import java.lang.reflect.*;
-import java.util.*;
-import org.junit.*;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-
-
-/**
- *
- * @author jrose
- */
-public class MethodHandlesTest {
-    // How much output?
-    static int verbosity = 0;
-    static {
-        String vstr = System.getProperty("test.java.dyn.MethodHandlesTest.verbosity");
-        if (vstr != null)  verbosity = Integer.parseInt(vstr);
-    }
-
-    // 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 = true;
-
-    @Test
-    public void testFirst() throws Throwable {
-        verbosity += 9; try {
-            // left blank for debugging
-        } finally { printCounts(); verbosity -= 9; }
-    }
-
-    // current failures
-    @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
-    public void testFail_1() throws Throwable {
-        // AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters
-        testSpreadArguments(int.class, 0, 6);
-    }
-    @Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args")
-    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 {
-        // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
-        testSpreadArguments(int.class, 1, 2);
-    }
-    @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
-    public void testFail_4() throws Throwable {
-        // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
-        testCollectArguments(int.class, 1, 2);
-    }
-    @Test @Ignore("cannot collect leading primitive types")
-    public void testFail_5() throws Throwable {
-        // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
-        testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
-    }
-    @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit")
-    public void testFail_6() throws Throwable {
-        // ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13
-        testInsertArguments(0, 0, MAX_ARG_INCREASE+10);
-    }
-    static final int MAX_ARG_INCREASE = 3;
-
-    public MethodHandlesTest() {
-    }
-
-    @Before
-    public void checkImplementedPlatform() {
-        boolean platformOK = false;
-        Properties properties = System.getProperties();
-        String vers = properties.getProperty("java.vm.version");
-        String name = properties.getProperty("java.vm.name");
-        String arch = properties.getProperty("os.arch");
-        if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
-             arch.equals("sparc") || arch.equals("sparcv9")) &&
-            (name.contains("Client") || name.contains("Server"))
-            ) {
-            platformOK = true;
-        } else {
-            System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
-        }
-        assumeTrue(platformOK);
-    }
-
-    String testName;
-    static int allPosTests, allNegTests;
-    int posTests, negTests;
-    @After
-    public void printCounts() {
-        if (verbosity >= 2 && (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");
-            allPosTests += posTests;
-            allNegTests += negTests;
-            posTests = negTests = 0;
-        }
-    }
-    void countTest(boolean positive) {
-        if (positive) ++posTests;
-        else          ++negTests;
-    }
-    void countTest() { countTest(true); }
-    void startTest(String name) {
-        if (testName != null)  printCounts();
-        if (verbosity >= 1)
-            System.out.println(name);
-        posTests = negTests = 0;
-        testName = name;
-    }
-
-    @BeforeClass
-    public static void setUpClass() throws Exception {
-        calledLog.clear();
-        calledLog.add(null);
-        nextArgVal = INITIAL_ARG_VAL;
-    }
-
-    @AfterClass
-    public static void tearDownClass() throws Exception {
-        int posTests = allPosTests, negTests = allNegTests;
-        if (verbosity >= 2 && (posTests | negTests) != 0) {
-            System.out.println();
-            if (posTests != 0)  System.out.println("=== "+posTests+" total positive test cases");
-            if (negTests != 0)  System.out.println("=== "+negTests+" total negative test cases");
-        }
-    }
-
-    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) && verbosity < 9)  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", expected, actual);
-    }
-    static void printCalled(MethodHandle target, String name, Object... args) {
-        if (verbosity >= 3)
-            System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
-    }
-
-    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 final int ONE_MILLION = (1000*1000),  // first int value
-                     TEN_BILLION = (10*1000*1000*1000),  // scale factor to reach upper 32 bits
-                     INITIAL_ARG_VAL = ONE_MILLION << 1;  // <<1 makes space for sign bit;
-    static long nextArgVal;
-    static long nextArg(boolean moreBits) {
-        long val = nextArgVal++;
-        long sign = -(val & 1); // alternate signs
-        val >>= 1;
-        if (moreBits)
-            // Guarantee some bits in the high word.
-            // In any case keep the decimal representation simple-looking,
-            // with lots of zeroes, so as not to make the printed decimal
-            // strings unnecessarily noisy.
-            val += (val % ONE_MILLION) * TEN_BILLION;
-        return val ^ sign;
-    }
-    static int nextArg() {
-        // Produce a 32-bit result something like ONE_MILLION+(smallint).
-        // Example: 1_000_042.
-        return (int) nextArg(false);
-    }
-    static long nextArg(Class<?> kind) {
-        if (kind == long.class   || kind == Long.class ||
-            kind == double.class || kind == Double.class)
-            // produce a 64-bit result something like
-            // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
-            // Example: 10_000_420_001_000_042.
-            return nextArg(true);
-        return (long) nextArg();
-    }
-
-    static Object randomArg(Class<?> param) {
-        Object wrap = castToWrapperOrNull(nextArg(param), param);
-        if (wrap != null) {
-            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()) {
-            for (Class<?> c : param.getClasses()) {
-                if (param.isAssignableFrom(c) && !c.isInterface())
-                    { param = c; break; }
-            }
-        }
-        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();
-    }
-
-    /** Return lambda(arg...[arity]) { new Object[]{ arg... } } */
-    static MethodHandle varargsList(int arity) {
-        return ValueConversions.varargsList(arity);
-    }
-    /** Return lambda(arg...[arity]) { Arrays.asList(arg...) } */
-    static MethodHandle varargsArray(int arity) {
-        return ValueConversions.varargsArray(arity);
-    }
-    /** Variation of varargsList, but with the given rtype. */
-    static MethodHandle varargsList(int arity, Class<?> rtype) {
-        MethodHandle list = varargsList(arity);
-        MethodType listType = list.type().changeReturnType(rtype);
-        if (List.class.isAssignableFrom(rtype) || rtype == void.class || rtype == Object.class) {
-            // OK
-        } else if (rtype.isAssignableFrom(String.class)) {
-            if (LIST_TO_STRING == null)
-                try {
-                    LIST_TO_STRING = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToString",
-                                                        MethodType.methodType(String.class, List.class));
-                } catch (Exception ex) { throw new RuntimeException(ex); }
-            list = MethodHandles.filterReturnValue(list, LIST_TO_STRING);
-        } else if (rtype.isPrimitive()) {
-            if (LIST_TO_INT == null)
-                try {
-                    LIST_TO_INT = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToInt",
-                                                     MethodType.methodType(int.class, List.class));
-                } catch (Exception ex) { throw new RuntimeException(ex); }
-            list = MethodHandles.filterReturnValue(list, LIST_TO_INT);
-            list = MethodHandles.explicitCastArguments(list, listType);
-        } else {
-            throw new RuntimeException("varargsList: "+rtype);
-        }
-        return list.asType(listType);
-    }
-    private static MethodHandle LIST_TO_STRING, LIST_TO_INT;
-    private static String listToString(List x) { return x.toString(); }
-    private static int listToInt(List x) { return x.toString().hashCode(); }
-
-    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); }
-
-        static final Lookup EXAMPLE = MethodHandles.lookup();  // for testing findSpecial
-    }
-    static final Lookup EXAMPLE = Example.EXAMPLE;
-    public static class PubExample extends Example {
-        public PubExample() { super("PubExample#"+nextArg()); }
-    }
-    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();
-        public static class Impl implements IntExample {
-            public void        v0()     { called("Int/v0", this); }
-            final String name;
-            public Impl() { name = "Impl#"+nextArg(); }
-            @Override public String toString() { return name; }
-        }
-    }
-
-    static final Object[][][] ACCESS_CASES = {
-        { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false
-        { { false, PUBLIC }, { false, PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[1]: only PRIVATE
-        { { false, PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[2]: PUBLIC false
-        { { true,  PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[3]: all true
-    };
-
-    static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) {
-        Object[][] cases;
-        if (name.contains("pri_") || isSpecial) {
-            cases = ACCESS_CASES[1]; // PRIVATE only
-        } else if (name.contains("pkg_") || !Modifier.isPublic(defc.getModifiers())) {
-            cases = ACCESS_CASES[2]; // not PUBLIC
-        } else {
-            assertTrue(name.indexOf('_') < 0);
-            boolean pubc = Modifier.isPublic(defc.getModifiers());
-            if (pubc)
-                cases = ACCESS_CASES[3]; // all access levels
-            else
-                cases = ACCESS_CASES[2]; // PACKAGE but not PUBLIC
-        }
-        if (defc != Example.class && cases[cases.length-1][1] == EXAMPLE)
-            cases = Arrays.copyOfRange(cases, 0, cases.length-1);
-        return cases;
-    }
-    static Object[][] accessCases(Class<?> defc, String name) {
-        return accessCases(defc, name, false);
-    }
-
-    @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;
-        Exception noAccess = null;
-        try {
-            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
-            target = lookup.in(defc).findStatic(defc, name, type);
-        } catch (ReflectiveOperationException ex) {
-            noAccess = ex;
-            if (name.contains("bogus"))
-                assertTrue(noAccess instanceof NoSuchMethodException);
-            else
-                assertTrue(noAccess instanceof IllegalAccessException);
-        }
-        if (verbosity >= 3)
-            System.out.println("findStatic "+lookup+": "+defc.getName()+"."+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());
-        assertNameStringContains(target, name);
-        if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
-        Object[] args = randomArgs(params);
-        printCalled(target, name, args);
-        target.invokeWithArguments(args);
-        assertCalled(name, args);
-        if (verbosity >= 1)
-            System.out.print(':');
-    }
-
-    // rough check of name string
-    static void assertNameStringContains(Object x, String s) {
-        if (x.toString().contains(s))  return;
-        assertEquals(s, x);
-    }
-
-    @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;
-        Exception noAccess = null;
-        try {
-            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
-            target = lookup.in(defc).findVirtual(defc, methodName, type);
-        } catch (ReflectiveOperationException ex) {
-            noAccess = ex;
-            if (name.contains("bogus"))
-                assertTrue(noAccess instanceof NoSuchMethodException);
-            else
-                assertTrue(noAccess instanceof IllegalAccessException);
-        }
-        if (verbosity >= 3)
-            System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+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);
-        assertEquals(typeWithSelf, target.type());
-        assertNameStringContains(target, methodName);
-        if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
-        Object[] argsWithSelf = randomArgs(paramsWithSelf);
-        if (rcvc != defc)  argsWithSelf[0] = randomArg(rcvc);
-        printCalled(target, name, argsWithSelf);
-        target.invokeWithArguments(argsWithSelf);
-        assertCalled(name, argsWithSelf);
-        if (verbosity >= 1)
-            System.out.print(':');
-    }
-
-    @Test
-    public void testFindSpecial() throws Throwable {
-        if (CAN_SKIP_WORKING)  return;
-        startTest("findSpecial");
-        testFindSpecial(SubExample.class, Example.class, void.class, "v0");
-        testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0");
-        // Do some negative testing:
-        testFindSpecial(false, EXAMPLE, SubExample.class, Example.class, void.class, "bogus");
-        testFindSpecial(false, PRIVATE, SubExample.class, Example.class, void.class, "bogus");
-        for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) {
-            testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0");
-            testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class);
-            testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0");
-        }
-    }
-
-    void testFindSpecial(Class<?> specialCaller,
-                         Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
-        testFindSpecial(true,  EXAMPLE, specialCaller, defc, ret, name, params);
-        testFindSpecial(true,  PRIVATE, specialCaller, defc, ret, name, params);
-        testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params);
-        testFindSpecial(false, PUBLIC,  specialCaller, defc, ret, name, params);
-    }
-    void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller,
-                         Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
-        countTest(positive);
-        MethodType type = MethodType.methodType(ret, params);
-        MethodHandle target = null;
-        Exception noAccess = null;
-        try {
-            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
-            if (verbosity >= 5)  System.out.println("  lookup => "+lookup.in(specialCaller));
-            target = lookup.in(specialCaller).findSpecial(defc, name, type, specialCaller);
-        } catch (ReflectiveOperationException ex) {
-            noAccess = ex;
-            if (name.contains("bogus"))
-                assertTrue(noAccess instanceof NoSuchMethodException);
-            else
-                assertTrue(noAccess instanceof IllegalAccessException);
-        }
-        if (verbosity >= 3)
-            System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target
-                               +(target == null ? "" : target.type())
-                               +(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(specialCaller, target.type().parameterType(0));
-        assertEquals(type,          target.type().dropParameterTypes(0,1));
-        Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params);
-        MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
-        assertNameStringContains(target, name);
-        if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE)  return;
-        Object[] args = randomArgs(paramsWithSelf);
-        printCalled(target, name, args);
-        target.invokeWithArguments(args);
-        assertCalled(name, args);
-    }
-
-    @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;
-        Exception noAccess = null;
-        try {
-            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
-            target = lookup.in(defc).bind(receiver, methodName, type);
-        } catch (ReflectiveOperationException ex) {
-            noAccess = ex;
-            if (name.contains("bogus"))
-                assertTrue(noAccess instanceof NoSuchMethodException);
-            else
-                assertTrue(noAccess instanceof IllegalAccessException);
-        }
-        if (verbosity >= 3)
-            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.invokeWithArguments(args);
-        Object[] argsWithReceiver = cat(array(Object[].class, receiver), args);
-        assertCalled(name, argsWithReceiver);
-        if (verbosity >= 1)
-            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)) {
-            testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params);
-        }
-    }
-    void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
-        for (Object[] ac : accessCases(defc, name)) {
-            testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
-        }
-    }
-    void testUnreflectMaybeSpecial(Class<?> specialCaller,
-                                   boolean positive, Lookup lookup,
-                                   Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
-        countTest(positive);
-        MethodType type = MethodType.methodType(ret, params);
-        Method rmethod = defc.getDeclaredMethod(name, params);
-        MethodHandle target = null;
-        Exception noAccess = null;
-        boolean isStatic = (rcvc == null);
-        boolean isSpecial = (specialCaller != null);
-        try {
-            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
-            if (isSpecial)
-                target = lookup.in(specialCaller).unreflectSpecial(rmethod, specialCaller);
-            else
-                target = lookup.in(defc).unreflect(rmethod);
-        } catch (ReflectiveOperationException ex) {
-            noAccess = ex;
-            if (name.contains("bogus"))
-                assertTrue(noAccess instanceof NoSuchMethodException);
-            else
-                assertTrue(noAccess instanceof IllegalAccessException);
-        }
-        if (verbosity >= 3)
-            System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type
-                               +(!isSpecial ? "" : " specialCaller="+specialCaller)
-                               +( isStatic  ? "" : " receiver="+rcvc)
-                               +" => "+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(isStatic, Modifier.isStatic(rmethod.getModifiers()));
-        Class<?>[] paramsMaybeWithSelf = params;
-        if (!isStatic) {
-            paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params);
-        }
-        MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf);
-        if (isStatic) {
-            assertEquals(typeMaybeWithSelf, target.type());
-        } else {
-            if (isSpecial)
-                assertEquals(specialCaller, target.type().parameterType(0));
-            else
-                assertEquals(defc, target.type().parameterType(0));
-            assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc));
-        }
-        Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf);
-        printCalled(target, name, argsMaybeWithSelf);
-        target.invokeWithArguments(argsMaybeWithSelf);
-        assertCalled(name, argsMaybeWithSelf);
-        if (verbosity >= 1)
-            System.out.print(':');
-    }
-
-    void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
-        for (Object[] ac : accessCases(defc, name, true)) {
-            Class<?> specialCaller = rcvc;
-            testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
-        }
-    }
-
-    @Test
-    public void testUnreflectSpecial() throws Throwable {
-        if (CAN_SKIP_WORKING)  return;
-        startTest("unreflectSpecial");
-        testUnreflectSpecial(Example.class,    Example.class, void.class, "v0");
-        testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0");
-        testUnreflectSpecial(Example.class,    Example.class, void.class, "pkg_v0");
-        testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0");
-        testUnreflectSpecial(Example.class,    Example.class, Object.class, "v2", int.class, int.class);
-        testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class);
-        testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0");
-    }
-
-    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++;
-                        assertTrue(value.equals(v));
-                    }
-                    assertTrue(name.equals(field.getName()));
-                    assertTrue(type.equals(field.getType()));
-                    assertTrue(isStatic == (Modifier.isStatic(field.getModifiers())));
-                    cases.add(new Object[]{ field, value });
-                }
-            }
-            cases.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class });
-            cases.add(new Object[]{ new Object[]{ true,  HasFields.class, "bogus_sL", Object.class }, Error.class });
-            CASES = cases.toArray(new Object[0][]);
-        }
-    }
-
-    static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC = 3, TEST_SETTER = 0x10;
-    static boolean testModeMatches(int testMode, boolean isStatic) {
-        switch (testMode) {
-        case TEST_FIND_STATIC:          return isStatic;
-        case TEST_FIND_FIELD:           return !isStatic;
-        case TEST_UNREFLECT:            return true;  // unreflect matches both
-        }
-        throw new InternalError("testMode="+testMode);
-    }
-
-    @Test
-    public void testUnreflectGetter() throws Throwable {
-        startTest("unreflectGetter");
-        testGetter(TEST_UNREFLECT);
-    }
-    @Test
-    public void testFindGetter() throws Throwable {
-        startTest("findGetter");
-        testGetter(TEST_FIND_FIELD);
-    }
-    @Test
-    public void testFindStaticGetter() throws Throwable {
-        startTest("findStaticGetter");
-        testGetter(TEST_FIND_STATIC);
-    }
-    public void testGetter(int testMode) throws Throwable {
-        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
-        for (Object[] c : HasFields.CASES) {
-            boolean positive = (c[1] != Error.class);
-            testGetter(positive, lookup, c[0], c[1], testMode);
-        }
-        testGetter(true, lookup,
-                   new Object[]{ true,  System.class, "out", java.io.PrintStream.class },
-                   System.out, testMode);
-        for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
-            testGetter(false, lookup,
-                       new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
-                       null, testMode);
-        }
-    }
-    public void testGetter(boolean positive, MethodHandles.Lookup lookup,
-                           Object fieldRef, Object value, int testMode) throws Throwable {
-        testAccessor(positive, lookup, fieldRef, value, testMode);
-    }
-
-    public void testAccessor(boolean positive, MethodHandles.Lookup lookup,
-                             Object fieldRef, Object value, int testMode0) throws Throwable {
-        boolean isGetter = ((testMode0 & TEST_SETTER) == 0);
-        int testMode = testMode0 & ~TEST_SETTER;
-        boolean isStatic;
-        Class<?> fclass;
-        String   fname;
-        Class<?> ftype;
-        Field f = (fieldRef instanceof Field ? (Field)fieldRef : null);
-        if (f != null) {
-            isStatic = Modifier.isStatic(f.getModifiers());
-            fclass   = f.getDeclaringClass();
-            fname    = f.getName();
-            ftype    = f.getType();
-        } else {
-            Object[] scnt = (Object[]) fieldRef;
-            isStatic = (Boolean)  scnt[0];
-            fclass   = (Class<?>) scnt[1];
-            fname    = (String)   scnt[2];
-            ftype    = (Class<?>) scnt[3];
-            try {
-                f = fclass.getDeclaredField(fname);
-            } catch (ReflectiveOperationException ex) {
-                f = null;
-            }
-        }
-        if (!testModeMatches(testMode, isStatic))  return;
-        if (f == null && testMode == TEST_UNREFLECT)  return;
-        countTest(positive);
-        MethodType expType;
-        if (isGetter)
-            expType = MethodType.methodType(ftype, HasFields.class);
-        else
-            expType = MethodType.methodType(void.class, HasFields.class, ftype);
-        if (isStatic)  expType = expType.dropParameterTypes(0, 1);
-        Exception noAccess = null;
-        MethodHandle mh;
-        try {
-            switch (testMode0) {
-            case TEST_UNREFLECT:   mh = lookup.unreflectGetter(f);                      break;
-            case TEST_FIND_FIELD:  mh = lookup.findGetter(fclass, fname, ftype);        break;
-            case TEST_FIND_STATIC: mh = lookup.findStaticGetter(fclass, fname, ftype);  break;
-            case TEST_SETTER|
-                 TEST_UNREFLECT:   mh = lookup.unreflectSetter(f);                      break;
-            case TEST_SETTER|
-                 TEST_FIND_FIELD:  mh = lookup.findSetter(fclass, fname, ftype);        break;
-            case TEST_SETTER|
-                 TEST_FIND_STATIC: mh = lookup.findStaticSetter(fclass, fname, ftype);  break;
-            default:
-                throw new InternalError("testMode="+testMode);
-            }
-        } catch (ReflectiveOperationException ex) {
-            mh = null;
-            noAccess = ex;
-            if (fname.contains("bogus"))
-                assertTrue(noAccess instanceof NoSuchFieldException);
-            else
-                assertTrue(noAccess instanceof IllegalAccessException);
-        }
-        if (verbosity >= 3)
-            System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype
-                               +" => "+mh
-                               +(noAccess == null ? "" : " !! "+noAccess));
-        if (positive && noAccess != null)  throw new RuntimeException(noAccess);
-        assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, mh != null);
-        if (!positive)  return; // negative test failed as expected
-        assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount());
-
-
-        assertSame(mh.type(), expType);
-        assertNameStringContains(mh, fname);
-        HasFields fields = new HasFields();
-        Object sawValue;
-        Class<?> vtype = ftype;
-        if (ftype != int.class)  vtype = Object.class;
-        if (isGetter) {
-            mh = MethodHandles.convertArguments(mh, mh.type().generic()
-                                                .changeReturnType(vtype));
-        } else {
-            int last = mh.type().parameterCount() - 1;
-            mh = MethodHandles.convertArguments(mh, mh.type().generic()
-                                                .changeReturnType(void.class)
-                                                .changeParameterType(last, vtype));
-        }
-        if (f != null && f.getDeclaringClass() == HasFields.class) {
-            assertEquals(f.get(fields), value);  // clean to start with
-        }
-        if (isGetter) {
-            Object expValue = value;
-            for (int i = 0; i <= 1; i++) {
-                if (isStatic) {
-                    if (ftype == int.class)
-                        sawValue = (int) mh.invokeExact();  // do these exactly
-                    else
-                        sawValue = mh.invokeExact();
-                } else {
-                    if (ftype == int.class)
-                        sawValue = (int) mh.invokeExact((Object) fields);
-                    else
-                        sawValue = mh.invokeExact((Object) fields);
-                }
-                assertEquals(sawValue, expValue);
-                if (f != null && f.getDeclaringClass() == HasFields.class
-                    && !Modifier.isFinal(f.getModifiers())) {
-                    Object random = randomArg(ftype);
-                    f.set(fields, random);
-                    expValue = random;
-                } else {
-                    break;
-                }
-            }
-        } else {
-            for (int i = 0; i <= 1; i++) {
-                Object putValue = randomArg(ftype);
-                if (isStatic) {
-                    if (ftype == int.class)
-                        mh.invokeExact((int)putValue);  // do these exactly
-                    else
-                        mh.invokeExact(putValue);
-                } else {
-                    if (ftype == int.class)
-                        mh.invokeExact((Object) fields, (int)putValue);
-                    else
-                        mh.invokeExact((Object) fields, putValue);
-                }
-                if (f != null && f.getDeclaringClass() == HasFields.class) {
-                    assertEquals(f.get(fields), putValue);
-                }
-            }
-        }
-        if (f != null && f.getDeclaringClass() == HasFields.class) {
-            f.set(fields, value);  // put it back
-        }
-    }
-
-
-    @Test
-    public void testUnreflectSetter() throws Throwable {
-        startTest("unreflectSetter");
-        testSetter(TEST_UNREFLECT);
-    }
-    @Test
-    public void testFindSetter() throws Throwable {
-        startTest("findSetter");
-        testSetter(TEST_FIND_FIELD);
-    }
-    @Test
-    public void testFindStaticSetter() throws Throwable {
-        startTest("findStaticSetter");
-        testSetter(TEST_FIND_STATIC);
-    }
-    public void testSetter(int testMode) throws Throwable {
-        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
-        startTest("unreflectSetter");
-        for (Object[] c : HasFields.CASES) {
-            boolean positive = (c[1] != Error.class);
-            testSetter(positive, lookup, c[0], c[1], testMode);
-        }
-        for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
-            testSetter(false, lookup,
-                       new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
-                       null, testMode);
-        }
-    }
-    public void testSetter(boolean positive, MethodHandles.Lookup lookup,
-                           Object fieldRef, Object value, int testMode) throws Throwable {
-        testAccessor(positive, lookup, fieldRef, value, testMode | TEST_SETTER);
-    }
-
-    @Test
-    public void testArrayElementGetter() throws Throwable {
-        startTest("arrayElementGetter");
-        testArrayElementGetterSetter(false);
-    }
-
-    @Test
-    public void testArrayElementSetter() throws Throwable {
-        startTest("arrayElementSetter");
-        testArrayElementGetterSetter(true);
-    }
-
-    public void testArrayElementGetterSetter(boolean testSetter) throws Throwable {
-        testArrayElementGetterSetter(new Object[10], testSetter);
-        testArrayElementGetterSetter(new String[10], testSetter);
-        testArrayElementGetterSetter(new boolean[10], testSetter);
-        testArrayElementGetterSetter(new byte[10], testSetter);
-        testArrayElementGetterSetter(new char[10], testSetter);
-        testArrayElementGetterSetter(new short[10], testSetter);
-        testArrayElementGetterSetter(new int[10], testSetter);
-        testArrayElementGetterSetter(new float[10], testSetter);
-        testArrayElementGetterSetter(new long[10], testSetter);
-        testArrayElementGetterSetter(new double[10], testSetter);
-    }
-
-    public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
-        countTest(true);
-        if (verbosity >= 2)  System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]");
-        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);
-        if (elemType != int.class && elemType != boolean.class) {
-            MethodType gtype;
-            if (true) { // FIXME: remove this path (and remove <void> below in the mh.invokes)
-                gtype = mh.type().changeParameterType(0, Object.class);
-                if (testSetter)
-                    gtype = gtype.changeParameterType(2, Object.class);
-                else
-                    gtype = gtype.changeReturnType(Object.class);
-            } else
-                // FIXME: This simpler path hits a bug in convertArguments => ToGeneric
-                gtype = mh.type().generic().changeParameterType(1, int.class);
-            mh = MethodHandles.convertArguments(mh, gtype);
-        }
-        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.invokeExact((int[]) array, i, (int)random);
-                else if (elemType == boolean.class)
-                    mh.invokeExact((boolean[]) array, i, (boolean)random);
-                else
-                    mh.invokeExact(array, i, random);
-                assertEquals(model, array2list(array));
-            } else {
-                Array.set(array, i, random);
-            }
-            if (verbosity >= 5) {
-                List<Object> array2list = array2list(array);
-                System.out.println("a["+i+"]="+random+" => "+array2list);
-                if (!array2list.equals(model))
-                    System.out.println("***   != "+model);
-            }
-            // observe array element
-            sawValue = Array.get(array, i);
-            if (!testSetter) {
-                expValue = sawValue;
-                if (elemType == int.class)
-                    sawValue = (int) mh.invokeExact((int[]) array, i);
-                else if (elemType == boolean.class)
-                    sawValue = (boolean) mh.invokeExact((boolean[]) array, i);
-                else
-                    sawValue = mh.invokeExact(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";
-            try {
-                return PRIVATE.findStatic(Callee.class, name, type);
-            } catch (Exception ex) {
-                throw new RuntimeException(ex);
-            }
-        }
-    }
-
-    @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);
-        testConvert(Callee.ofType(1), null, "id", char.class);
-        testConvert(Callee.ofType(1), null, "id", byte.class);
-    }
-
-    void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
-        testConvert(true, false, id, rtype, name, params);
-        testConvert(true, true,  id, rtype, name, params);
-    }
-
-    void testConvert(boolean positive, boolean useAsType,
-                     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.invokeWithArguments(convArgs);
-        {
-            Class<?> dst = newType.returnType();
-            Class<?> src = idType.returnType();
-            if (src != dst)
-                convResult = castToWrapper(convResult, dst);
-        }
-        MethodHandle target = null;
-        RuntimeException error = null;
-        try {
-            if (useAsType)
-                target = id.asType(newType);
-            else
-                target = MethodHandles.convertArguments(id, newType);
-        } catch (RuntimeException ex) {
-            error = ex;
-        }
-        if (verbosity >= 3)
-            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.invokeWithArguments(args);
-        assertCalled(name, convArgs);
-        assertEquals(convResult, result);
-        if (verbosity >= 1)
-            System.out.print(':');
-    }
-
-    @Test
-    public void testVarargsCollector() throws Throwable {
-        MethodHandle vac0 = PRIVATE.findStatic(MethodHandlesTest.class, "called",
-                               MethodType.methodType(Object.class, String.class, Object[].class));
-        vac0 = vac0.bindTo("vac");
-        MethodHandle vac = vac0.asVarargsCollector(Object[].class);
-        testConvert(true,  true,  vac.asType(MethodType.genericMethodType(0)), null, "vac");
-        testConvert(true,  true,  vac.asType(MethodType.genericMethodType(0)), null, "vac");
-        for (Class<?> at : new Class[] { Object.class, String.class, Integer.class }) {
-            testConvert(true,  true,  vac.asType(MethodType.genericMethodType(1)), null, "vac", at);
-            testConvert(true,  true,  vac.asType(MethodType.genericMethodType(2)), null, "vac", at, at);
-        }
-    }
-
-    @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 >= 2)
-            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;
-        assertTrue(inargs == types.length);
-        if (verbosity >= 3)
-            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 >= 4) {
-            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(varargsList(outargs), outType);
-        MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
-        Object result = newTarget.invokeWithArguments(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 >= 3)
-                System.out.println("spreadArguments "+argType);
-            // FIXME: enable _adapter_spread_args and fix Fail_2
-            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 = varargsArray(nargs);
-        MethodHandle target2 = changeArgTypes(target, argType);
-        if (verbosity >= 3)
-            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.invokeWithArguments(args);
-            assertArrayEquals(args, check);
-            switch (nargs) {
-                case 0:
-                    check = (Object[]) target.invokeExact();
-                    assertArrayEquals(args, check);
-                    break;
-                case 1:
-                    check = (Object[]) target.invokeExact(args[0]);
-                    assertArrayEquals(args, check);
-                    break;
-                case 2:
-                    check = (Object[]) target.invokeExact(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 = target2.asSpreader(Object[].class, nargs-pos).asType(newType);
-        Object[] returnValue;
-        if (pos == 0) {
-            // In the following line, the first cast implies
-            // normal Object return value for the MH call (Object[])->Object,
-            // while the second cast dynamically converts to an Object array.
-            // Such a double cast is typical of MH.invokeExact.
-            returnValue = (Object[]) (Object) result.invokeExact(args);
-        } else {
-            Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
-            args1[pos] = Arrays.copyOfRange(args, pos, args.length);
-            returnValue = (Object[]) result.invokeWithArguments(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 >= 3)
-                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 = 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 = varargsArray(pos+1);
-        target = changeArgTypes(target, 0, pos, argType);
-        target = changeArgTypes(target, pos, pos+1, Object[].class);
-        if (verbosity >= 3)
-            System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
-        MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType);
-        Object[] returnValue = (Object[]) result.invokeWithArguments(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 = 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 >= 3)
-            System.out.println("insert: "+argsToInsert+" into "+target);
-        MethodHandle target2 = MethodHandles.insertArguments(target, pos,
-                (Object[]) argsToInsert.toArray());
-        argsToInsert.clear();  // remove from argsToInsert
-        Object res2 = target2.invokeWithArguments(argsToPass);
-        Object res2List = Arrays.asList((Object[])res2);
-        if (verbosity >= 3)
-            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 testFilterReturnValue() throws Throwable {
-        if (CAN_SKIP_WORKING)  return;
-        startTest("filterReturnValue");
-        Class<?> classOfVCList = varargsList(1).invokeWithArguments(0).getClass();
-        assertTrue(List.class.isAssignableFrom(classOfVCList));
-        for (int nargs = 0; nargs <= 3; nargs++) {
-            for (Class<?> rtype : new Class[] { Object.class,
-                                                List.class,
-                                                int.class,
-                                                //byte.class, //FIXME: add this
-                                                //long.class, //FIXME: add this
-                                                CharSequence.class,
-                                                String.class }) {
-                testFilterReturnValue(nargs, rtype);
-            }
-        }
-    }
-
-    void testFilterReturnValue(int nargs, Class<?> rtype) throws Throwable {
-        countTest();
-        MethodHandle target = varargsList(nargs, rtype);
-        MethodHandle filter;
-        if (List.class.isAssignableFrom(rtype) || rtype.isAssignableFrom(List.class))
-            filter = varargsList(1);  // add another layer of list-ness
-        else
-            filter = MethodHandles.identity(rtype);
-        filter = filter.asType(MethodType.methodType(target.type().returnType(), rtype));
-        Object[] argsToPass = randomArgs(nargs, Object.class);
-        if (verbosity >= 3)
-            System.out.println("filter "+target+" to "+rtype.getSimpleName()+" with "+filter);
-        MethodHandle target2 = MethodHandles.filterReturnValue(target, filter);
-        if (verbosity >= 4)
-            System.out.println("filtered target: "+target2);
-        // Simulate expected effect of filter on return value:
-        Object unfiltered = target.invokeWithArguments(argsToPass);
-        Object expected = filter.invokeWithArguments(unfiltered);
-        if (verbosity >= 4)
-            System.out.println("unfiltered: "+unfiltered+" : "+unfiltered.getClass().getSimpleName());
-        if (verbosity >= 4)
-            System.out.println("expected: "+expected+" : "+expected.getClass().getSimpleName());
-        Object result = target2.invokeWithArguments(argsToPass);
-        if (verbosity >= 3)
-            System.out.println("result: "+result+" : "+result.getClass().getSimpleName());
-        if (!expected.equals(result))
-            System.out.println("*** fail at n/rt = "+nargs+"/"+rtype.getSimpleName()+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
-        assertEquals(expected, result);
-    }
-
-    @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 = varargsList(nargs);
-        MethodHandle filter = varargsList(1);
-        filter = MethodHandles.convertArguments(filter, filter.type().generic());
-        Object[] argsToPass = randomArgs(nargs, Object.class);
-        if (verbosity >= 3)
-            System.out.println("filter "+target+" at "+pos+" with "+filter);
-        MethodHandle target2 = MethodHandles.filterArguments(target, pos, filter);
-        // Simulate expected effect of filter on arglist:
-        Object[] filteredArgs = argsToPass.clone();
-        filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]);
-        List<Object> expected = Arrays.asList(filteredArgs);
-        Object result = target2.invokeWithArguments(argsToPass);
-        if (verbosity >= 3)
-            System.out.println("result: "+result);
-        if (!expected.equals(result))
-            System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
-        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 = varargsList(1 + nargs);
-        MethodHandle combine = varargsList(fold).asType(MethodType.genericMethodType(fold));
-        List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
-        if (verbosity >= 3)
-            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 >= 3)
-            System.out.println("fold: "+argsToFold+" into "+target2);
-        Object foldedArgs = combine.invokeWithArguments(argsToFold);
-        argsToFold.add(0, foldedArgs);
-        Object result = target2.invokeWithArguments(argsToPass);
-        if (verbosity >= 3)
-            System.out.println("result: "+result);
-        if (!expected.equals(result))
-            System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected);
-        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 = 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.invokeWithArguments(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 >= 3)
-            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));
-        assertTrue(target.isVarargsCollector());
-        target = target.asType(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.invokeWithArguments(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.invokeExact(target);
-                break;
-            case 1:
-                result = inv.invokeExact(target, args[0]);
-                break;
-            case 2:
-                result = inv.invokeExact(target, args[0], args[1]);
-                break;
-            case 3:
-                result = inv.invokeExact(target, args[0], args[1], args[2]);
-                break;
-            }
-            if (testRetCode)  assertEquals(code, result);
-            assertCalled("invokee", args);
-        }
-        calledLog.clear();
-        result = inv.invokeWithArguments(targetPlusArgs);
-        if (testRetCode)  assertEquals(code, result);
-        assertCalled("invokee", args);
-        // varargs invoker #0
-        calledLog.clear();
-        inv = MethodHandles.spreadInvoker(type, 0);
-        result = inv.invokeExact(target, args);
-        if (testRetCode)  assertEquals(code, result);
-        assertCalled("invokee", args);
-        if (nargs >= 1) {
-            // varargs invoker #1
-            calledLog.clear();
-            inv = MethodHandles.spreadInvoker(type, 1);
-            result = inv.invokeExact(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.spreadInvoker(type, 2);
-            result = inv.invokeExact(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.spreadInvoker(type, 3);
-            result = inv.invokeExact(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.spreadInvoker(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.invokeWithArguments(targetPlusVarArgs);
-            if (testRetCode)  assertEquals(code, result);
-            assertCalled("invokee", args);
-        }
-
-        // dynamic invoker
-        countTest();
-        CallSite site = new MutableCallSite(type);
-        inv = site.dynamicInvoker();
-
-        // see if we get the result of the original target:
-        try {
-            result = inv.invokeWithArguments(args);
-            assertTrue("should not reach here", false);
-        } catch (IllegalStateException ex) {
-            String msg = ex.getMessage();
-            assertTrue(msg, msg.contains("site"));
-        }
-
-        // set new target after invoker is created, to make sure we track target
-        site.setTarget(target);
-        calledLog.clear();
-        result = inv.invokeWithArguments(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 >= 3)
-                System.out.println(logEntry(willCall, argList));
-            Object result = mh.invokeWithArguments(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 >= 3)
-            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.asType(MethodType.genericMethodType(2));
-        while (thrower.type().parameterCount() < nargs)
-            thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class);
-        MethodHandle catcher = varargsList(1+nargs).asType(MethodType.genericMethodType(1+nargs));
-        MethodHandle target = MethodHandles.catchException(thrower,
-                thrown.getClass(), catcher);
-        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.invokeWithArguments(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());
-        target = MethodHandles.convertArguments(target, target.type().generic());
-        Throwable caught = null;
-        try {
-            Object res = target.invokeExact((Object) 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 {
-        public MethodHandle asMethodHandle() {
-            return VALUE.bindTo(this);
-        }
-        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 VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY;
-        static {
-            try {
-                VALUE = PRIVATE.findVirtual(
-                    Surprise.class, "value",
-                        MethodType.methodType(Object.class, Object.class));
-                REF_IDENTITY = PRIVATE.findStatic(
-                    Surprise.class, "refIdentity",
-                        MethodType.methodType(Object.class, Object.class));
-                BOX_IDENTITY = PRIVATE.findStatic(
-                    Surprise.class, "boxIdentity",
-                        MethodType.methodType(Integer.class, Integer.class));
-                INT_IDENTITY = PRIVATE.findStatic(
-                    Surprise.class, "intIdentity",
-                        MethodType.methodType(int.class, int.class));
-            } catch (Exception ex) {
-                throw new RuntimeException(ex);
-            }
-        }
-    }
-
-    void testCastFailure(String mode, int okCount) throws Throwable {
-        countTest(false);
-        if (verbosity > 2)  System.out.println("mode="+mode);
-        Surprise boo = new Surprise();
-        MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0;
-        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, 0, surprise);
-                identity = MethodHandles.filterArguments(callee, 0, identity);
-            }
-        }
-        assertNotSame(mode, surprise, surprise0);
-        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.invokeExact(x);
-            assertEquals(x, y);
-            Object z = surprise.invokeExact(x);
-            assertEquals(x, z);
-        }
-        boo.boo("Boo!");
-        Object y = identity.invokeExact(x);
-        assertEquals(x, y);
-        try {
-            Object z = surprise.invokeExact(x);
-            System.out.println("Failed to throw; got z="+z);
-            assertTrue(false);
-        } catch (Exception ex) {
-            if (verbosity > 2)
-                System.out.println("caught "+ex);
-            if (verbosity > 3)
-                ex.printStackTrace();
-            assertTrue(ex instanceof ClassCastException
-                    // FIXME: accept only one of the two for any given unit test
-                    || ex instanceof WrongMethodTypeException
-                    );
-        }
-    }
-
-    static Example userMethod(Object o, String s, int i) {
-        called("userMethod", o, s, i);
-        return null;
-    }
-
-    @Test
-    public void testUserClassInSignature() throws Throwable {
-        if (CAN_SKIP_WORKING)  return;
-        startTest("testUserClassInSignature");
-        Lookup lookup = MethodHandles.lookup();
-        String name; MethodType mt; MethodHandle mh;
-        Object[] args;
-
-        // Try a static method.
-        name = "userMethod";
-        mt = MethodType.methodType(Example.class, Object.class, String.class, int.class);
-        mh = lookup.findStatic(lookup.lookupClass(), name, mt);
-        assertEquals(mt, mh.type());
-        assertEquals(Example.class, mh.type().returnType());
-        args = randomArgs(mh.type().parameterArray());
-        mh.invokeWithArguments(args);
-        assertCalled(name, args);
-
-        // Try a virtual method.
-        name = "v2";
-        mt = MethodType.methodType(Object.class, Object.class, int.class);
-        mh = lookup.findVirtual(Example.class, name, mt);
-        assertEquals(mt, mh.type().dropParameterTypes(0,1));
-        assertTrue(mh.type().parameterList().contains(Example.class));
-        args = randomArgs(mh.type().parameterArray());
-        mh.invokeWithArguments(args);
-        assertCalled(name, args);
-    }
-
-    static void runForRunnable() {
-        called("runForRunnable");
-    }
-    private interface Fooable {
-        Object foo(Fooable x, Object y);
-        // this is for randomArg:
-        public class Impl implements Fooable {
-            public Object foo(Fooable x, Object y) {
-                throw new RuntimeException("do not call");
-            }
-            final String name;
-            public Impl() { name = "Fooable#"+nextArg(); }
-            @Override public String toString() { return name; }
-        }
-    }
-    static Object fooForFooable(Fooable x, Object y) {
-        return called("fooForFooable", x, y);
-    }
-    private static class MyCheckedException extends Exception {
-    }
-    private interface WillThrow {
-        void willThrow() throws MyCheckedException;
-    }
-
-    @Test
-    public void testAsInstance() throws Throwable {
-        if (CAN_SKIP_WORKING)  return;
-        Lookup lookup = MethodHandles.lookup();
-        {
-            MethodType mt = MethodType.methodType(void.class);
-            MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt);
-            Runnable proxy = MethodHandles.asInstance(mh, Runnable.class);
-            proxy.run();
-            assertCalled("runForRunnable");
-        }
-        {
-            MethodType mt = MethodType.methodType(Object.class, Fooable.class, Object.class);
-            MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", mt);
-            Fooable proxy = MethodHandles.asInstance(mh, Fooable.class);
-            Object[] args = randomArgs(mt.parameterArray());
-            Object result = proxy.foo((Fooable) args[0], args[1]);
-            assertCalled("fooForFooable", args);
-            assertEquals(result, logEntry("fooForFooable", args));
-        }
-        for (Throwable ex : new Throwable[] { new NullPointerException("ok"),
-                                              new InternalError("ok"),
-                                              new Throwable("fail"),
-                                              new Exception("fail"),
-                                              new MyCheckedException()
-                                            }) {
-            MethodHandle mh = MethodHandles.throwException(void.class, Throwable.class);
-            mh = MethodHandles.insertArguments(mh, 0, ex);
-            WillThrow proxy = MethodHandles.asInstance(mh, WillThrow.class);
-            try {
-                proxy.willThrow();
-                System.out.println("Failed to throw: "+ex);
-                assertTrue(false);
-            } catch (Throwable ex1) {
-                if (verbosity > 2) {
-                    System.out.println("throw "+ex);
-                    System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1));
-                }
-                if (ex instanceof RuntimeException ||
-                    ex instanceof Error) {
-                    assertSame("must pass unchecked exception out without wrapping", ex, ex1);
-                } else if (ex instanceof MyCheckedException) {
-                    assertSame("must pass declared exception out without wrapping", ex, ex1);
-                } else {
-                    assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1);
-                    UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1;
-                    assertSame(ex, utex.getCause());
-                }
-            }
-        }
-        // Test error checking:
-        for (Class<?> nonSAM : new Class[] { Object.class,
-                                             String.class,
-                                             CharSequence.class,
-                                             Example.class }) {
-            try {
-                MethodHandles.asInstance(varargsArray(0), nonSAM);
-                System.out.println("Failed to throw");
-                assertTrue(false);
-            } catch (IllegalArgumentException ex) {
-            }
-        }
-    }
-}
-// 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 (ReflectiveOperationException ex) {
-                // break from loop!
-            }
-            if (array == null)  break;
-            arrays.add(array);
-        }
-        assertTrue(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: cannot form a varargs array of length "+nargs);
-    }
-
-    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> lists = new ArrayList<MethodHandle>();
-        MethodHandles.Lookup lookup = IMPL_LOOKUP;
-        for (;;) {
-            int nargs = lists.size();
-            MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
-            String name = "list";
-            MethodHandle list = null;
-            try {
-                list = lookup.findStatic(ValueConversions.class, name, type);
-            } catch (ReflectiveOperationException ex) {
-                // break from loop!
-            }
-            if (list == null)  break;
-            lists.add(list);
-        }
-        assertTrue(lists.size() == 11);  // current number of methods
-        return lists.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();
-    }
-}
--- a/jdk/test/java/dyn/MethodTypeTest.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,542 +0,0 @@
-/*
- * Copyright 2008, 2011 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.MethodType
- * @compile MethodTypeTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.MethodTypeTest
- */
-
-package test.java.dyn;
-
-import sun.dyn.MemberName;
-import java.dyn.MethodType;
-import java.lang.reflect.Method;
-
-import java.util.*;
-import org.junit.*;
-import static org.junit.Assert.*;
-
-/**
- *
- * @author jrose
- */
-public class MethodTypeTest {
-
-    private Class<?> rtype;
-    private Class<?>[] ptypes;
-    private MethodType mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov;
-    private MethodType mt_iSI, mt_ISi, mt_ISI, mt_iSi;
-    private MethodType mt_viO, mt_iO2, mt_OOi, mt_iOi;
-    private MethodType mt_VIO, mt_IO2, mt_OOI, mt_IOI, mt_VIS;
-    private MethodType mt_vOiSzA, mt_OO99;
-    private MethodType[] GALLERY;
-    private Method compareTo;
-
-    @Before
-    public void setUp() throws Exception {
-        rtype = void.class;
-        ptypes = new Class<?>[] { int.class, String.class };
-
-        mt_viS = MethodType.methodType(void.class, int.class, String.class);
-        mt_OO = MethodType.methodType(Object.class, Object.class);
-        mt_OO2 = MethodType.methodType(Object.class, Object.class, Object.class);
-        mt_vv = MethodType.methodType(void.class);
-        mt_Vv = MethodType.methodType(Void.class);
-        mt_Ov = MethodType.methodType(Object.class);
-        mt_iSI = MethodType.methodType(int.class, String.class, Integer.class);
-        mt_ISi = MethodType.methodType(Integer.class, String.class, int.class);
-        mt_ISI = MethodType.methodType(Integer.class, String.class, Integer.class);
-        mt_iSi = MethodType.methodType(int.class, String.class, int.class);
-
-        compareTo = String.class.getDeclaredMethod("compareTo", String.class);
-
-        mt_viO = MethodType.methodType(void.class, int.class, Object.class);
-        mt_iO2 = MethodType.methodType(int.class, Object.class, Object.class);
-        mt_OOi = MethodType.methodType(Object.class, Object.class, int.class);
-        mt_iOi = MethodType.methodType(int.class, Object.class, int.class);
-
-        mt_VIO = MethodType.methodType(Void.class, Integer.class, Object.class);
-        mt_IO2 = MethodType.methodType(Integer.class, Object.class, Object.class);
-        mt_OOI = MethodType.methodType(Object.class, Object.class, Integer.class);
-        mt_IOI = MethodType.methodType(Integer.class, Object.class, Integer.class);
-        mt_VIS = MethodType.methodType(Void.class, Integer.class, String.class);
-
-        mt_vOiSzA = MethodType.methodType(void.class, Object.class, int.class, String.class, boolean.class, Object[].class);
-        mt_OO99 = MethodType.genericMethodType(99);
-
-        GALLERY = new MethodType[] {
-            mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov,
-            mt_iSI, mt_ISi, mt_ISI, mt_iSi,
-            mt_viO, mt_iO2, mt_OOi, mt_iOi,
-            mt_VIO, mt_IO2, mt_OOI, mt_IOI,
-            mt_VIS, mt_vOiSzA, mt_OO99
-        };
-    }
-
-    @After
-    public void tearDown() throws Exception {
-    }
-
-    /** Make sure the method types are all distinct. */
-    @Test
-    public void testDistinct() {
-        List<MethodType> gallery2 = new ArrayList<>();
-        for (MethodType mt : GALLERY) {
-            assertFalse(mt.toString(), gallery2.contains(mt));
-            gallery2.add(mt);
-        }
-        // check self-equality also:
-        assertEquals(Arrays.asList(GALLERY), gallery2);
-    }
-
-    /**
-     * Test of make method, of class MethodType.
-     */
-    @Test
-    public void testMake_Class_ClassArr() {
-        System.out.println("make (from type array)");
-        MethodType result = MethodType.methodType(rtype, ptypes);
-        assertSame(mt_viS, result);
-    }
-
-    /**
-     * Test of make method, of class MethodType.
-     */
-    @Test
-    public void testMake_Class_List() {
-        System.out.println("make (from type list)");
-        MethodType result = MethodType.methodType(rtype, Arrays.asList(ptypes));
-        assertSame(mt_viS, result);
-    }
-
-    /**
-     * Test of make method, of class MethodType.
-     */
-    @Test
-    public void testMake_3args() {
-        System.out.println("make (from type with varargs)");
-        MethodType result = MethodType.methodType(rtype, ptypes[0], ptypes[1]);
-        assertSame(mt_viS, result);
-    }
-
-    /**
-     * Test of make method, of class MethodType.
-     */
-    @Test
-    public void testMake_Class() {
-        System.out.println("make (from single type)");
-        Class<?> rt = Integer.class;
-        MethodType expResult = MethodType.methodType(rt, new Class<?>[0]);
-        MethodType result = MethodType.methodType(rt);
-        assertSame(expResult, result);
-    }
-
-    @Test
-    public void testMakeGeneric() {
-        System.out.println("makeGeneric");
-        int objectArgCount = 2;
-        MethodType expResult = mt_OO2;
-        MethodType result = MethodType.genericMethodType(objectArgCount);
-        assertSame(expResult, result);
-    }
-
-    /**
-     * Test of make method, of class MethodType.
-     */
-    @Test
-    public void testMake_Method() {
-        System.out.println("make (via MemberName.getMethodType)");
-        MethodType expResult = MethodType.methodType(int.class, String.class);
-        MemberName name = new MemberName(compareTo);
-        MethodType result = name.getMethodType();
-        assertSame(expResult, result);
-    }
-
-    /**
-     * Test of make method, of class MethodType.
-     */
-    @Test
-    public void testMake_MethodType() {
-        System.out.println("make (from rtype, MethodType)");
-        MethodType expResult = mt_iO2;
-        MethodType result = MethodType.methodType(int.class, mt_IO2);
-        assertSame(expResult, result);
-    }
-
-    /**
-     * Test of make method, of class MethodType.
-     */
-    @Test
-    public void testMake_String_ClassLoader() {
-        System.out.println("make (from bytecode signature)");
-        ClassLoader loader = null;
-        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
-        String obj = "Ljava/lang/Object;";
-        assertEquals(obj, concat(Object.class));
-        String[] expResults = {
-            "(ILjava/lang/String;)V",
-            concat("(", obj, 2, ")", Object.class),
-            "()V", "()"+obj,
-            concat("(", String.class, Integer.class, ")I"),
-            concat("(", String.class, "I)", Integer.class),
-            concat("(", String.class, Integer.class, ")", Integer.class),
-            concat("(", String.class, "I)I")
-        };
-        for (int i = 0; i < instances.length; i++) {
-            MethodType instance = instances[i];
-            String result = instance.toMethodDescriptorString();
-            assertEquals("#"+i, expResults[i], result);
-            MethodType parsed = MethodType.fromMethodDescriptorString(result, loader);
-            assertSame("--#"+i, instance, parsed);
-        }
-    }
-    private static String concat(Object... parts) {
-        StringBuilder sb = new StringBuilder();
-        Object prevPart = "";
-        for (Object part : parts) {
-            if (part instanceof Class) {
-                part = "L"+((Class)part).getName()+";";
-            }
-            if (part instanceof Integer) {
-                for (int n = (Integer) part; n > 1; n--)
-                    sb.append(prevPart);
-                part = "";
-            }
-            sb.append(part);
-            prevPart = part;
-        }
-        return sb.toString().replace('.', '/');
-    }
-
-    @Test
-    public void testHasPrimitives() {
-        System.out.println("hasPrimitives");
-        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
-        boolean[] expResults =   {true,   false,  true,  false, true,   true,   false,  true};
-        for (int i = 0; i < instances.length; i++) {
-            boolean result = instances[i].hasPrimitives();
-            assertEquals("#"+i, expResults[i], result);
-        }
-    }
-
-    @Test
-    public void testHasWrappers() {
-        System.out.println("hasWrappers");
-        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
-        boolean[] expResults =   {false,  false,  false, false, true,   true,   true,   false};
-        for (int i = 0; i < instances.length; i++) {
-            System.out.println("  hasWrappers "+instances[i]);
-            boolean result = instances[i].hasWrappers();
-            assertEquals("#"+i, expResults[i], result);
-        }
-    }
-
-    @Test
-    public void testErase() {
-        System.out.println("erase");
-        MethodType[] instances  = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
-        MethodType[] expResults = {mt_viO, mt_OO2, mt_vv, mt_Ov, mt_iO2, mt_OOi, mt_OO2, mt_iOi};
-        for (int i = 0; i < instances.length; i++) {
-            MethodType result = instances[i].erase();
-            assertSame("#"+i, expResults[i], result);
-        }
-    }
-
-    @Test
-    public void testGeneric() {
-        System.out.println("generic");
-        MethodType[] instances =  {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
-        MethodType[] expResults = {mt_OO2, mt_OO2, mt_Ov, mt_Ov, mt_OO2, mt_OO2, mt_OO2, mt_OO2};
-        for (int i = 0; i < instances.length; i++) {
-            MethodType result = instances[i].generic();
-            assertSame("#"+i, expResults[i], result);
-        }
-    }
-
-    @Test
-    public void testWrap() {
-        System.out.println("wrap");
-        MethodType[] instances =  {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
-        MethodType[] expResults = {mt_VIS, mt_OO2, mt_Vv, mt_Ov, mt_ISI, mt_ISI, mt_ISI, mt_ISI};
-        for (int i = 0; i < instances.length; i++) {
-            MethodType result = instances[i].wrap();
-            assertSame("#"+i, expResults[i], result);
-        }
-    }
-
-    @Test
-    public void testUnwrap() {
-        System.out.println("unwrap");
-        MethodType[] instances =  {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
-        MethodType[] expResults = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSi, mt_iSi, mt_iSi, mt_iSi};
-        for (int i = 0; i < instances.length; i++) {
-            MethodType result = instances[i].unwrap();
-            assertSame("#"+i, expResults[i], result);
-        }
-    }
-
-    /**
-     * Test of parameterType method, of class MethodType.
-     */
-    @Test
-    public void testParameterType() {
-        System.out.println("parameterType");
-        for (int num = 0; num < ptypes.length; num++) {
-            MethodType instance = mt_viS;
-            Class<?> expResult = ptypes[num];
-            Class<?> result = instance.parameterType(num);
-            assertSame(expResult, result);
-        }
-    }
-
-    /**
-     * Test of parameterCount method, of class MethodType.
-     */
-    @Test
-    public void testParameterCount() {
-        System.out.println("parameterCount");
-        MethodType instance = mt_viS;
-        int expResult = 2;
-        int result = instance.parameterCount();
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of returnType method, of class MethodType.
-     */
-    @Test
-    public void testReturnType() {
-        System.out.println("returnType");
-        MethodType instance = mt_viS;
-        Class<?> expResult = void.class;
-        Class<?> result = instance.returnType();
-        assertSame(expResult, result);
-    }
-
-    /**
-     * Test of parameterList method, of class MethodType.
-     */
-    @Test
-    public void testParameterList() {
-        System.out.println("parameterList");
-        MethodType instance = mt_viS;
-        List<Class<?>> expResult = Arrays.asList(ptypes);
-        List<Class<?>> result = instance.parameterList();
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of parameterArray method, of class MethodType.
-     */
-    @Test
-    public void testParameterArray() {
-        System.out.println("parameterArray");
-        MethodType instance = mt_viS;
-        Class<?>[] expResult = ptypes;
-        Class<?>[] result = instance.parameterArray();
-        assertEquals(Arrays.asList(expResult), Arrays.asList(result));
-    }
-
-    /**
-     * Test of equals method, of class MethodType.
-     */
-    @Test
-    public void testEquals_Object() {
-        System.out.println("equals");
-        Object x = null;
-        MethodType instance = mt_viS;
-        boolean expResult = false;
-        boolean result = instance.equals(x);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of equals method, of class MethodType.
-     */
-    @Test
-    public void testEquals_MethodType() {
-        System.out.println("equals");
-        MethodType that = mt_viS;
-        MethodType instance = mt_viS;
-        boolean expResult = true;
-        boolean result = instance.equals(that);
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of hashCode method, of class MethodType.
-     */
-    @Test
-    public void testHashCode() {
-        System.out.println("hashCode");
-        MethodType instance = mt_viS;
-        ArrayList<Class<?>> types = new ArrayList<Class<?>>();
-        types.add(instance.returnType());
-        types.addAll(instance.parameterList());
-        int expResult = types.hashCode();
-        int result = instance.hashCode();
-        assertEquals(expResult, result);
-    }
-
-    /**
-     * Test of toString method, of class MethodType.
-     */
-    @Test
-    public void testToString() {
-        System.out.println("toString");
-        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
-        //String expResult = "void[int, class java.lang.String]";
-        String[] expResults = {
-            "(int,String)void",
-            "(Object,Object)Object",
-            "()void",
-            "()Object",
-            "(String,Integer)int",
-            "(String,int)Integer",
-            "(String,Integer)Integer",
-            "(String,int)int"
-        };
-        for (int i = 0; i < instances.length; i++) {
-            MethodType instance = instances[i];
-            String result = instance.toString();
-            System.out.println("#"+i+":"+result);
-            assertEquals("#"+i, expResults[i], result);
-        }
-    }
-
-    private static byte[] writeSerial(Object x) throws java.io.IOException {
-        try (java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
-             java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(bout)
-             ) {
-            out.writeObject(x);
-            out.flush();
-            return bout.toByteArray();
-        }
-    }
-    private static Object readSerial(byte[] wire) throws java.io.IOException, ClassNotFoundException {
-        try (java.io.ByteArrayInputStream bin = new java.io.ByteArrayInputStream(wire);
-             java.io.ObjectInputStream in = new java.io.ObjectInputStream(bin)) {
-            return in.readObject();
-        }
-    }
-    private static void testSerializedEquality(Object x) throws java.io.IOException, ClassNotFoundException {
-        if (x instanceof Object[])
-            x = Arrays.asList((Object[]) x);  // has proper equals method
-        byte[] wire = writeSerial(x);
-        Object y = readSerial(wire);
-        assertEquals(x, y);
-    }
-
-    /** Test (de-)serialization. */
-    @Test
-    public void testSerialization() throws Throwable {
-        System.out.println("serialization");
-        for (MethodType mt : GALLERY) {
-            testSerializedEquality(mt);
-        }
-        testSerializedEquality(GALLERY);
-
-        // Make a list of mixed objects:
-        List<Object> stuff = new ArrayList<>();
-        Collections.addAll(stuff, GALLERY);  // copy #1
-        Object[] triples = Arrays.copyOfRange(GALLERY, 0, GALLERY.length/2);
-        Collections.addAll(stuff, triples);  // copy #3 (partial)
-        for (MethodType mt : GALLERY) {
-            Collections.addAll(stuff, mt.parameterArray());
-        }
-        Collections.shuffle(stuff, new Random(292));
-        Collections.addAll(stuff, GALLERY);  // copy #2
-        testSerializedEquality(stuff);
-    }
-
-    /** Test serialization formats. */
-    @Test
-    public void testPortableSerialFormat() throws Throwable {
-        System.out.println("portable serial format");
-        Object[][] cases = {
-            { mt_vv, new byte[] {  // ()void
-                    (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13,
-                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x64, (byte)0x79, (byte)0x6e,
-                    (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
-                    (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
-                    (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
-                    (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x6f, (byte)0x69, (byte)0x64,
-                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
-                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00,
-                    (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e,
-                    (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61,
-                    (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab, (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb,
-                    (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
-                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
-                } },
-            { mt_OO, new byte[] {  // (Object)Object
-                    (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13,
-                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x64, (byte)0x79, (byte)0x6e,
-                    (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
-                    (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
-                    (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
-                    (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61,
-                    (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62,
-                    (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
-                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
-                    (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00, (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a,
-                    (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
-                    (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61, (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab,
-                    (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb, (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02,
-                    (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01,
-                    (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x03, (byte)0x78,
-                } },
-        };
-        boolean generateData = false;
-        //generateData = true;
-        for (Object[] c : cases) {
-            MethodType mt = (MethodType) c[0];
-            System.out.println("deserialize "+mt);
-            byte[] wire = (byte[]) c[1];
-            if (generateData) {
-                wire = writeSerial(mt);
-                final String INDENT = "                ";
-                System.out.print("{  // "+mt);
-                for (int i = 0; i < wire.length; i++) {
-                    if (i % 8 == 0) { System.out.println(); System.out.print(INDENT+"   "); }
-                    String hex = Integer.toHexString(wire[i] & 0xFF);
-                    if (hex.length() == 1)  hex = "0"+hex;
-                    System.out.print(" (byte)0x"+hex+",");
-                }
-                System.out.println();
-                System.out.println(INDENT+"}");
-                System.out.flush();
-            }
-            Object decode;
-            try {
-                decode = readSerial(wire);
-            } catch (Exception ex) {
-                decode = ex;  // oops!
-            }
-            assertEquals(mt, decode);
-        }
-    }
-}
--- a/jdk/test/java/dyn/indify/Indify.java	Wed Jul 05 17:38:31 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1890 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package indify;
-
-import java.util.*;
-import java.io.*;
-import java.lang.reflect.Modifier;
-import java.util.regex.*;
-
-/**
- * Transform one or more class files to incorporate JSR 292 features,
- * such as {@code invokedynamic}.
- * <p>
- * This is a standalone program in a single source file.
- * In this form, it may be useful for test harnesses, small experiments, and javadoc examples.
- * Copies of this file may show up in multiple locations for standalone usage.
- * The primary maintained location of this file is as follows:
- * <a href="http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java">
- * http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java</a>
- * <p>
- * Static private methods named MH_x and MT_x (where x is arbitrary)
- * must be stereotyped generators of MethodHandle and MethodType
- * constants.  All calls to them are transformed to {@code CONSTANT_MethodHandle}
- * and {@code CONSTANT_MethodType} "ldc" instructions.
- * The stereotyped code must create method types by calls to {@code methodType} or
- * {@code fromMethodDescriptorString}.  The "lookup" argument must be created
- * by calls to {@code java.dyn.MethodHandles#lookup MethodHandles.lookup}.
- * The class and string arguments must be constant.
- * The following methods of {@code java.dyn.MethodHandle.Lookup Lookup} are
- * allowed for method handle creation: {@code findStatic}, {@code findVirtual},
- * {@code findConstructor}, {@code findSpecial},
- * {@code findGetter}, {@code findSetter},
- * {@code findStaticGetter}, or {@code findStaticSetter}.
- * The call to one of these methods must be followed immediately
- * by an {@code areturn} instruction.
- * The net result of the call to the MH_x or MT_x method must be
- * the creation of a constant method handle.  Thus, replacing calls
- * to MH_x or MT_x methods by {@code ldc} instructions should leave
- * the meaning of the program unchanged.
- * <p>
- * Static private methods named INDY_x must be stereotyped generators
- * of {@code invokedynamic} call sites.
- * All calls to them must be immediately followed by
- * {@code invokeExact} calls.
- * All such pairs of calls are transformed to {@code invokedynamic}
- * instructions.  Each INDY_x method must begin with a call to a
- * MH_x method, which is taken to be its bootstrap method.
- * The method must be immediately invoked (via {@code invokeGeneric}
- * on constant lookup, name, and type arguments.  An object array of
- * constants may also be appended to the {@code invokeGeneric call}.
- * This call must be cast to {@code CallSite}, and the result must be
- * immediately followed by a call to {@code dynamicInvoker}, with the
- * resulting method handle returned.
- * <p>
- * The net result of all of these actions is equivalent to the JVM's
- * execution of an {@code invokedynamic} instruction in the unlinked state.
- * Running this code once should produce the same results as running
- * the corresponding {@code invokedynamic} instruction.
- * In order to model the caching behavior, the code of an INDY_x
- * method is allowed to begin with getstatic, aaload, and if_acmpne
- * instructions which load a static method handle value and return it
- * if the value is non-null.
- * <p>
- * Example usage:
- * <blockquote><pre>
-$ JAVA_HOME=(some recent OpenJDK 7 build)
-$ ant
-$ $JAVA_HOME/bin/java -cp build/classes indify.Indify --overwrite --dest build/testout build/classes/indify/Example.class
-$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/classes indify.Example
-MT = (java.lang.Object)java.lang.Object
-MH = adder(int,int)java.lang.Integer
-adder(1,2) = 3
-calling indy:  42
-$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/testout indify.Example
-(same output as above)
- * </pre></blockquote>
- * <p>
- * Before OpenJDK build b123, the format of {@code CONSTANT_InvokeDynamic} is in transition,
- * and the switch {@code --transitionalJSR292=yes} is recommended.
- * It is turned <em>off</em> by default, but users of earlier builds may need to turn it on.
- * <p>
- * A version of this transformation built on top of <a href="http://asm.ow2.org/">http://asm.ow2.org/</a> would be welcome.
- * @author John Rose
- */
-public class Indify {
-    public static void main(String... av) throws IOException {
-        new Indify().run(av);
-    }
-
-    public File dest;
-    public String[] classpath = {"."};
-    public boolean keepgoing = false;
-    public boolean expandProperties = false;
-    public boolean overwrite = false;
-    public boolean quiet = false;
-    public boolean verbose = false;
-    public boolean transitionalJSR292 = false;  // final version is distributed
-    public boolean all = false;
-    public int verifySpecifierCount = -1;
-
-    public void run(String... av) throws IOException {
-        List<String> avl = new ArrayList<>(Arrays.asList(av));
-        parseOptions(avl);
-        if (avl.isEmpty())
-            throw new IllegalArgumentException("Usage: indify [--dest dir] [option...] file...");
-        if ("--java".equals(avl.get(0))) {
-            avl.remove(0);
-            try {
-                runApplication(avl.toArray(new String[0]));
-            } catch (Exception ex) {
-                if (ex instanceof RuntimeException)  throw (RuntimeException) ex;
-                throw new RuntimeException(ex);
-            }
-            return;
-        }
-        Exception err = null;
-        for (String a : avl) {
-            try {
-                indify(a);
-            } catch (Exception ex) {
-                if (err == null)  err = ex;
-                System.err.println("failure on "+a);
-                if (!keepgoing)  break;
-            }
-        }
-        if (err != null) {
-            if (err instanceof IOException)  throw (IOException) err;
-            throw (RuntimeException) err;
-        }
-    }
-
-    /** Execute the given application under a class loader which indifies all application classes. */
-    public void runApplication(String... av) throws Exception {
-        List<String> avl = new ArrayList<>(Arrays.asList(av));
-        String mainClassName = avl.remove(0);
-        av = avl.toArray(new String[0]);
-        Class<?> mainClass = Class.forName(mainClassName, true, makeClassLoader());
-        java.lang.reflect.Method main = mainClass.getMethod("main", String[].class);
-        try { main.setAccessible(true); } catch (SecurityException ex) { }
-        main.invoke(null, (Object) av);
-    }
-
-    public void parseOptions(List<String> av) throws IOException {
-        for (; !av.isEmpty(); av.remove(0)) {
-            String a = av.get(0);
-            if (a.startsWith("-")) {
-                String a2 = null;
-                int eq = a.indexOf('=');
-                if (eq > 0) {
-                    a2 = maybeExpandProperties(a.substring(eq+1));
-                    a = a.substring(0, eq+1);
-                }
-                switch (a) {
-                case "--java":
-                    return;  // keep this argument
-                case "-d": case "--dest": case "-d=": case "--dest=":
-                    dest = new File(a2 != null ? a2 : maybeExpandProperties(av.remove(1)));
-                    break;
-                case "-cp": case "--classpath":
-                    classpath = maybeExpandProperties(av.remove(1)).split("["+File.pathSeparatorChar+"]");
-                    break;
-                case "-k": case "--keepgoing": case "--keepgoing=":
-                    keepgoing = booleanOption(a2);  // print errors but keep going
-                    break;
-                case "--expand-properties": case "--expand-properties=":
-                    expandProperties = booleanOption(a2);  // expand property references in subsequent arguments
-                    break;
-                case "--verify-specifier-count": case "--verify-specifier-count=":
-                    verifySpecifierCount = Integer.valueOf(a2);
-                    break;
-                case "--overwrite": case "--overwrite=":
-                    overwrite = booleanOption(a2);  // overwrite output files
-                    break;
-                case "--all": case "--all=":
-                    all = booleanOption(a2);  // copy all classes, even if no patterns
-                    break;
-                case "-q": case "--quiet": case "--quiet=":
-                    quiet = booleanOption(a2);  // less output
-                    break;
-                case "-v": case "--verbose": case "--verbose=":
-                    verbose = booleanOption(a2);  // more output
-                    break;
-                case "--transitionalJSR292": case "--transitionalJSR292=":
-                    transitionalJSR292 = booleanOption(a2);  // use older invokedynamic format
-                    break;
-                default:
-                    throw new IllegalArgumentException("unrecognized flag: "+a);
-                }
-                continue;
-            } else {
-                break;
-            }
-        }
-        if (dest == null && !overwrite)
-            throw new RuntimeException("no output specified; need --dest d or --overwrite");
-        if (expandProperties) {
-            for (int i = 0; i < av.size(); i++)
-                av.set(i, maybeExpandProperties(av.get(i)));
-        }
-    }
-
-    private boolean booleanOption(String s) {
-        if (s == null)  return true;
-        switch (s) {
-        case "true":  case "yes": case "on":  case "1": return true;
-        case "false": case "no":  case "off": case "0": return false;
-        }
-        throw new IllegalArgumentException("unrecognized boolean flag="+s);
-    }
-
-    private String maybeExpandProperties(String s) {
-        if (!expandProperties)  return s;
-        Set<String> propsDone = new HashSet<>();
-        while (s.contains("${")) {
-            int lbrk = s.indexOf("${");
-            int rbrk = s.indexOf('}', lbrk);
-            if (rbrk < 0)  break;
-            String prop = s.substring(lbrk+2, rbrk);
-            if (!propsDone.add(prop))  break;
-            String value = System.getProperty(prop);
-            if (verbose)  System.err.println("expanding ${"+prop+"} => "+value);
-            if (value == null)  break;
-            s = s.substring(0, lbrk) + value + s.substring(rbrk+1);
-        }
-        return s;
-    }
-
-    public void indify(String a) throws IOException {
-        File f = new File(a);
-        String fn = f.getName();
-        if (fn.endsWith(".class") && f.isFile())
-            indifyFile(f, dest);
-        else if (fn.endsWith(".jar") && f.isFile())
-            indifyJar(f, dest);
-        else if (f.isDirectory())
-            indifyTree(f, dest);
-        else if (!keepgoing)
-            throw new RuntimeException("unrecognized file: "+a);
-    }
-
-    private void ensureDirectory(File dir) {
-        if (dir.mkdirs() && !quiet)
-            System.err.println("created "+dir);
-    }
-
-    public void indifyFile(File f, File dest) throws IOException {
-        if (verbose)  System.err.println("reading "+f);
-        ClassFile cf = new ClassFile(f);
-        Logic logic = new Logic(cf);
-        boolean changed = logic.transform();
-        logic.reportPatternMethods(quiet, keepgoing);
-        if (changed || all) {
-            File outfile;
-            if (dest != null) {
-                ensureDirectory(dest);
-                outfile = classPathFile(dest, cf.nameString());
-            } else {
-                outfile = f;  // overwrite input file, no matter where it is
-            }
-            cf.writeTo(outfile);
-            if (!quiet)  System.err.println("wrote "+outfile);
-        }
-    }
-
-    File classPathFile(File pathDir, String className) {
-        String qualname = className.replace('.','/')+".class";
-        qualname = qualname.replace('/', File.separatorChar);
-        return new File(pathDir, qualname);
-    }
-
-    public void indifyJar(File f, Object dest) throws IOException {
-        throw new UnsupportedOperationException("Not yet implemented");
-    }
-
-    public void indifyTree(File f, File dest) throws IOException {
-        if (verbose)  System.err.println("reading directory: "+f);
-        for (File f2 : f.listFiles(new FilenameFilter() {
-                public boolean accept(File dir, String name) {
-                    if (name.endsWith(".class"))  return true;
-                    if (name.contains("."))  return false;
-                    // return true if it might be a package name:
-                    return Character.isJavaIdentifierStart(name.charAt(0));
-                }})) {
-            if (f2.getName().endsWith(".class"))
-                indifyFile(f2, dest);
-            else if (f2.isDirectory())
-                indifyTree(f2, dest);
-        }
-    }
-
-    public ClassLoader makeClassLoader() {
-        return new Loader();
-    }
-    private class Loader extends ClassLoader {
-        Loader() {
-            this(Indify.class.getClassLoader());
-        }
-        Loader(ClassLoader parent) {
-            super(parent);
-        }
-        public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
-            File f = findClassInPath(name);
-            if (f != null) {
-                try {
-                    Class<?> c = transformAndLoadClass(f);
-                    if (c != null) {
-                        if (resolve)  resolveClass(c);
-                        return c;
-                    }
-                } catch (Exception ex) {
-                    if (ex instanceof IllegalArgumentException)
-                        // pass error from reportPatternMethods
-                        throw (IllegalArgumentException) ex;
-                }
-            }
-            return super.loadClass(name, resolve);
-        }
-        private File findClassInPath(String name) {
-            for (String s : classpath) {
-                File f = classPathFile(new File(s), name);
-                //System.out.println("Checking for "+f);
-                if (f.exists() && f.canRead()) {
-                    return f;
-                }
-            }
-            return null;
-        }
-        protected Class<?> findClass(String name) throws ClassNotFoundException {
-            try {
-                return transformAndLoadClass(findClassInPath(name));
-            } catch (IOException ex) {
-                throw new ClassNotFoundException("IO error", ex);
-            }
-        }
-        private Class<?> transformAndLoadClass(File f) throws ClassNotFoundException, IOException {
-            if (verbose)  System.err.println("Loading class from "+f);
-            ClassFile cf = new ClassFile(f);
-            Logic logic = new Logic(cf);
-            boolean changed = logic.transform();
-            if (verbose && !changed)  System.err.println("(no change)");
-            logic.reportPatternMethods(!verbose, keepgoing);
-            byte[] bytes = cf.toByteArray();
-            return defineClass(null, bytes, 0, bytes.length);
-        }
-    }
-
-    private class Logic {
-        // Indify logic, per se.
-        ClassFile cf;
-        final char[] poolMarks;
-        final Map<Method,Constant> constants = new HashMap<>();
-        final Map<Method,String> indySignatures = new HashMap<>();
-        Logic(ClassFile cf) {
-            this.cf = cf;
-            poolMarks = new char[cf.pool.size()];
-        }
-        boolean transform() {
-            if (!initializeMarks())  return false;
-            if (!findPatternMethods())  return false;
-            Pool pool = cf.pool;
-            //for (Constant c : cp)  System.out.println("  # "+c);
-            for (Method m : cf.methods) {
-                if (constants.containsKey(m))  continue;  // don't bother
-                // Transform references.
-                int blab = 0;
-                for (Instruction i = m.instructions(); i != null; i = i.next()) {
-                    if (i.bc != opc_invokestatic)  continue;
-                    int methi = i.u2At(1);
-                    if (poolMarks[methi] == 0)  continue;
-                    Short[] ref = pool.getMemberRef((short)methi);
-                    Method conm = findMember(cf.methods, ref[1], ref[2]);
-                    if (conm == null)  continue;
-                    Constant con = constants.get(conm);
-                    if (con == null)  continue;
-                    if (blab++ == 0 && !quiet)
-                        System.err.println("patching "+cf.nameString()+"."+m);
-                    //if (blab == 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println("  |"+j); }
-                    if (con.tag == CONSTANT_InvokeDynamic ||
-                        con.tag == CONSTANT_InvokeDynamic_17) {
-                        // need to patch the following instruction too,
-                        // but there are usually intervening argument pushes too
-                        Instruction i2 = findPop(i);
-                        Short[] ref2 = null;
-                        short ref2i = 0;
-                        if (i2 != null && i2.bc == opc_invokevirtual &&
-                                poolMarks[(char)(ref2i = (short) i2.u2At(1))] == 'D')
-                            ref2 = pool.getMemberRef(ref2i);
-                        if (ref2 == null || !"invokeExact".equals(pool.getString(ref2[1]))) {
-                            System.err.println(m+": failed to create invokedynamic at "+i.pc);
-                            continue;
-                        }
-                        String invType = pool.getString(ref2[2]);
-                        String bsmType = indySignatures.get(conm);
-                        if (!invType.equals(bsmType)) {
-                            System.err.println(m+": warning: "+conm+" call type and local invoke type differ: "
-                                    +bsmType+", "+invType);
-                        }
-                        assert(i.len == 3 || i2.len == 3);
-                        if (!quiet)  System.err.println(i+" "+conm+";...; "+i2+" => invokedynamic "+con);
-                        int start = i.pc + 3, end = i2.pc;
-                        System.arraycopy(i.codeBase, start, i.codeBase, i.pc, end-start);
-                        i.forceNext(0);  // force revisit of new instruction
-                        i2.u1AtPut(-3, opc_invokedynamic);
-                        i2.u2AtPut(-2, con.index);
-                        i2.u2AtPut(0, (short)0);
-                        i2.u1AtPut(2, opc_nop);
-                        //System.out.println(new Instruction(i.codeBase, i2.pc-3));
-                    } else {
-                        if (!quiet)  System.err.println(i+" "+conm+" => ldc "+con);
-                        assert(i.len == 3);
-                        i.u1AtPut(0, opc_ldc_w);
-                        i.u2AtPut(1, con.index);
-                    }
-                }
-                //if (blab >= 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println("    |"+j); }
-            }
-            cf.methods.removeAll(constants.keySet());
-            return true;
-        }
-
-        // Scan forward from the instruction to find where the stack p
-        // below the current sp at the instruction.
-        Instruction findPop(Instruction i) {
-            //System.out.println("findPop from "+i);
-            Pool pool = cf.pool;
-            JVMState jvm = new JVMState();
-        decode:
-            for (i = i.clone().next(); i != null; i = i.next()) {
-                String pops = INSTRUCTION_POPS[i.bc];
-                //System.out.println("  "+i+" "+jvm.stack+" : "+pops.replace("$", " => "));
-                if (pops == null)  break;
-                if (jvm.stackMotion(i.bc))  continue decode;
-                if (pops.indexOf('Q') >= 0) {
-                    Short[] ref = pool.getMemberRef((short) i.u2At(1));
-                    String type = simplifyType(pool.getString(CONSTANT_Utf8, ref[2]));
-                    switch (i.bc) {
-                    case opc_getstatic:
-                    case opc_getfield:
-                    case opc_putstatic:
-                    case opc_putfield:
-                        pops = pops.replace("Q", type);
-                        break;
-                    default:
-                        if (!type.startsWith("("))
-                            throw new InternalError(i.toString());
-                        pops = pops.replace("Q$Q", type.substring(1).replace(")","$"));
-                        break;
-                    }
-                    //System.out.println("special type: "+type+" => "+pops);
-                }
-                int npops = pops.indexOf('$');
-                if (npops < 0)  throw new InternalError();
-                if (npops > jvm.sp())  return i;
-                List<Object> args = jvm.args(npops);
-                int k = 0;
-                for (Object x : args) {
-                    char have = (Character) x;
-                    char want = pops.charAt(k++);
-                    if (have == 'X' || want == 'X')  continue;
-                    if (have != want)  break decode;
-                }
-                if (pops.charAt(k++) != '$')  break decode;
-                args.clear();
-                while (k < pops.length())
-                    args.add(pops.charAt(k++));
-            }
-            System.err.println("*** bailout on jvm: "+jvm.stack+" "+i);
-            return null;
-        }
-
-        boolean findPatternMethods() {
-            boolean found = false;
-            for (char mark : "THI".toCharArray()) {
-                for (Method m : cf.methods) {
-                    if (!Modifier.isPrivate(m.access))  continue;
-                    if (!Modifier.isStatic(m.access))  continue;
-                    if (nameAndTypeMark(m.name, m.type) == mark) {
-                        Constant con = scanPattern(m, mark);
-                        if (con == null)  continue;
-                        constants.put(m, con);
-                        found = true;
-                    }
-                }
-            }
-            return found;
-        }
-
-        void reportPatternMethods(boolean quietly, boolean allowMatchFailure) {
-            if (!quietly && !constants.keySet().isEmpty())
-                System.err.println("pattern methods removed: "+constants.keySet());
-            for (Method m : cf.methods) {
-                if (nameMark(cf.pool.getString(m.name)) != 0 &&
-                    constants.get(m) == null) {
-                    String failure = "method has special name but fails to match pattern: "+m;
-                    if (!allowMatchFailure)
-                        throw new IllegalArgumentException(failure);
-                    else if (!quietly)
-                        System.err.println("warning: "+failure);
-                }
-            }
-            if (verifySpecifierCount >= 0) {
-                List<Object[]> specs = bootstrapMethodSpecifiers(false);
-                int specsLen = (specs == null ? 0 : specs.size());
-                if (specsLen != verifySpecifierCount) {
-                    throw new IllegalArgumentException("BootstrapMethods length is "+specsLen+" but should be "+verifySpecifierCount);
-                }
-            }
-            if (!quiet)  System.err.flush();
-        }
-
-        // mark constant pool entries according to participation in patterns
-        boolean initializeMarks() {
-            boolean changed = false;
-            for (;;) {
-                boolean changed1 = false;
-                int cpindex = -1;
-                for (Constant e : cf.pool) {
-                    ++cpindex;
-                    if (e == null)  continue;
-                    char mark = poolMarks[cpindex];
-                    if (mark != 0)  continue;
-                    switch (e.tag) {
-                    case CONSTANT_Utf8:
-                        mark = nameMark(e.itemString()); break;
-                    case CONSTANT_NameAndType:
-                        mark = nameAndTypeMark(e.itemIndexes()); break;
-                    case CONSTANT_Class: {
-                        int n1 = e.itemIndex();
-                        char nmark = poolMarks[(char)n1];
-                        if ("DJ".indexOf(nmark) >= 0)
-                            mark = nmark;
-                        break;
-                    }
-                    case CONSTANT_Field:
-                    case CONSTANT_Method: {
-                        Short[] n12 = e.itemIndexes();
-                        short cl = n12[0];
-                        short nt = n12[1];
-                        char cmark = poolMarks[(char)cl];
-                        if (cmark != 0) {
-                            mark = cmark;  // it is a java.dyn.* or java.lang.* method
-                            break;
-                        }
-                        String cls = cf.pool.getString(CONSTANT_Class, cl);
-                        if (cls.equals(cf.nameString())) {
-                            switch (poolMarks[(char)nt]) {
-                            // it is a private MH/MT/INDY method
-                            case 'T': case 'H': case 'I':
-                                mark = poolMarks[(char)nt];
-                                break;
-                            }
-                        }
-                        break;
-                    }
-                    default:  break;
-                    }
-                    if (mark != 0) {
-                        poolMarks[cpindex] = mark;
-                        changed1 = true;
-                    }
-                }
-                if (!changed1)
-                    break;
-                changed = true;
-            }
-            return changed;
-        }
-        char nameMark(String s) {
-            if (s.startsWith("MT_"))                return 'T';
-            else if (s.startsWith("MH_"))           return 'H';
-            else if (s.startsWith("INDY_"))         return 'I';
-            else if (s.startsWith("java/dyn/"))     return 'D';
-            else if (s.startsWith("java/lang/"))    return 'J';
-            return 0;
-        }
-        char nameAndTypeMark(Short[] n12) {
-            return nameAndTypeMark(n12[0], n12[1]);
-        }
-        char nameAndTypeMark(short n1, short n2) {
-            char mark = poolMarks[(char)n1];
-            if (mark == 0)  return 0;
-            String descr = cf.pool.getString(CONSTANT_Utf8, n2);
-            String requiredType;
-            switch (poolMarks[(char)n1]) {
-            case 'H': requiredType = "()Ljava/dyn/MethodHandle;";  break;
-            case 'T': requiredType = "()Ljava/dyn/MethodType;";    break;
-            case 'I': requiredType = "()Ljava/dyn/MethodHandle;";  break;
-            default:  return 0;
-            }
-            if (descr.equals(requiredType))  return mark;
-            return 0;
-        }
-
-        private class JVMState {
-            final List<Object> stack = new ArrayList<>();
-            int sp() { return stack.size(); }
-            void push(Object x) { stack.add(x); }
-            void push2(Object x) { stack.add(EMPTY_SLOT); stack.add(x); }
-            void pushAt(int pos, Object x) { stack.add(stack.size()+pos, x); }
-            Object pop() { return stack.remove(sp()-1); }
-            Object top() { return stack.get(sp()-1); }
-            List<Object> args(boolean hasRecv, String type) {
-                return args(argsize(type) + (hasRecv ? 1 : 0));
-            }
-            List<Object> args(int argsize) {
-                return stack.subList(sp()-argsize, sp());
-            }
-            boolean stackMotion(int bc) {
-                switch (bc) {
-                case opc_pop:    pop();             break;
-                case opc_pop2:   pop(); pop();      break;
-                case opc_swap:   pushAt(-1, pop()); break;
-                case opc_dup:    push(top());       break;
-                case opc_dup_x1: pushAt(-2, top()); break;
-                case opc_dup_x2: pushAt(-3, top()); break;
-                // ? also: dup2{,_x1,_x2}
-                default:  return false;
-                }
-                return true;
-            }
-        }
-        private final String EMPTY_SLOT = "_";
-        private void removeEmptyJVMSlots(List<Object> args) {
-            for (;;) {
-                int i = args.indexOf(EMPTY_SLOT);
-                if (i >= 0 && i+1 < args.size()
-                    && (isConstant(args.get(i+1), CONSTANT_Long) ||
-                        isConstant(args.get(i+1), CONSTANT_Double)))
-                    args.remove(i);
-                else  break;
-            }
-        }
-
-        private Constant scanPattern(Method m, char patternMark) {
-            if (verbose)  System.err.println("scan "+m+" for pattern="+patternMark);
-            int wantTag;
-            switch (patternMark) {
-            case 'T': wantTag = CONSTANT_MethodType; break;
-            case 'H': wantTag = CONSTANT_MethodHandle; break;
-            case 'I': wantTag = CONSTANT_InvokeDynamic; break;
-            default: throw new InternalError();
-            }
-            Instruction i = m.instructions();
-            JVMState jvm = new JVMState();
-            Pool pool = cf.pool;
-            int branchCount = 0;
-            Object arg;
-            List<Object> args;
-            List<Object> bsmArgs = null;  // args to invokeGeneric
-        decode:
-            for (; i != null; i = i.next()) {
-                //System.out.println(jvm.stack+" "+i);
-                int bc = i.bc;
-                switch (bc) {
-                case opc_ldc:           jvm.push(pool.get(i.u1At(1)));   break;
-                case opc_ldc_w:         jvm.push(pool.get(i.u2At(1)));   break;
-                case opc_ldc2_w:        jvm.push2(pool.get(i.u2At(1)));  break;
-                case opc_aconst_null:   jvm.push(null);                  break;
-                case opc_bipush:        jvm.push((int)(byte) i.u1At(1)); break;
-                case opc_sipush:        jvm.push((int)(short)i.u2At(1)); break;
-
-                // these support creation of a restarg array
-                case opc_anewarray:
-                    arg = jvm.pop();
-                    if (!(arg instanceof Integer))  break decode;
-                    arg = Arrays.asList(new Object[(Integer)arg]);
-                    jvm.push(arg);
-                    break;
-                case opc_dup:
-                    jvm.push(jvm.top()); break;
-                case opc_aastore:
-                    args = jvm.args(3);  // array, index, value
-                    if (args.get(0) instanceof List &&
-                        args.get(1) instanceof Integer) {
-                        ((List<Object>)args.get(0)).set( (Integer)args.get(1), args.get(2) );
-                    }
-                    args.clear();
-                    break;
-
-                case opc_new:
-                {
-                    String type = pool.getString(CONSTANT_Class, (short)i.u2At(1));
-                    //System.out.println("new "+type);
-                    switch (type) {
-                    case "java/lang/StringBuilder":
-                        jvm.push("StringBuilder");
-                        continue decode;  // go to next instruction
-                    }
-                    break decode;  // bail out
-                }
-
-                case opc_getstatic:
-                {
-                    // int.class compiles to getstatic Integer.TYPE
-                    int fieldi = i.u2At(1);
-                    char mark = poolMarks[fieldi];
-                    //System.err.println("getstatic "+fieldi+Arrays.asList(pool.getStrings(pool.getMemberRef((short)fieldi)))+mark);
-                    if (mark == 'J') {
-                        Short[] ref = pool.getMemberRef((short) fieldi);
-                        String name = pool.getString(CONSTANT_Utf8, ref[1]);
-                        if ("TYPE".equals(name)) {
-                            String wrapperName = pool.getString(CONSTANT_Class, ref[0]).replace('/', '.');
-                            // a primitive type descriptor
-                            Class<?> primClass;
-                            try {
-                                primClass = (Class<?>) Class.forName(wrapperName).getField(name).get(null);
-                            } catch (Exception ex) {
-                                throw new InternalError("cannot load "+wrapperName+"."+name);
-                            }
-                            jvm.push(primClass);
-                            break;
-                        }
-                    }
-                    // unknown field; keep going...
-                    jvm.push(UNKNOWN_CON);
-                    break;
-                }
-                case opc_putstatic:
-                {
-                    if (patternMark != 'I')  break decode;
-                    jvm.pop();
-                    // unknown field; keep going...
-                    break;
-                }
-
-                case opc_invokestatic:
-                case opc_invokevirtual:
-                case opc_invokespecial:
-                {
-                    boolean hasRecv = (bc != opc_invokestatic);
-                    int methi = i.u2At(1);
-                    char mark = poolMarks[methi];
-                    Short[] ref = pool.getMemberRef((short)methi);
-                    String type = pool.getString(CONSTANT_Utf8, ref[2]);
-                    //System.out.println("invoke "+pool.getString(CONSTANT_Utf8, ref[1])+" "+Arrays.asList(ref)+" : "+type);
-                    args = jvm.args(hasRecv, type);
-                    String intrinsic = null;
-                    Constant con;
-                    if (mark == 'D' || mark == 'J') {
-                        intrinsic = pool.getString(CONSTANT_Utf8, ref[1]);
-                        if (mark == 'J') {
-                            String cls = pool.getString(CONSTANT_Class, ref[0]);
-                            cls = cls.substring(1+cls.lastIndexOf('/'));
-                            intrinsic = cls+"."+intrinsic;
-                        }
-                        //System.out.println("recognized intrinsic "+intrinsic);
-                        byte refKind = -1;
-                        switch (intrinsic) {
-                        case "findGetter":          refKind = REF_getField;         break;
-                        case "findStaticGetter":    refKind = REF_getStatic;        break;
-                        case "findSetter":          refKind = REF_putField;         break;
-                        case "findStaticSetter":    refKind = REF_putStatic;        break;
-                        case "findVirtual":         refKind = REF_invokeVirtual;    break;
-                        case "findStatic":          refKind = REF_invokeStatic;     break;
-                        case "findSpecial":         refKind = REF_invokeSpecial;    break;
-                        case "findConstructor":     refKind = REF_newInvokeSpecial; break;
-                        }
-                        if (refKind >= 0 && (con = parseMemberLookup(refKind, args)) != null) {
-                            args.clear(); args.add(con);
-                            continue;
-                        }
-                    }
-                    Method ownMethod = null;
-                    if (mark == 'T' || mark == 'H' || mark == 'I') {
-                        ownMethod = findMember(cf.methods, ref[1], ref[2]);
-                    }
-                    //if (intrinsic != null)  System.out.println("intrinsic = "+intrinsic);
-                    switch (intrinsic == null ? "" : intrinsic) {
-                    case "fromMethodDescriptorString":
-                        con = makeMethodTypeCon(args.get(0));
-                        args.clear(); args.add(con);
-                        continue;
-                    case "methodType": {
-                        flattenVarargs(args);  // there are several overloadings, some with varargs
-                        StringBuilder buf = new StringBuilder();
-                        String rtype = null;
-                        for (Object typeArg : args) {
-                            if (typeArg instanceof Class) {
-                                Class<?> argClass = (Class<?>) typeArg;
-                                if (argClass.isPrimitive()) {
-                                    char tchar;
-                                    switch (argClass.getName()) {
-                                    case "void":    tchar = 'V'; break;
-                                    case "boolean": tchar = 'Z'; break;
-                                    case "byte":    tchar = 'B'; break;
-                                    case "char":    tchar = 'C'; break;
-                                    case "short":   tchar = 'S'; break;
-                                    case "int":     tchar = 'I'; break;
-                                    case "long":    tchar = 'J'; break;
-                                    case "float":   tchar = 'F'; break;
-                                    case "double":  tchar = 'D'; break;
-                                    default:  throw new InternalError(argClass.toString());
-                                    }
-                                    buf.append(tchar);
-                                } else {
-                                    // should not happen, but...
-                                    buf.append('L').append(argClass.getName().replace('.','/')).append(';');
-                                }
-                            } else if (typeArg instanceof Constant) {
-                                Constant argCon = (Constant) typeArg;
-                                if (argCon.tag == CONSTANT_Class) {
-                                    String cn = pool.get(argCon.itemIndex()).itemString();
-                                    if (cn.endsWith(";"))
-                                        buf.append(cn);
-                                    else
-                                        buf.append('L').append(cn).append(';');
-                                } else {
-                                    break decode;
-                                }
-                            } else {
-                                break decode;
-                            }
-                            if (rtype == null) {
-                                // first arg is treated differently
-                                rtype = buf.toString();
-                                buf.setLength(0);
-                                buf.append('(');
-                            }
-                        }
-                        buf.append(')').append(rtype);
-                        con = con = makeMethodTypeCon(buf.toString());
-                        args.clear(); args.add(con);
-                        continue;
-                    }
-                    case "lookup":
-                    case "dynamicInvoker":
-                        args.clear(); args.add(intrinsic);
-                        continue;
-                    case "lookupClass":
-                        if (args.equals(Arrays.asList("lookup"))) {
-                            // fold lookup().lookupClass() to the enclosing class
-                            args.clear(); args.add(pool.get(cf.thisc));
-                            continue;
-                        }
-                        break;
-                    case "invokeGeneric":
-                    case "invokeWithArguments":
-                        if (patternMark != 'I')  break decode;
-                        if ("invokeWithArguments".equals(intrinsic))
-                            flattenVarargs(args);
-                        bsmArgs = new ArrayList(args);
-                        args.clear(); args.add("invokeGeneric");
-                        continue;
-                    case "Integer.valueOf":
-                    case "Float.valueOf":
-                    case "Long.valueOf":
-                    case "Double.valueOf":
-                        removeEmptyJVMSlots(args);
-                        if (args.size() == 1) {
-                            arg = args.remove(0);
-                            assert(3456 == (CONSTANT_Integer*1000 + CONSTANT_Float*100 + CONSTANT_Long*10 + CONSTANT_Double));
-                            if (isConstant(arg, CONSTANT_Integer + "IFLD".indexOf(intrinsic.charAt(0)))
-                                || arg instanceof Number) {
-                                args.add(arg); continue;
-                            }
-                        }
-                        break decode;
-                    case "StringBuilder.append":
-                        // allow calls like ("value = "+x)
-                        removeEmptyJVMSlots(args);
-                        args.subList(1, args.size()).clear();
-                        continue;
-                    case "StringBuilder.toString":
-                        args.clear();
-                        args.add(intrinsic);
-                        continue;
-                    }
-                    if (!hasRecv && ownMethod != null && patternMark != 0) {
-                        con = constants.get(ownMethod);
-                        if (con == null)  break decode;
-                        args.clear(); args.add(con);
-                        continue;
-                    } else if (type.endsWith(")V")) {
-                        // allow calls like println("reached the pattern method")
-                        args.clear();
-                        continue;
-                    }
-                    break decode;  // bail out for most calls
-                }
-                case opc_areturn:
-                {
-                    ++branchCount;
-                    if (bsmArgs != null) {
-                        // parse bsmArgs as (MH, lookup, String, MT, [extra])
-                        Constant indyCon = makeInvokeDynamicCon(bsmArgs);
-                        if (indyCon != null) {
-                            Constant typeCon = (Constant) bsmArgs.get(3);
-                            indySignatures.put(m, pool.getString(typeCon.itemIndex()));
-                            return indyCon;
-                        }
-                        System.err.println(m+": inscrutable bsm arguments: "+bsmArgs);
-                        break decode;  // bail out
-                    }
-                    arg = jvm.pop();
-                    if (branchCount == 2 && UNKNOWN_CON.equals(arg))
-                        break;  // merge to next path
-                    if (isConstant(arg, wantTag))
-                        return (Constant) arg;
-                    break decode;  // bail out
-                }
-                default:
-                    if (jvm.stackMotion(i.bc))  break;
-                    if (bc >= opc_nconst_MIN && bc <= opc_nconst_MAX)
-                        { jvm.push(INSTRUCTION_CONSTANTS[bc - opc_nconst_MIN]); break; }
-                    if (patternMark == 'I') {
-                        // these support caching paths in INDY_x methods
-                        if (bc == opc_aload || bc >= opc_aload_0 && bc <= opc_aload_MAX)
-                            { jvm.push(UNKNOWN_CON); break; }
-                        if (bc == opc_astore || bc >= opc_astore_0 && bc <= opc_astore_MAX)
-                            { jvm.pop(); break; }
-                        switch (bc) {
-                        case opc_getfield:
-                        case opc_aaload:
-                            jvm.push(UNKNOWN_CON); break;
-                        case opc_ifnull:
-                        case opc_ifnonnull:
-                            // ignore branch target
-                            if (++branchCount != 1)  break decode;
-                            jvm.pop();
-                            break;
-                        case opc_checkcast:
-                            arg = jvm.top();
-                            if ("invokeWithArguments".equals(arg) ||
-                                "invokeGeneric".equals(arg))
-                                break;  // assume it is a helpful cast
-                            break decode;
-                        default:
-                            break decode;  // bail out
-                        }
-                        continue decode; // go to next instruction
-                    }
-                    break decode;  // bail out
-                } //end switch
-            }
-            System.err.println(m+": bailout on "+i+" jvm stack: "+jvm.stack);
-            return null;
-        }
-        private final String UNKNOWN_CON = "<unknown>";
-
-        private void flattenVarargs(List<Object> args) {
-            int size = args.size();
-            if (size > 0 && args.get(size-1) instanceof List)
-                args.addAll((List<Object>) args.remove(size-1));
-        }
-
-        private boolean isConstant(Object x, int tag) {
-            return x instanceof Constant && ((Constant)x).tag == tag;
-        }
-        private Constant makeMethodTypeCon(Object x) {
-            short utfIndex;
-            if (x instanceof String)
-                utfIndex = (short) cf.pool.addConstant(CONSTANT_Utf8, x).index;
-            else if (isConstant(x, CONSTANT_String))
-                utfIndex = ((Constant)x).itemIndex();
-            else  return null;
-            return cf.pool.addConstant(CONSTANT_MethodType, utfIndex);
-        }
-        private Constant parseMemberLookup(byte refKind, List<Object> args) {
-            // E.g.: lookup().findStatic(Foo.class, "name", MethodType)
-            if (args.size() != 4)  return null;
-            int argi = 0;
-            if (!"lookup".equals(args.get(argi++)))  return null;
-            short refindex, cindex, ntindex, nindex, tindex;
-            Object con;
-            if (!isConstant(con = args.get(argi++), CONSTANT_Class))  return null;
-            cindex = (short)((Constant)con).index;
-            if (!isConstant(con = args.get(argi++), CONSTANT_String))  return null;
-            nindex = ((Constant)con).itemIndex();
-            if (isConstant(con = args.get(argi++), CONSTANT_MethodType) ||
-                isConstant(con, CONSTANT_Class)) {
-                tindex = ((Constant)con).itemIndex();
-            } else return null;
-            ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
-                    new Short[]{ nindex, tindex }).index;
-            byte reftag = CONSTANT_Method;
-            if (refKind <= REF_putStatic)
-                reftag = CONSTANT_Field;
-            else if (refKind == REF_invokeInterface)
-                reftag = CONSTANT_InterfaceMethod;
-            Constant ref = cf.pool.addConstant(reftag, new Short[]{ cindex, ntindex });
-            return cf.pool.addConstant(CONSTANT_MethodHandle, new Object[]{ refKind, (short)ref.index });
-        }
-        private Constant makeInvokeDynamicCon(List<Object> args) {
-            // E.g.: MH_bsm.invokeGeneric(lookup(), "name", MethodType, "extraArg")
-            removeEmptyJVMSlots(args);
-            if (args.size() != 4 && args.size() != 5)  return null;
-            int argi = 0;
-            short nindex, tindex, ntindex, bsmindex;
-            Object con;
-            if (!isConstant(con = args.get(argi++), CONSTANT_MethodHandle))  return null;
-            bsmindex = (short) ((Constant)con).index;
-            if (!"lookup".equals(args.get(argi++)))  return null;
-            if (!isConstant(con = args.get(argi++), CONSTANT_String))  return null;
-            nindex = ((Constant)con).itemIndex();
-            if (!isConstant(con = args.get(argi++), CONSTANT_MethodType))  return null;
-            tindex = ((Constant)con).itemIndex();
-            ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
-                                                  new Short[]{ nindex, tindex }).index;
-            if (transitionalJSR292) {
-                if (argi != args.size()) {
-                    System.err.println("BSM specifier has extra arguments but transitionalJSR292=1");
-                    return null;
-                }
-                return cf.pool.addConstant(CONSTANT_InvokeDynamic_17,
-                        new Short[]{ bsmindex, ntindex });
-            }
-            List<Object> extraArgs = Collections.emptyList();
-            if (argi < args.size()) {
-                Object arg = args.get(argi);
-                if (arg instanceof List)
-                    extraArgs = (List<Object>) arg;
-                else
-                    extraArgs = Arrays.asList(arg);
-                removeEmptyJVMSlots(args);
-            }
-            List<Short> extraArgIndexes = new CountedList<>(Short.class);
-            for (Object x : extraArgs) {
-                if (x instanceof Number) {
-                    Object num = null; byte numTag = 0;
-                    if (x instanceof Integer) { num = x; numTag = CONSTANT_Integer; }
-                    if (x instanceof Float)   { num = Float.floatToRawIntBits((Float)x); numTag = CONSTANT_Float; }
-                    if (x instanceof Long)    { num = x; numTag = CONSTANT_Long; }
-                    if (x instanceof Double)  { num = Double.doubleToRawLongBits((Double)x); numTag = CONSTANT_Double; }
-                    if (num != null)  x = cf.pool.addConstant(numTag, x);
-                }
-                if (!(x instanceof Constant))  return null;
-                extraArgIndexes.add((short) ((Constant)x).index);
-            }
-            List<Object[]> specs = bootstrapMethodSpecifiers(true);
-            int specindex = -1;
-            Object[] spec = new Object[]{ bsmindex, extraArgIndexes };
-            for (Object[] spec1 : specs) {
-                if (Arrays.equals(spec1, spec)) {
-                    specindex = specs.indexOf(spec1);
-                    if (verbose)  System.err.println("reusing BSM specifier: "+spec1[0]+spec1[1]);
-                    break;
-                }
-            }
-            if (specindex == -1) {
-                specindex = (short) specs.size();
-                specs.add(spec);
-                if (verbose)  System.err.println("adding BSM specifier: "+spec[0]+spec[1]);
-            }
-            return cf.pool.addConstant(CONSTANT_InvokeDynamic,
-                        new Short[]{ (short)specindex, ntindex });
-        }
-
-        List<Object[]> bootstrapMethodSpecifiers(boolean createIfNotFound) {
-            Attr bsms = cf.findAttr("BootstrapMethods");
-            if (bsms == null) {
-                if (!createIfNotFound)  return null;
-                bsms = new Attr(cf, "BootstrapMethods", new byte[]{0,0});
-                assert(bsms == cf.findAttr("BootstrapMethods"));
-            }
-            if (bsms.item instanceof byte[]) {
-                // unflatten
-                List<Object[]> specs = new CountedList<>(Object[].class);
-                DataInputStream in = new DataInputStream(new ByteArrayInputStream((byte[]) bsms.item));
-                try {
-                    int len = (char) in.readShort();
-                    for (int i = 0; i < len; i++) {
-                        short bsm = in.readShort();
-                        int argc = (char) in.readShort();
-                        List<Short> argv = new CountedList<>(Short.class);
-                        for (int j = 0; j < argc; j++)
-                            argv.add(in.readShort());
-                        specs.add(new Object[]{ bsm, argv });
-                    }
-                } catch (IOException ex) { throw new InternalError(); }
-                bsms.item = specs;
-            }
-            return (List<Object[]>) bsms.item;
-        }
-    }
-
-    private DataInputStream openInput(File f) throws IOException {
-        return new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
-    }
-
-    private DataOutputStream openOutput(File f) throws IOException {
-        if (!overwrite && f.exists())
-            throw new IOException("file already exists: "+f);
-        ensureDirectory(f.getParentFile());
-        return new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
-    }
-
-    static byte[] readRawBytes(DataInputStream in, int size) throws IOException {
-        byte[] bytes = new byte[size];
-        int nr = in.read(bytes);
-        if (nr != size)
-            throw new InternalError("wrong size: "+nr);
-        return bytes;
-    }
-
-    private interface Chunk {
-        void readFrom(DataInputStream in) throws IOException;
-        void writeTo(DataOutputStream out) throws IOException;
-    }
-
-    private static class CountedList<T> extends ArrayList<T> implements Chunk {
-        final Class<? extends T> itemClass;
-        final int rowlen;
-        CountedList(Class<? extends T> itemClass, int rowlen) {
-            this.itemClass = itemClass;
-            this.rowlen = rowlen;
-        }
-        CountedList(Class<? extends T> itemClass) { this(itemClass, -1); }
-        public void readFrom(DataInputStream in) throws IOException {
-            int count = in.readUnsignedShort();
-            while (size() < count) {
-                if (rowlen < 0) {
-                    add(readInput(in, itemClass));
-                } else {
-                    Class<?> elemClass = itemClass.getComponentType();
-                    Object[] row = (Object[]) java.lang.reflect.Array.newInstance(elemClass, rowlen);
-                    for (int i = 0; i < rowlen; i++)
-                        row[i] = readInput(in, elemClass);
-                    add(itemClass.cast(row));
-                }
-            }
-        }
-        public void writeTo(DataOutputStream out) throws IOException {
-            out.writeShort((short)size());
-            for (T item : this) {
-                writeOutput(out, item);
-            }
-        }
-    }
-
-    private static <T> T readInput(DataInputStream in, Class<T> dataClass) throws IOException {
-        Object data;
-        if (dataClass == Integer.class) {
-            data = in.readInt();
-        } else if (dataClass == Short.class) {
-            data = in.readShort();
-        } else if (dataClass == Byte.class) {
-            data = in.readByte();
-        } else if (dataClass == String.class) {
-            data = in.readUTF();
-        } else if (Chunk.class.isAssignableFrom(dataClass)) {
-            T obj;
-            try { obj = dataClass.newInstance(); }
-                catch (Exception ex) { throw new RuntimeException(ex); }
-            ((Chunk)obj).readFrom(in);
-            data = obj;
-        } else {
-            throw new InternalError("bad input datum: "+dataClass);
-        }
-        return dataClass.cast(data);
-    }
-    private static <T> T readInput(byte[] bytes, Class<T> dataClass) {
-        try {
-            return readInput(new DataInputStream(new ByteArrayInputStream(bytes)), dataClass);
-        } catch (IOException ex) {
-            throw new InternalError();
-        }
-    }
-    private static void readInputs(DataInputStream in, Object... data) throws IOException {
-        for (Object x : data)  ((Chunk)x).readFrom(in);
-    }
-
-    private static void writeOutput(DataOutputStream out, Object data) throws IOException {
-        if (data == null) {
-            return;
-        } if (data instanceof Integer) {
-            out.writeInt((Integer)data);
-        } else if (data instanceof Long) {
-            out.writeLong((Long)data);
-        } else if (data instanceof Short) {
-            out.writeShort((Short)data);
-        } else if (data instanceof Byte) {
-            out.writeByte((Byte)data);
-        } else if (data instanceof String) {
-            out.writeUTF((String)data);
-        } else if (data instanceof byte[]) {
-            out.write((byte[])data);
-        } else if (data instanceof Object[]) {
-            for (Object x : (Object[]) data)
-                writeOutput(out, x);
-        } else if (data instanceof Chunk) {
-            Chunk x = (Chunk) data;
-            x.writeTo(out);
-        } else if (data instanceof List) {
-            for (Object x : (List<?>) data)
-                writeOutput(out, x);
-        } else {
-            throw new InternalError("bad output datum: "+data+" : "+data.getClass().getName());
-        }
-    }
-    private static void writeOutputs(DataOutputStream out, Object... data) throws IOException {
-        for (Object x : data)  writeOutput(out, x);
-    }
-
-    public static abstract class Outer {
-        public abstract List<? extends Inner> inners();
-        protected void linkInners() {
-            for (Inner i : inners()) {
-                i.linkOuter(this);
-                if (i instanceof Outer)
-                    ((Outer)i).linkInners();
-            }
-        }
-        public <T extends Outer> T outer(Class<T> c) {
-            for (Outer walk = this;; walk = ((Inner)walk).outer()) {
-                if (c.isInstance(walk))
-                    return c.cast(walk);
-                //if (!(walk instanceof Inner))  return null;
-            }
-        }
-
-        public abstract List<Attr> attrs();
-        public Attr findAttr(String name) {
-            return findAttr(outer(ClassFile.class).pool.stringIndex(name, false));
-        }
-        public Attr findAttr(int name) {
-            if (name == 0)  return null;
-            for (Attr a : attrs()) {
-                if (a.name == name)  return a;
-            }
-            return null;
-        }
-    }
-    public interface Inner { Outer outer(); void linkOuter(Outer o); }
-    public static abstract class InnerOuter extends Outer implements Inner {
-        public Outer outer;
-        public Outer outer() { return outer; }
-        public void linkOuter(Outer o) { assert(outer == null); outer = o; }
-    }
-    public static class Constant<T> implements Chunk {
-        public final byte tag;
-        public final T item;
-        public final int index;
-        public Constant(int index, byte tag, T item) {
-            this.index = index;
-            this.tag = tag;
-            this.item = item;
-        }
-        public Constant checkTag(byte tag) {
-            if (this.tag != tag)  throw new InternalError(this.toString());
-            return this;
-        }
-        public String itemString() { return (String)item; }
-        public Short itemIndex() { return (Short)item; }
-        public Short[] itemIndexes() { return (Short[])item; }
-        public void readFrom(DataInputStream in) throws IOException {
-            throw new InternalError("do not call");
-        }
-        public void writeTo(DataOutputStream out) throws IOException {
-            writeOutputs(out, tag, item);
-        }
-        public boolean equals(Object x) { return (x instanceof Constant && equals((Constant)x)); }
-        public boolean equals(Constant that) {
-            return (this.tag == that.tag && this.itemAsComparable().equals(that.itemAsComparable()));
-        }
-        public int hashCode() { return (tag * 31) + this.itemAsComparable().hashCode(); }
-        public Object itemAsComparable() {
-            switch (tag) {
-            case CONSTANT_Double:   return Double.longBitsToDouble((Long)item);
-            case CONSTANT_Float:    return Float.intBitsToFloat((Integer)item);
-            }
-            return (item instanceof Object[] ? Arrays.asList((Object[])item) : item);
-        }
-        public String toString() {
-            String itstr = String.valueOf(itemAsComparable());
-            return (index + ":" + tagName(tag) + (itstr.startsWith("[")?"":"=") + itstr);
-        }
-        private static String[] TAG_NAMES;
-        public static String tagName(byte tag) {  // used for error messages
-            if (TAG_NAMES == null)
-                TAG_NAMES = ("None Utf8 Unicode Integer Float Long Double Class String"
-                             +" Fieldref Methodref InterfaceMethodref NameAndType #13 #14"
-                             +" MethodHandle MethodType InvokeDynamic#17 InvokeDynamic").split(" ");
-            if ((tag & 0xFF) >= TAG_NAMES.length)  return "#"+(tag & 0xFF);
-            return TAG_NAMES[tag & 0xFF];
-        }
-    }
-
-    public static class Pool extends CountedList<Constant> implements Chunk {
-        private Map<String,Short> strings = new TreeMap<>();
-
-        public Pool() {
-            super(Constant.class);
-        }
-        public void readFrom(DataInputStream in) throws IOException {
-            int count = in.readUnsignedShort();
-            add(null);  // always ignore first item
-            while (size() < count) {
-                readConstant(in);
-            }
-        }
-        public <T> Constant<T> addConstant(byte tag, T item) {
-            Constant<T> con = new Constant<>(size(), tag, item);
-            int idx = indexOf(con);
-            if (idx >= 0)  return get(idx);
-            add(con);
-            if (tag == CONSTANT_Utf8)  strings.put((String)item, (short) con.index);
-            return con;
-        }
-        private void readConstant(DataInputStream in) throws IOException {
-            byte tag = in.readByte();
-            int index = size();
-            Object arg;
-            switch (tag) {
-            case CONSTANT_Utf8:
-                arg = in.readUTF();
-                strings.put((String) arg, (short) size());
-                break;
-            case CONSTANT_Integer:
-            case CONSTANT_Float:
-                arg = in.readInt(); break;
-            case CONSTANT_Long:
-            case CONSTANT_Double:
-                add(new Constant(index, tag, in.readLong()));
-                add(null);
-                return;
-            case CONSTANT_Class:
-            case CONSTANT_String:
-                arg = in.readShort(); break;
-            case CONSTANT_Field:
-            case CONSTANT_Method:
-            case CONSTANT_InterfaceMethod:
-            case CONSTANT_NameAndType:
-            case CONSTANT_InvokeDynamic_17:
-            case CONSTANT_InvokeDynamic:
-                // read an ordered pair
-                arg = new Short[] { in.readShort(), in.readShort() };
-                break;
-            case CONSTANT_MethodHandle:
-                // read an ordered pair; first part is a u1 (not u2)
-                arg = new Object[] { in.readByte(), in.readShort() };
-                break;
-            case CONSTANT_MethodType:
-                arg = in.readShort(); break;
-            default:
-                throw new InternalError("bad CP tag "+tag);
-            }
-            add(new Constant(index, tag, arg));
-        }
-
-        // Access:
-        public Constant get(int index) {
-            // extra 1-bits get into the shorts
-            return super.get((char) index);
-        }
-        String getString(byte tag, short index) {
-            get(index).checkTag(tag);
-            return getString(index);
-        }
-        String getString(short index) {
-            Object v = get(index).item;
-            if (v instanceof Short)
-                v = get((Short)v).checkTag(CONSTANT_Utf8).item;
-            return (String) v;
-        }
-        String[] getStrings(Short[] indexes) {
-            String[] res = new String[indexes.length];
-            for (int i = 0; i < indexes.length; i++)
-                res[i] = getString(indexes[i]);
-            return res;
-        }
-        int stringIndex(String name, boolean createIfNotFound) {
-            Short x = strings.get(name);
-            if (x != null)  return (char)(int) x;
-            if (!createIfNotFound)  return 0;
-            return addConstant(CONSTANT_Utf8, name).index;
-        }
-        Short[] getMemberRef(short index) {
-            Short[] cls_nnt = get(index).itemIndexes();
-            Short[] name_type = get(cls_nnt[1]).itemIndexes();
-            return new Short[]{ cls_nnt[0], name_type[0], name_type[1] };
-        }
-    }
-
-    public class ClassFile extends Outer implements Chunk {
-        ClassFile(File f) throws IOException {
-            DataInputStream in = openInput(f);
-            try {
-                readFrom(in);
-            } finally {
-                if (in != null)  in.close();
-            }
-        }
-
-        public int                magic, version;  // <min:maj>
-        public final Pool         pool       = new Pool();
-        public short              access, thisc, superc;
-        public final List<Short>  interfaces = new CountedList<>(Short.class);
-        public final List<Field>  fields     = new CountedList<>(Field.class);
-        public final List<Method> methods    = new CountedList<>(Method.class);
-        public final List<Attr>   attrs      = new CountedList<>(Attr.class);
-
-        public final void readFrom(DataInputStream in) throws IOException {
-            magic = in.readInt(); version = in.readInt();
-            if (magic != 0xCAFEBABE)  throw new IOException("bad magic number");
-            pool.readFrom(in);
-            Code_index = pool.stringIndex("Code", false);
-            access = in.readShort(); thisc = in.readShort(); superc = in.readShort();
-            readInputs(in, interfaces, fields, methods, attrs);
-            if (in.read() >= 0)  throw new IOException("junk after end of file");
-            linkInners();
-        }
-
-        void writeTo(File f) throws IOException {
-            DataOutputStream out = openOutput(f);
-            try {
-                writeTo(out);
-            } finally {
-                out.close();
-            }
-        }
-
-        public void writeTo(DataOutputStream out) throws IOException {
-            writeOutputs(out, magic, version, pool,
-                         access, thisc, superc, interfaces,
-                         fields, methods, attrs);
-        }
-
-        public byte[] toByteArray() {
-            try {
-                ByteArrayOutputStream buf = new ByteArrayOutputStream();
-                writeTo(new DataOutputStream(buf));
-                return buf.toByteArray();
-            } catch (IOException ex) {
-                throw new InternalError();
-            }
-        }
-
-        public List<Inner> inners() {
-            List<Inner> inns = new ArrayList<>();
-            inns.addAll(fields); inns.addAll(methods); inns.addAll(attrs);
-            return inns;
-        }
-        public List<Attr> attrs() { return attrs; }
-
-        // derived stuff:
-        public String nameString() { return pool.getString(CONSTANT_Class, thisc); }
-        int Code_index;
-    }
-
-    private static <T extends Member> T findMember(List<T> mems, int name, int type) {
-        if (name == 0 || type == 0)  return null;
-        for (T m : mems) {
-            if (m.name == name && m.type == type)  return m;
-        }
-        return null;
-    }
-
-    public static class Member extends InnerOuter implements Chunk {
-        public short access, name, type;
-        public final List<Attr> attrs = new CountedList<>(Attr.class);
-        public void readFrom(DataInputStream in) throws IOException {
-            access = in.readShort(); name = in.readShort(); type = in.readShort();
-            readInputs(in, attrs);
-        }
-        public void writeTo(DataOutputStream out) throws IOException {
-            writeOutputs(out, access, name, type, attrs);
-        }
-        public List<Attr> inners() { return attrs; }
-        public List<Attr> attrs() { return attrs; }
-        public ClassFile outer() { return (ClassFile) outer; }
-        public String nameString() { return outer().pool.getString(CONSTANT_Utf8, name); }
-        public String typeString() { return outer().pool.getString(CONSTANT_Utf8, type); }
-        public String toString() {
-            if (outer == null)  return super.toString();
-            return nameString() + (this instanceof Method ? "" : ":")
-                    + simplifyType(typeString());
-        }
-    }
-    public static class Field extends Member {
-    }
-    public static class Method extends Member {
-        public Code code() {
-            Attr a = findAttr("Code");
-            if (a == null)  return null;
-            return (Code) a.item;
-        }
-        public Instruction instructions() {
-            Code code = code();
-            if (code == null)  return null;
-            return code.instructions();
-        }
-    }
-
-    public static class Attr extends InnerOuter implements Chunk {
-        public short name;
-        public int size = -1;  // no pre-declared size
-        public Object item;
-
-        public Attr() {}
-        public Attr(Outer outer, String name, Object item) {
-            ClassFile cf = outer.outer(ClassFile.class);
-            linkOuter(outer);
-            this.name = (short) cf.pool.stringIndex(name, true);
-            this.item = item;
-            outer.attrs().add(this);
-        }
-        public void readFrom(DataInputStream in) throws IOException {
-            name = in.readShort();
-            size = in.readInt();
-            item = readRawBytes(in, size);
-        }
-        public void writeTo(DataOutputStream out) throws IOException {
-            out.writeShort(name);
-            // write the 4-byte size header and then the contents:
-            byte[] bytes;
-            int trueSize;
-            if (item instanceof byte[]) {
-                bytes = (byte[]) item;
-                out.writeInt(trueSize = bytes.length);
-                out.write(bytes);
-            } else {
-                trueSize = flatten(out);
-                //if (!(item instanceof Code))  System.err.println("wrote complex attr name="+(int)(char)name+" size="+trueSize+" data="+Arrays.toString(flatten()));
-            }
-            if (trueSize != size && size >= 0)
-                System.err.println("warning: attribute size changed "+size+" to "+trueSize);
-        }
-        public void linkOuter(Outer o) {
-            super.linkOuter(o);
-            if (item instanceof byte[] &&
-                outer instanceof Method &&
-                ((Method)outer).outer().Code_index == name) {
-                    item = readInput((byte[])item, Code.class);
-            }
-        }
-        public List<Inner> inners() {
-            if (item instanceof Inner)
-                return Collections.nCopies(1, (Inner)item);
-            return Collections.emptyList();
-        }
-        public List<Attr> attrs() { return null; }  // Code overrides this
-        public byte[] flatten() {
-            ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
-            flatten(buf);
-            return buf.toByteArray();
-        }
-        public int flatten(DataOutputStream out) throws IOException {
-            ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
-            int trueSize = flatten(buf);
-            out.writeInt(trueSize);
-            buf.writeTo(out);
-            return trueSize;
-        }
-        private int flatten(ByteArrayOutputStream buf) {
-            try {
-                writeOutput(new DataOutputStream(buf), item);
-                return buf.size();
-            } catch (IOException ex) {
-                throw new InternalError();
-            }
-        }
-        public String nameString() {
-            ClassFile cf = outer(ClassFile.class);
-            if (cf == null)  return "#"+name;
-            return cf.pool.getString(name);
-        }
-        public String toString() {
-            return nameString()+(size < 0 ? "=" : "["+size+"]=")+item;
-        }
-    }
-
-    public static class Code extends InnerOuter implements Chunk {
-        public short stacks, locals;
-        public byte[] bytes;
-        public final List<Short[]> etable = new CountedList<>(Short[].class, 4);
-        public final List<Attr> attrs = new CountedList<>(Attr.class);
-        // etable[N] = (N)*{ startpc, endpc, handlerpc, catchtype }
-        public void readFrom(DataInputStream in) throws IOException {
-            stacks = in.readShort(); locals = in.readShort();
-            bytes = readRawBytes(in, in.readInt());
-            readInputs(in, etable, attrs);
-        }
-        public void writeTo(DataOutputStream out) throws IOException {
-            writeOutputs(out, stacks, locals, bytes.length, bytes, etable, attrs);
-        }
-        public List<Attr> inners() { return attrs; }
-        public List<Attr> attrs() { return attrs; }
-        public Instruction instructions() {
-            return new Instruction(bytes, 0);
-        }
-    }
-
-    // lots of constants
-    private static final byte
-        CONSTANT_Utf8              = 1,
-        CONSTANT_Integer           = 3,
-        CONSTANT_Float             = 4,
-        CONSTANT_Long              = 5,
-        CONSTANT_Double            = 6,
-        CONSTANT_Class             = 7,
-        CONSTANT_String            = 8,
-        CONSTANT_Field             = 9,
-        CONSTANT_Method            = 10,
-        CONSTANT_InterfaceMethod   = 11,
-        CONSTANT_NameAndType       = 12,
-        CONSTANT_MethodHandle      = 15,  // JSR 292
-        CONSTANT_MethodType        = 16,  // JSR 292
-        CONSTANT_InvokeDynamic_17  = 17,  // JSR 292, only occurs in old class files
-        CONSTANT_InvokeDynamic     = 18;  // JSR 292
-    private static final byte
-        REF_getField               = 1,
-        REF_getStatic              = 2,
-        REF_putField               = 3,
-        REF_putStatic              = 4,
-        REF_invokeVirtual          = 5,
-        REF_invokeStatic           = 6,
-        REF_invokeSpecial          = 7,
-        REF_newInvokeSpecial       = 8,
-        REF_invokeInterface        = 9;
-
-    private static final int
-        opc_nop                    = 0,
-        opc_aconst_null            = 1,
-        opc_nconst_MIN             = 2,  // iconst_m1
-        opc_nconst_MAX             = 15, // dconst_1
-        opc_bipush                 = 16,
-        opc_sipush                 = 17,
-        opc_ldc                    = 18,
-        opc_ldc_w                  = 19,
-        opc_ldc2_w                 = 20,
-        opc_aload                  = 25,
-        opc_aload_0                = 42,
-        opc_aload_MAX              = 45,
-        opc_aaload                 = 50,
-        opc_astore                 = 58,
-        opc_astore_0               = 75,
-        opc_astore_MAX             = 78,
-        opc_aastore                = 83,
-        opc_pop                    = 87,
-        opc_pop2                   = 88,
-        opc_dup                    = 89,
-        opc_dup_x1                 = 90,
-        opc_dup_x2                 = 91,
-        opc_dup2                   = 92,
-        opc_dup2_x1                = 93,
-        opc_dup2_x2                = 94,
-        opc_swap                   = 95,
-        opc_tableswitch            = 170,
-        opc_lookupswitch           = 171,
-        opc_areturn                = 176,
-        opc_getstatic              = 178,
-        opc_putstatic              = 179,
-        opc_getfield               = 180,
-        opc_putfield               = 181,
-        opc_invokevirtual          = 182,
-        opc_invokespecial          = 183,
-        opc_invokestatic           = 184,
-        opc_invokeinterface        = 185,
-        opc_invokedynamic          = 186,
-        opc_new                    = 187,
-        opc_anewarray              = 189,
-        opc_checkcast              = 192,
-        opc_ifnull                 = 198,
-        opc_ifnonnull              = 199,
-        opc_wide                   = 196;
-
-    private static final Object[] INSTRUCTION_CONSTANTS = {
-        -1, 0, 1, 2, 3, 4, 5, 0L, 1L, 0.0F, 1.0F, 2.0F, 0.0D, 1.0D
-    };
-
-    private static final String INSTRUCTION_FORMATS =
-        "nop$ aconst_null$L iconst_m1$I iconst_0$I iconst_1$I "+
-        "iconst_2$I iconst_3$I iconst_4$I iconst_5$I lconst_0$J_ "+
-        "lconst_1$J_ fconst_0$F fconst_1$F fconst_2$F dconst_0$D_ "+
-        "dconst_1$D_ bipush=bx$I sipush=bxx$I ldc=bk$X ldc_w=bkk$X "+
-        "ldc2_w=bkk$X_ iload=bl/wbll$I lload=bl/wbll$J_ fload=bl/wbll$F "+
-        "dload=bl/wbll$D_ aload=bl/wbll$L iload_0$I iload_1$I "+
-        "iload_2$I iload_3$I lload_0$J_ lload_1$J_ lload_2$J_ "+
-        "lload_3$J_ fload_0$F fload_1$F fload_2$F fload_3$F dload_0$D_ "+
-        "dload_1$D_ dload_2$D_ dload_3$D_ aload_0$L aload_1$L "+
-        "aload_2$L aload_3$L iaload$LI$I laload$LI$J_ faload$LI$F "+
-        "daload$LI$D_ aaload$LI$L baload$LI$I caload$LI$I saload$LI$I "+
-        "istore=bl/wbll$I$ lstore=bl/wbll$J_$ fstore=bl/wbll$F$ "+
-        "dstore=bl/wbll$D_$ astore=bl/wbll$L$ istore_0$I$ istore_1$I$ "+
-        "istore_2$I$ istore_3$I$ lstore_0$J_$ lstore_1$J_$ "+
-        "lstore_2$J_$ lstore_3$J_$ fstore_0$F$ fstore_1$F$ fstore_2$F$ "+
-        "fstore_3$F$ dstore_0$D_$ dstore_1$D_$ dstore_2$D_$ "+
-        "dstore_3$D_$ astore_0$L$ astore_1$L$ astore_2$L$ astore_3$L$ "+
-        "iastore$LII$ lastore$LIJ_$ fastore$LIF$ dastore$LID_$ "+
-        "aastore$LIL$ bastore$LII$ castore$LII$ sastore$LII$ pop$X$ "+
-        "pop2$XX$ dup$X$XX dup_x1$XX$XXX dup_x2$XXX$XXXX dup2$XX$XXXX "+
-        "dup2_x1$XXX$XXXXX dup2_x2$XXXX$XXXXXX swap$XX$XX "+
-        "iadd$II$I ladd$J_J_$J_ fadd$FF$F dadd$D_D_$D_ isub$II$I "+
-        "lsub$J_J_$J_ fsub$FF$F dsub$D_D_$D_ imul$II$I lmul$J_J_$J_ "+
-        "fmul$FF$F dmul$D_D_$D_ idiv$II$I ldiv$J_J_$J_ fdiv$FF$F "+
-        "ddiv$D_D_$D_ irem$II$I lrem$J_J_$J_ frem$FF$F drem$D_D_$D_ "+
-        "ineg$I$I lneg$J_$J_ fneg$F$F dneg$D_$D_ ishl$II$I lshl$J_I$J_ "+
-        "ishr$II$I lshr$J_I$J_ iushr$II$I lushr$J_I$J_ iand$II$I "+
-        "land$J_J_$J_ ior$II$I lor$J_J_$J_ ixor$II$I lxor$J_J_$J_ "+
-        "iinc=blx/wbllxx$ i2l$I$J_ i2f$I$F i2d$I$D_ l2i$J_$I l2f$J_$F "+
-        "l2d$J_$D_ f2i$F$I f2l$F$J_ f2d$F$D_ d2i$D_$I d2l$D_$J_ "+
-        "d2f$D_$F i2b$I$I i2c$I$I i2s$I$I lcmp fcmpl fcmpg dcmpl dcmpg "+
-        "ifeq=boo ifne=boo iflt=boo ifge=boo ifgt=boo ifle=boo "+
-        "if_icmpeq=boo if_icmpne=boo if_icmplt=boo if_icmpge=boo "+
-        "if_icmpgt=boo if_icmple=boo if_acmpeq=boo if_acmpne=boo "+
-        "goto=boo jsr=boo ret=bl/wbll tableswitch=* lookupswitch=* "+
-        "ireturn lreturn freturn dreturn areturn return "+
-        "getstatic=bkf$Q putstatic=bkf$Q$ getfield=bkf$L$Q "+
-        "putfield=bkf$LQ$ invokevirtual=bkm$LQ$Q "+
-        "invokespecial=bkm$LQ$Q invokestatic=bkm$Q$Q "+
-        "invokeinterface=bkixx$LQ$Q invokedynamic=bkd__$Q$Q new=bkc$L "+
-        "newarray=bx$I$L anewarray=bkc$I$L arraylength$L$I athrow "+
-        "checkcast=bkc$L$L instanceof=bkc$L$I monitorenter$L "+
-        "monitorexit$L wide=* multianewarray=bkcx ifnull=boo "+
-        "ifnonnull=boo goto_w=boooo jsr_w=boooo ";
-    private static final String[] INSTRUCTION_NAMES;
-    private static final String[] INSTRUCTION_POPS;
-    private static final int[] INSTRUCTION_INFO;
-    static {
-        String[] insns = INSTRUCTION_FORMATS.split(" ");
-        assert(insns[opc_lookupswitch].startsWith("lookupswitch"));
-        assert(insns[opc_tableswitch].startsWith("tableswitch"));
-        assert(insns[opc_wide].startsWith("wide"));
-        assert(insns[opc_invokedynamic].startsWith("invokedynamic"));
-        int[] info = new int[256];
-        String[] names = new String[256];
-        String[] pops = new String[256];
-        for (int i = 0; i < insns.length; i++) {
-            String insn = insns[i];
-            int dl = insn.indexOf('$');
-            if (dl > 0) {
-                String p = insn.substring(dl+1);
-                if (p.indexOf('$') < 0)  p = "$" + p;
-                pops[i] = p;
-                insn = insn.substring(0, dl);
-            }
-            int eq = insn.indexOf('=');
-            if (eq < 0) {
-                info[i] = 1;
-                names[i] = insn;
-                continue;
-            }
-            names[i] = insn.substring(0, eq);
-            String fmt = insn.substring(eq+1);
-            if (fmt.equals("*")) {
-                info[i] = 0;
-                continue;
-            }
-            int sl = fmt.indexOf('/');
-            if (sl < 0) {
-                info[i] = (char) fmt.length();
-            } else {
-                String wfmt = fmt.substring(sl+1);
-                fmt = fmt.substring(0, sl);
-                info[i] = (char)( fmt.length() + (wfmt.length() * 16) );
-            }
-        }
-        INSTRUCTION_INFO = info;
-        INSTRUCTION_NAMES = names;
-        INSTRUCTION_POPS = pops;
-    }
-
-    public static class Instruction implements Cloneable {
-        byte[] codeBase;
-        int pc;
-        int bc;
-        int info;
-        int wide;
-        int len;
-        Instruction(byte[] codeBase, int pc) {
-            this.codeBase = codeBase;
-            init(pc);
-        }
-        public Instruction clone() {
-            try {
-                return (Instruction) super.clone();
-            } catch (CloneNotSupportedException ex) {
-                throw new InternalError();
-            }
-        }
-        private Instruction init(int pc) {
-            this.pc = pc;
-            this.bc = codeBase[pc] & 0xFF;
-            this.info = INSTRUCTION_INFO[bc];
-            this.wide = 0;
-            this.len = (info & 0x0F);
-            if (len == 0)
-                computeLength();
-            return this;
-        }
-        Instruction next() {
-            if (len == 0 && bc != 0)  throw new InternalError();
-            int npc = pc + len;
-            if (npc == codeBase.length)
-                return null;
-            return init(npc);
-        }
-        void forceNext(int newLen) {
-            bc = opc_nop;
-            len = newLen;
-        }
-
-        public String toString() {
-            StringBuilder buf = new StringBuilder();
-            buf.append(pc).append(":").append(INSTRUCTION_NAMES[bc]);
-            switch (len) {
-            case 3: buf.append(" ").append(u2At(1)); break;
-            case 5: buf.append(" ").append(u2At(1)).append(" ").append(u2At(3)); break;
-            default:  for (int i = 1; i < len; i++)  buf.append(" ").append(u1At(1));
-            }
-            return buf.toString();
-        }
-
-        // these are the hard parts
-        private void computeLength() {
-            int cases;
-            switch (bc) {
-            case opc_wide:
-                bc = codeBase[pc + 1];
-                info = INSTRUCTION_INFO[bc];
-                len = ((info >> 4) & 0x0F);
-                if (len == 0)  throw new RuntimeException("misplaced wide bytecode: "+bc);
-                return;
-
-            case opc_tableswitch:
-                cases = (u4At(alignedIntOffset(2)) - u4At(alignedIntOffset(1)) + 1);
-                len = alignedIntOffset(3 + cases*1);
-                return;
-
-            case opc_lookupswitch:
-                cases = u4At(alignedIntOffset(1));
-                len = alignedIntOffset(2 + cases*2);
-                return;
-
-            default:
-                throw new RuntimeException("unknown bytecode: "+bc);
-            }
-        }
-        // switch code
-        // clget the Nth int (where 0 is the first after the opcode itself)
-        public int alignedIntOffset(int n) {
-            int pos = pc + 1;
-            pos += ((-pos) & 0x03);  // align it
-            pos += (n * 4);
-            return pos - pc;
-        }
-        public int u1At(int pos) {
-            return (codeBase[pc+pos] & 0xFF);
-        }
-        public int u2At(int pos) {
-            return (u1At(pos+0)<<8) + u1At(pos+1);
-        }
-        public int u4At(int pos) {
-            return (u2At(pos+0)<<16) + u2At(pos+2);
-        }
-        public void u1AtPut(int pos, int x) {
-            codeBase[pc+pos] = (byte)x;
-        }
-        public void u2AtPut(int pos, int x) {
-            codeBase[pc+pos+0] = (byte)(x >> 8);
-            codeBase[pc+pos+1] = (byte)(x >> 0);
-        }
-    }
-
-    static String simplifyType(String type) {
-        String simpleType = OBJ_SIGNATURE.matcher(type).replaceAll("L");
-        assert(simpleType.matches("^\\([A-Z]*\\)[A-Z]$"));
-        // change (DD)D to (D_D_)D_
-        simpleType = WIDE_SIGNATURE.matcher(simpleType).replaceAll("\\0_");
-        return simpleType;
-    }
-    static int argsize(String type) {
-        return simplifyType(type).length()-3;
-    }
-    private static final Pattern OBJ_SIGNATURE = Pattern.compile("\\[*L[^;]*;|\\[+[A-Z]");
-    private static final Pattern WIDE_SIGNATURE = Pattern.compile("[JD]");
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/6987555/Test6987555.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6987555
+ * @summary JSR 292 unboxing to a boolean value fails on big-endian SPARC
+ *
+ * @run main/othervm -Xint -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6987555
+ */
+
+import java.lang.invoke.*;
+
+public class Test6987555 {
+    private static final Class   CLASS = Test6987555.class;
+    private static final String  NAME  = "foo";
+    private static final boolean DEBUG = false;
+
+    public static void main(String[] args) throws Throwable {
+        testboolean();
+        testbyte();
+        testchar();
+        testshort();
+        testint();
+    }
+
+    // boolean
+    static void testboolean() throws Throwable {
+        doboolean(false);
+        doboolean(true);
+    }
+    static void doboolean(boolean x) throws Throwable {
+        if (DEBUG)  System.out.println("boolean=" + x);
+        MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(boolean.class, boolean.class));
+        MethodHandle mh2 = mh1.asType(MethodType.methodType(boolean.class, Boolean.class));
+        boolean a = (boolean) mh1.invokeExact(x);
+        boolean b = (boolean) mh2.invokeExact(Boolean.valueOf(x));
+        assert a == b : a + " != " + b;
+    }
+
+    // byte
+    static void testbyte() throws Throwable {
+        byte[] a = new byte[] {
+            Byte.MIN_VALUE,
+            Byte.MIN_VALUE + 1,
+            -0x0F,
+            -1,
+            0,
+            1,
+            0x0F,
+            Byte.MAX_VALUE - 1,
+            Byte.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            dobyte(a[i]);
+        }
+    }
+    static void dobyte(byte x) throws Throwable {
+        if (DEBUG)  System.out.println("byte=" + x);
+        MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(byte.class, byte.class));
+        MethodHandle mh2 = mh1.asType(MethodType.methodType(byte.class, Byte.class));
+        byte a = (byte) mh1.invokeExact(x);
+        byte b = (byte) mh2.invokeExact(Byte.valueOf(x));
+        assert a == b : a + " != " + b;
+    }
+
+    // char
+    static void testchar() throws Throwable {
+        char[] a = new char[] {
+            Character.MIN_VALUE,
+            Character.MIN_VALUE + 1,
+            0x000F,
+            0x00FF,
+            0x0FFF,
+            Character.MAX_VALUE - 1,
+            Character.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            dochar(a[i]);
+        }
+    }
+    static void dochar(char x) throws Throwable {
+        if (DEBUG)  System.out.println("char=" + x);
+        MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(char.class, char.class));
+        MethodHandle mh2 = mh1.asType(MethodType.methodType(char.class, Character.class));
+        char a = (char) mh1.invokeExact(x);
+        char b = (char) mh2.invokeExact(Character.valueOf(x));
+        assert a == b : a + " != " + b;
+    }
+
+    // short
+    static void testshort() throws Throwable {
+        short[] a = new short[] {
+            Short.MIN_VALUE,
+            Short.MIN_VALUE + 1,
+            -0x0FFF,
+            -0x00FF,
+            -0x000F,
+            -1,
+            0,
+            1,
+            0x000F,
+            0x00FF,
+            0x0FFF,
+            Short.MAX_VALUE - 1,
+            Short.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            doshort(a[i]);
+        }
+    }
+    static void doshort(short x) throws Throwable {
+        if (DEBUG)  System.out.println("short=" + x);
+        MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(short.class, short.class));
+        MethodHandle mh2 = mh1.asType(MethodType.methodType(short.class, Short.class));
+        short a = (short) mh1.invokeExact(x);
+        short b = (short) mh2.invokeExact(Short.valueOf(x));
+        assert a == b : a + " != " + b;
+    }
+
+    // int
+    static void testint() throws Throwable {
+        int[] a = new int[] {
+            Integer.MIN_VALUE,
+            Integer.MIN_VALUE + 1,
+            -0x00000FFF,
+            -0x000000FF,
+            -0x0000000F,
+            -1,
+            0,
+            1,
+            0x0000000F,
+            0x000000FF,
+            0x00000FFF,
+            Integer.MAX_VALUE - 1,
+            Integer.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            doint(a[i]);
+        }
+    }
+    static void doint(int x) throws Throwable {
+        if (DEBUG)  System.out.println("int=" + x);
+        MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(int.class, int.class));
+        MethodHandle mh2 = mh1.asType(MethodType.methodType(int.class, Integer.class));
+        int a = (int) mh1.invokeExact(x);
+        int b = (int) mh2.invokeExact(Integer.valueOf(x));
+        assert a == b : a + " != " + b;
+    }
+
+    public static boolean foo(boolean i) { return i; }
+    public static byte    foo(byte    i) { return i; }
+    public static char    foo(char    i) { return i; }
+    public static short   foo(short   i) { return i; }
+    public static int     foo(int     i) { return i; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/6991596/Test6991596.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6991596
+ * @summary JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC
+ *
+ * @run main/othervm -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6991596
+ */
+
+import java.lang.invoke.*;
+
+public class Test6991596 {
+    private static final Class   CLASS = Test6991596.class;
+    private static final String  NAME  = "foo";
+    private static final boolean DEBUG = System.getProperty("DEBUG", "false").equals("true");
+
+    public static void main(String[] args) throws Throwable {
+        testboolean();
+        testbyte();
+        testchar();
+        testshort();
+        testint();
+        testlong();
+    }
+
+    // Helpers to get various methods.
+    static MethodHandle getmh1(Class ret, Class arg) throws ReflectiveOperationException {
+        return MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(ret, arg));
+    }
+    static MethodHandle getmh2(MethodHandle mh1, Class ret, Class arg) {
+        return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
+    }
+    static MethodHandle getmh3(MethodHandle mh1, Class ret, Class arg) {
+        return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
+    }
+
+    // test adapter_opt_i2i
+    static void testboolean() throws Throwable {
+        boolean[] a = new boolean[] {
+            true,
+            false
+        };
+        for (int i = 0; i < a.length; i++) {
+            doboolean(a[i]);
+        }
+    }
+    static void doboolean(boolean x) throws Throwable {
+        if (DEBUG)  System.out.println("boolean=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, boolean.class);
+            // TODO add this for all cases when the bugs are fixed.
+            //MethodHandle mh3 = getmh3(mh1, boolean.class, boolean.class);
+            boolean a = (boolean) mh1.invokeExact((boolean) x);
+            boolean b = (boolean) mh2.invokeExact(x);
+            //boolean c = mh3.<boolean>invokeExact((boolean) x);
+            check(x, a, b);
+            //check(x, c, x);
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class,    byte.class   );
+            MethodHandle mh2 = getmh2(mh1, byte.class,    boolean.class);
+            byte a = (byte) mh1.invokeExact((byte) (x ? 1 : 0));
+            byte b = (byte) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, boolean.class);
+            char a = (char) mh1.invokeExact((char) (x ? 1 : 0));
+            char b = (char) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, boolean.class);
+            short a = (short) mh1.invokeExact((short) (x ? 1 : 0));
+            short b = (short) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+    }
+
+    static void testbyte() throws Throwable {
+        byte[] a = new byte[] {
+            Byte.MIN_VALUE,
+            Byte.MIN_VALUE + 1,
+            -0x0F,
+            -1,
+            0,
+            1,
+            0x0F,
+            Byte.MAX_VALUE - 1,
+            Byte.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            dobyte(a[i]);
+        }
+    }
+    static void dobyte(byte x) throws Throwable {
+        if (DEBUG)  System.out.println("byte=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, byte.class);
+            boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+            boolean b = (boolean) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, byte.class);
+            byte a = (byte) mh1.invokeExact((byte) x);
+            byte b = (byte) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, byte.class);
+            char a = (char) mh1.invokeExact((char) x);
+            char b = (char) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, byte.class);
+            short a = (short) mh1.invokeExact((short) x);
+            short b = (short) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+    }
+
+    static void testchar() throws Throwable {
+        char[] a = new char[] {
+            Character.MIN_VALUE,
+            Character.MIN_VALUE + 1,
+            0x000F,
+            0x00FF,
+            0x0FFF,
+            Character.MAX_VALUE - 1,
+            Character.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            dochar(a[i]);
+        }
+    }
+    static void dochar(char x) throws Throwable {
+        if (DEBUG)  System.out.println("char=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, char.class);
+            boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+            boolean b = (boolean) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, char.class);
+            byte a = (byte) mh1.invokeExact((byte) x);
+            byte b = (byte) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, char.class);
+            char a = (char) mh1.invokeExact((char) x);
+            char b = (char) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, char.class);
+            short a = (short) mh1.invokeExact((short) x);
+            short b = (short) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+    }
+
+    static void testshort() throws Throwable {
+        short[] a = new short[] {
+            Short.MIN_VALUE,
+            Short.MIN_VALUE + 1,
+            -0x0FFF,
+            -0x00FF,
+            -0x000F,
+            -1,
+            0,
+            1,
+            0x000F,
+            0x00FF,
+            0x0FFF,
+            Short.MAX_VALUE - 1,
+            Short.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            doshort(a[i]);
+        }
+    }
+    static void doshort(short x) throws Throwable {
+        if (DEBUG)  System.out.println("short=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, short.class);
+            boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+            boolean b = (boolean) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, short.class);
+            byte a = (byte) mh1.invokeExact((byte) x);
+            byte b = (byte) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, short.class);
+            char a = (char) mh1.invokeExact((char) x);
+            char b = (char) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, short.class);
+            short a = (short) mh1.invokeExact((short) x);
+            short b = (short) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+    }
+
+    static void testint() throws Throwable {
+        int[] a = new int[] {
+            Integer.MIN_VALUE,
+            Integer.MIN_VALUE + 1,
+            -0x0FFFFFFF,
+            -0x00FFFFFF,
+            -0x000FFFFF,
+            -0x0000FFFF,
+            -0x00000FFF,
+            -0x000000FF,
+            -0x0000000F,
+            -1,
+            0,
+            1,
+            0x0000000F,
+            0x000000FF,
+            0x00000FFF,
+            0x0000FFFF,
+            0x000FFFFF,
+            0x00FFFFFF,
+            0x0FFFFFFF,
+            Integer.MAX_VALUE - 1,
+            Integer.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            doint(a[i]);
+        }
+    }
+    static void doint(int x) throws Throwable {
+        if (DEBUG)  System.out.println("int=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, int.class);
+            boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+            boolean b = (boolean) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, int.class);
+            byte a = (byte) mh1.invokeExact((byte) x);
+            byte b = (byte) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, int.class);
+            char a = (char) mh1.invokeExact((char) x);
+            char b = (char) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, int.class);
+            short a = (short) mh1.invokeExact((short) x);
+            short b = (short) mh2.invokeExact(x);
+            assert a == b : a + " != " + b;
+            check(x, a, b);
+        }
+
+        // int
+        {
+            MethodHandle mh1 = getmh1(     int.class, int.class);
+            MethodHandle mh2 = getmh2(mh1, int.class, int.class);
+            int a = (int) mh1.invokeExact((int) x);
+            int b = (int) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+    }
+
+    // test adapter_opt_l2i
+    static void testlong() throws Throwable {
+        long[] a = new long[] {
+            Long.MIN_VALUE,
+            Long.MIN_VALUE + 1,
+            -0x000000000FFFFFFFL,
+            -0x0000000000FFFFFFL,
+            -0x00000000000FFFFFL,
+            -0x000000000000FFFFL,
+            -0x0000000000000FFFL,
+            -0x00000000000000FFL,
+            -0x000000000000000FL,
+            -1L,
+            0L,
+            1L,
+            0x000000000000000FL,
+            0x00000000000000FFL,
+            0x0000000000000FFFL,
+            0x0000000000000FFFL,
+            0x000000000000FFFFL,
+            0x00000000000FFFFFL,
+            0x0000000000FFFFFFL,
+            0x000000000FFFFFFFL,
+            Long.MAX_VALUE - 1,
+            Long.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            dolong(a[i]);
+        }
+    }
+    static void dolong(long x) throws Throwable {
+        if (DEBUG)  System.out.println("long=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, long.class);
+            boolean a = (boolean) mh1.invokeExact((x & 1L) == 1L);
+            boolean b = (boolean) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, long.class);
+            byte a = (byte) mh1.invokeExact((byte) x);
+            byte b = (byte) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, long.class);
+            char a = (char) mh1.invokeExact((char) x);
+            char b = (char) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, long.class);
+            short a = (short) mh1.invokeExact((short) x);
+            short b = (short) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+
+        // int
+        {
+            MethodHandle mh1 = getmh1(     int.class, int.class);
+            MethodHandle mh2 = getmh2(mh1, int.class, long.class);
+            int a = (int) mh1.invokeExact((int) x);
+            int b = (int) mh2.invokeExact(x);
+            check(x, a, b);
+        }
+    }
+
+    static void check(boolean x, boolean e, boolean a) { p(z2h(x), z2h(e), z2h(a)); assert e == a : z2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+    static void check(boolean x, byte    e, byte    a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+    static void check(boolean x, int     e, int     a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+    static void check(int     x, boolean e, boolean a) { p(i2h(x), z2h(e), z2h(a)); assert e == a : i2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+    static void check(int     x, byte    e, byte    a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+    static void check(int     x, int     e, int     a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+    static void check(long    x, boolean e, boolean a) { p(l2h(x), z2h(e), z2h(a)); assert e == a : l2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+    static void check(long    x, byte    e, byte    a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+    static void check(long    x, int     e, int     a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+    static void p(String x, String e, String a) { if (DEBUG)  System.out.println(x + ": expected: " + e + ", actual: " + a); }
+
+    static String z2h(boolean x) { return x ? "1" : "0"; }
+    static String i2h(int     x) { return Integer.toHexString(x); }
+    static String l2h(long    x) { return Long.toHexString(x); }
+
+    // to int
+    public static boolean foo(boolean i) { return i; }
+    public static byte    foo(byte    i) { return i; }
+    public static char    foo(char    i) { return i; }
+    public static short   foo(short   i) { return i; }
+    public static int     foo(int     i) { return i; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/ClassValueTest.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary tests for class-specific values
+ * @compile ClassValueTest.java
+ * @run junit/othervm test.java.lang.invoke.ClassValueTest
+ */
+
+/*
+  Manually:
+   $ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/lang/invoke/ClassValueTest.java
+   $ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.lang.invoke.ClassValueTest
+  Output: .testAdd => 1000 : Integer
+ */
+
+package test.java.lang.invoke;
+
+import java.util.*;
+
+import java.lang.invoke.*;
+
+import org.junit.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author jrose
+ */
+public class ClassValueTest {
+    static String nameForCV1(Class<?> type) {
+        return "CV1:" + type.getName();
+    }
+    static int countForCV1;
+    static final ClassValue<String> CV1 = new CV1();
+    private static class CV1 extends ClassValue<String> {
+        protected String computeValue(Class<?> type) {
+            countForCV1++;
+            return nameForCV1(type);
+        }
+    }
+
+    static final Class[] CLASSES = {
+        String.class,
+        Integer.class,
+        int.class,
+        boolean[].class,
+        char[][].class,
+        ClassValueTest.class
+    };
+
+    @Test
+    public void testGet() {
+        countForCV1 = 0;
+        for (Class c : CLASSES) {
+            assertEquals(nameForCV1(c), CV1.get(c));
+        }
+        assertEquals(CLASSES.length, countForCV1);
+        for (Class c : CLASSES) {
+            assertEquals(nameForCV1(c), CV1.get(c));
+        }
+        assertEquals(CLASSES.length, countForCV1);
+    }
+
+    @Test
+    public void testRemove() {
+        for (Class c : CLASSES) {
+            CV1.get(c);
+        }
+        countForCV1 = 0;
+        int REMCOUNT = 3;
+        for (int i = 0; i < REMCOUNT; i++) {
+            CV1.remove(CLASSES[i]);
+        }
+        assertEquals(0, countForCV1);  // no change
+        for (Class c : CLASSES) {
+            assertEquals(nameForCV1(c), CV1.get(c));
+        }
+        assertEquals(REMCOUNT, countForCV1);
+    }
+
+    static String nameForCVN(Class<?> type, int n) {
+        return "CV[" + n + "]" + type.getName();
+    }
+    static int countForCVN;
+    static class CVN extends ClassValue<String> {
+        final int n;
+        CVN(int n) { this.n = n; }
+        protected String computeValue(Class<?> type) {
+            countForCVN++;
+            return nameForCVN(type, n);
+        }
+    };
+
+    @Test
+    public void testGetMany() {
+        int CVN_COUNT1 = 100, CVN_COUNT2 = 100;
+        CVN cvns[] = new CVN[CVN_COUNT1 * CVN_COUNT2];
+        for (int n = 0; n < cvns.length; n++) {
+            cvns[n] = new CVN(n);
+        }
+        countForCVN = 0;
+        for (int pass = 0; pass <= 2; pass++) {
+            for (int i1 = 0; i1 < CVN_COUNT1; i1++) {
+                eachClass:
+                for (Class c : CLASSES) {
+                    for (int i2 = 0; i2 < CVN_COUNT2; i2++) {
+                        int n = i1*CVN_COUNT2 + i2;
+                        assertEquals(0, countForCVN);
+                        assertEquals(nameForCVN(c, n), cvns[n].get(c));
+                        cvns[n].get(c);  //get it again
+                        //System.out.println("getting "+n+":"+cvns[n].get(c));
+                        boolean doremove = (((i1 + i2) & 3) == 0);
+                        switch (pass) {
+                        case 0:
+                            assertEquals(1, countForCVN);
+                            break;
+                        case 1:
+                            // remove on middle pass
+                            assertEquals(0, countForCVN);
+                            if (doremove) {
+                                //System.out.println("removing "+n+":"+cvns[n].get(c));
+                                cvns[n].remove(c);
+                                assertEquals(0, countForCVN);
+                            }
+                            break;
+                        case 2:
+                            assertEquals(doremove ? 1 : 0, countForCVN);
+                            break;
+                        }
+                        countForCVN = 0;
+                        if (i1 > i2 && i1 < i2+5)  continue eachClass;  // leave diagonal gap
+                    }
+                }
+            }
+        }
+        assertEquals(countForCVN, 0);
+        for (int n = 0; n < cvns.length; n++) {
+            for (Class c : CLASSES) {
+                assertEquals(nameForCVN(c, n), cvns[n].get(c));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/InvokeDynamicPrintArgs.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary smoke test for invokedynamic instructions
+ * @build indify.Indify
+ * @compile InvokeDynamicPrintArgs.java
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic
+ *      indify.Indify
+ *      --verify-specifier-count=3 --transitionalJSR292=false
+ *      --expand-properties --classpath ${test.classes}
+ *      --java test.java.lang.invoke.InvokeDynamicPrintArgs --check-output
+ */
+
+package test.java.lang.invoke;
+
+import org.junit.Test;
+
+import java.util.*;
+import java.io.*;
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+public class InvokeDynamicPrintArgs {
+    public static void main(String... av) throws Throwable {
+        if (av.length > 0)  openBuf();  // --check-output mode
+        System.out.println("Printing some argument lists, starting with a empty one:");
+        INDY_nothing().invokeExact();                 // BSM specifier #0 = {bsm}
+        INDY_bar().invokeExact("bar arg", 1);         // BSM specifier #1 = {bsm2, Void.class, "void type"}
+        INDY_bar2().invokeExact("bar2 arg", 222);     // BSM specifier #1 = (same)
+        INDY_baz().invokeExact("baz arg", 2, 3.14);   // BSM specifier #2 = {bsm2, 1234.5}
+        INDY_foo().invokeExact("foo arg");            // BSM specifier #0 = (same)
+        // Hence, BSM specifier count should be 3.  See "--verify-specifier-count=3" above.
+        System.out.println("Done printing argument lists.");
+        closeBuf();
+    }
+
+    @Test
+    public void testInvokeDynamicPrintArgs() throws IOException {
+        System.err.println(System.getProperties());
+        String testClassPath = System.getProperty("build.test.classes.dir");
+        if (testClassPath == null)  throw new RuntimeException();
+        String[] args = new String[]{
+            "--verify-specifier-count=3", "--transitionalJSR292=false",
+            "--expand-properties", "--classpath", testClassPath,
+            "--java", "test.java.lang.invoke.InvokeDynamicPrintArgs", "--check-output"
+        };
+        System.err.println("Indify: "+Arrays.toString(args));
+        indify.Indify.main(args);
+    }
+
+    private static PrintStream oldOut;
+    private static ByteArrayOutputStream buf;
+    private static void openBuf() {
+        oldOut = System.out;
+        buf = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(buf));
+    }
+    private static void closeBuf() {
+        if (buf == null)  return;
+        System.out.flush();
+        System.setOut(oldOut);
+        String[] haveLines = new String(buf.toByteArray()).split("[\n\r]+");
+        for (String line : haveLines)  System.out.println(line);
+        Iterator<String> iter = Arrays.asList(haveLines).iterator();
+        for (String want : EXPECT_OUTPUT) {
+            String have = iter.hasNext() ? iter.next() : "[EOF]";
+            if (want.equals(have))  continue;
+            System.err.println("want line: "+want);
+            System.err.println("have line: "+have);
+            throw new AssertionError("unexpected output: "+have);
+        }
+        if (iter.hasNext())
+            throw new AssertionError("unexpected output: "+iter.next());
+    }
+    private static final String[] EXPECT_OUTPUT = {
+        "Printing some argument lists, starting with a empty one:",
+        "[test.java.lang.invoke.InvokeDynamicPrintArgs, nothing, ()void][]",
+        "[test.java.lang.invoke.InvokeDynamicPrintArgs, bar, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]",
+        "[test.java.lang.invoke.InvokeDynamicPrintArgs, bar2, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]",
+        "[test.java.lang.invoke.InvokeDynamicPrintArgs, baz, (String,int,double)void, 1234.5][baz arg, 2, 3.14]",
+        "[test.java.lang.invoke.InvokeDynamicPrintArgs, foo, (String)void][foo arg]",
+        "Done printing argument lists."
+    };
+
+    private static void printArgs(Object bsmInfo, Object... args) {
+        System.out.println(bsmInfo+Arrays.deepToString(args));
+    }
+    private static MethodHandle MH_printArgs() throws ReflectiveOperationException {
+        shouldNotCallThis();
+        return lookup().findStatic(lookup().lookupClass(),
+                                   "printArgs", methodType(void.class, Object.class, Object[].class));
+    }
+
+    private static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
+        // ignore caller and name, but match the type:
+        Object bsmInfo = Arrays.asList(caller, name, type);
+        return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
+    }
+    private static MethodType MT_bsm() {
+        shouldNotCallThis();
+        return methodType(CallSite.class, Lookup.class, String.class, MethodType.class);
+    }
+    private static MethodHandle MH_bsm() throws ReflectiveOperationException {
+        shouldNotCallThis();
+        return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());
+    }
+
+    private static CallSite bsm2(Lookup caller, String name, MethodType type, Object... arg) throws ReflectiveOperationException {
+        // ignore caller and name, but match the type:
+        List<Object> bsmInfo = new ArrayList<>(Arrays.asList(caller, name, type));
+        bsmInfo.addAll(Arrays.asList((Object[])arg));
+        return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
+    }
+    private static MethodType MT_bsm2() {
+        shouldNotCallThis();
+        return methodType(CallSite.class, Lookup.class, String.class, MethodType.class, Object[].class);
+    }
+    private static MethodHandle MH_bsm2() throws ReflectiveOperationException {
+        shouldNotCallThis();
+        return lookup().findStatic(lookup().lookupClass(), "bsm2", MT_bsm2());
+    }
+
+    private static MethodHandle INDY_nothing() throws Throwable {
+        shouldNotCallThis();
+        return ((CallSite) MH_bsm().invokeGeneric(lookup(),
+                                                  "nothing", methodType(void.class)
+                                                  )).dynamicInvoker();
+    }
+    private static MethodHandle INDY_foo() throws Throwable {
+        shouldNotCallThis();
+        return ((CallSite) MH_bsm().invokeGeneric(lookup(),
+                                                  "foo", methodType(void.class, String.class)
+                                                  )).dynamicInvoker();
+    }
+    private static MethodHandle INDY_bar() throws Throwable {
+        shouldNotCallThis();
+        return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
+                                                  "bar", methodType(void.class, String.class, int.class)
+                                                  , new Object[] { Void.class, "void type!",
+                                                                   1, 234.5F, 67.5, (long)89 }
+                                                  )).dynamicInvoker();
+    }
+    private static MethodHandle INDY_bar2() throws Throwable {
+        shouldNotCallThis();
+        return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
+                                                  "bar2", methodType(void.class, String.class, int.class)
+                                                  , new Object[] { Void.class, "void type!",
+                                                                   1, 234.5F, 67.5, (long)89 }
+                                                  )).dynamicInvoker();
+    }
+    private static MethodHandle INDY_baz() throws Throwable {
+        shouldNotCallThis();
+        return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
+                                                  "baz", methodType(void.class, String.class, int.class, double.class)
+                                                  , 1234.5
+                                                  )).dynamicInvoker();
+    }
+
+    private static void shouldNotCallThis() {
+        // if this gets called, the transformation has not taken place
+        if (System.getProperty("InvokeDynamicPrintArgs.allow-untransformed") != null)  return;
+        throw new AssertionError("this code should be statically transformed away by Indify");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/InvokeGenericTest.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandle.invokeGeneric
+ * @compile -XDallowTransitionalJSR292=no -target 7 InvokeGenericTest.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.InvokeGenericTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+import java.lang.reflect.*;
+import java.util.*;
+import org.junit.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+
+/**
+ *
+ * @author jrose
+ */
+public class InvokeGenericTest {
+    // How much output?
+    static int verbosity = 0;
+    static {
+        String vstr = System.getProperty("test.java.lang.invoke.InvokeGenericTest.verbosity");
+        if (vstr != null)  verbosity = Integer.parseInt(vstr);
+    }
+
+    @Test
+    public void testFirst() throws Throwable {
+        verbosity += 9; try {
+            // left blank for debugging
+        } finally { printCounts(); verbosity -= 9; }
+    }
+
+    public InvokeGenericTest() {
+    }
+
+    @Before
+    public void checkImplementedPlatform() {
+        boolean platformOK = false;
+        Properties properties = System.getProperties();
+        String vers = properties.getProperty("java.vm.version");
+        String name = properties.getProperty("java.vm.name");
+        String arch = properties.getProperty("os.arch");
+        if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
+             arch.equals("sparc") || arch.equals("sparcv9")) &&
+            (name.contains("Client") || name.contains("Server"))
+            ) {
+            platformOK = true;
+        } else {
+            System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
+        }
+        assumeTrue(platformOK);
+    }
+
+    String testName;
+    static int allPosTests, allNegTests;
+    int posTests, negTests;
+    @After
+    public void printCounts() {
+        if (verbosity >= 2 && (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");
+            allPosTests += posTests;
+            allNegTests += negTests;
+            posTests = negTests = 0;
+        }
+    }
+    void countTest(boolean positive) {
+        if (positive) ++posTests;
+        else          ++negTests;
+    }
+    void countTest() { countTest(true); }
+    void startTest(String name) {
+        if (testName != null)  printCounts();
+        if (verbosity >= 1)
+            System.out.println(name);
+        posTests = negTests = 0;
+        testName = name;
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        calledLog.clear();
+        calledLog.add(null);
+        nextArgVal = INITIAL_ARG_VAL;
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+        int posTests = allPosTests, negTests = allNegTests;
+        if (verbosity >= 2 && (posTests | negTests) != 0) {
+            System.out.println();
+            if (posTests != 0)  System.out.println("=== "+posTests+" total positive test cases");
+            if (negTests != 0)  System.out.println("=== "+negTests+" total negative test cases");
+        }
+    }
+
+    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) && verbosity < 9)  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", expected, actual);
+    }
+    static void printCalled(MethodHandle target, String name, Object... args) {
+        if (verbosity >= 3)
+            System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
+    }
+
+    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 final int ONE_MILLION = (1000*1000),  // first int value
+                     TEN_BILLION = (10*1000*1000*1000),  // scale factor to reach upper 32 bits
+                     INITIAL_ARG_VAL = ONE_MILLION << 1;  // <<1 makes space for sign bit;
+    static long nextArgVal;
+    static long nextArg(boolean moreBits) {
+        long val = nextArgVal++;
+        long sign = -(val & 1); // alternate signs
+        val >>= 1;
+        if (moreBits)
+            // Guarantee some bits in the high word.
+            // In any case keep the decimal representation simple-looking,
+            // with lots of zeroes, so as not to make the printed decimal
+            // strings unnecessarily noisy.
+            val += (val % ONE_MILLION) * TEN_BILLION;
+        return val ^ sign;
+    }
+    static int nextArg() {
+        // Produce a 32-bit result something like ONE_MILLION+(smallint).
+        // Example: 1_000_042.
+        return (int) nextArg(false);
+    }
+    static long nextArg(Class<?> kind) {
+        if (kind == long.class   || kind == Long.class ||
+            kind == double.class || kind == Double.class)
+            // produce a 64-bit result something like
+            // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
+            // Example: 10_000_420_001_000_042.
+            return nextArg(true);
+        return (long) nextArg();
+    }
+
+    static Object randomArg(Class<?> param) {
+        Object wrap = castToWrapperOrNull(nextArg(param), param);
+        if (wrap != null) {
+            return wrap;
+        }
+//        import sun.invoke.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()) {
+            for (Class<?> c : param.getClasses()) {
+                if (param.isAssignableFrom(c) && !c.isInterface())
+                    { param = c; break; }
+            }
+        }
+        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 final Object ANON_OBJ = new Object();
+    static Object zeroArg(Class<?> param) {
+        Object x = castToWrapperOrNull(0L, param);
+        if (x != null)  return x;
+        if (param.isInterface() || param.isAssignableFrom(String.class))  return "\"\"";
+        if (param == Object.class)  return ANON_OBJ;
+        if (param.getComponentType() != null)  return Array.newInstance(param.getComponentType(), 0);
+        return null;
+    }
+    static Object[] zeroArgs(Class<?>... params) {
+        Object[] args = new Object[params.length];
+        for (int i = 0; i < args.length; i++)
+            args[i] = zeroArg(params[i]);
+        return args;
+    }
+    static Object[] zeroArgs(List<Class<?>> params) {
+        return zeroArgs(params.toArray(new Class<?>[0]));
+    }
+
+    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 InvokeGenericTest.
+    static final Lookup LOOKUP = MethodHandles.lookup();
+
+    Map<List<Class<?>>, MethodHandle> CALLABLES = new HashMap<List<Class<?>>, MethodHandle>();
+    MethodHandle callable(List<Class<?>> params) {
+        MethodHandle mh = CALLABLES.get(params);
+        if (mh == null) {
+            mh = collector_MH.asType(methodType(Object.class, params));
+            CALLABLES.put(params, mh);
+        }
+        return mh;
+    }
+    MethodHandle callable(Class<?>... params) {
+        return callable(Arrays.asList(params));
+    }
+    private static Object collector(Object... args) {
+        return Arrays.asList(args);
+    }
+    private static final MethodHandle collector_MH;
+    static {
+        try {
+            collector_MH
+                = LOOKUP.findStatic(LOOKUP.lookupClass(),
+                                    "collector",
+                                    methodType(Object.class, Object[].class));
+        } catch (ReflectiveOperationException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    @Test
+    public void testSimple() throws Throwable {
+        startTest("testSimple");
+        countTest();
+        String[] args = { "one", "two" };
+        MethodHandle mh = callable(Object.class, String.class);
+        Object res; List resl;
+        res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]);
+        //System.out.println(res);
+        assertEquals(Arrays.asList(args), res);
+    }
+
+    @Test
+    public void testWrongArgumentCount() throws Throwable {
+        startTest("testWrongArgumentCount");
+        for (int i = 0; i <= 10; i++) {
+            testWrongArgumentCount(Collections.<Class<?>>nCopies(i, Integer.class));
+            if (i <= 4) {
+                testWrongArgumentCount(Collections.<Class<?>>nCopies(i, int.class));
+                testWrongArgumentCount(Collections.<Class<?>>nCopies(i, long.class));
+            }
+        }
+    }
+    public void testWrongArgumentCount(List<Class<?>> params) throws Throwable {
+        int max = params.size();
+        for (int i = 0; i < max; i++) {
+            List<Class<?>> params2 = params.subList(0, i);
+            for (int k = 0; k <= 2; k++) {
+                if (k == 1)  params  = methodType(Object.class,  params).generic().parameterList();
+                if (k == 2)  params2 = methodType(Object.class, params2).generic().parameterList();
+                testWrongArgumentCount(params, params2);
+                testWrongArgumentCount(params2, params);
+            }
+        }
+    }
+    public void testWrongArgumentCount(List<Class<?>> expect, List<Class<?>> observe) throws Throwable {
+        countTest(false);
+        if (expect.equals(observe))
+            assert(false);
+        MethodHandle target = callable(expect);
+        Object[] args = zeroArgs(observe);
+        Object junk;
+        try {
+            switch (args.length) {
+            case 0:
+                junk = target.invokeGeneric(); break;
+            case 1:
+                junk = target.invokeGeneric(args[0]); break;
+            case 2:
+                junk = target.invokeGeneric(args[0], args[1]); break;
+            case 3:
+                junk = target.invokeGeneric(args[0], args[1], args[2]); break;
+            case 4:
+                junk = target.invokeGeneric(args[0], args[1], args[2], args[3]); break;
+            default:
+                junk = target.invokeWithArguments(args); break;
+            }
+        } catch (WrongMethodTypeException ex) {
+            return;
+        } catch (Exception ex) {
+            throw new RuntimeException("wrong exception calling "+target+target.type()+" on "+Arrays.asList(args)+" : "+ex);
+        }
+        throw new RuntimeException("bad success calling "+target+target.type()+" on "+Arrays.asList(args));
+    }
+
+    /** Make a list of all combinations of the given types, with the given arities.
+     *  A void return type is possible iff the first type is void.class.
+     */
+    static List<MethodType> allMethodTypes(int minargc, int maxargc, Class<?>... types) {
+        ArrayList<MethodType> result = new ArrayList<MethodType>();
+        if (types.length > 0) {
+            ArrayList<MethodType> argcTypes = new ArrayList<MethodType>();
+            // build arity-zero types first
+            for (Class<?> rtype : types) {
+                argcTypes.add(MethodType.methodType(rtype));
+            }
+            if (types[0] == void.class)
+                // void is not an argument type
+                types = Arrays.copyOfRange(types, 1, types.length);
+            for (int argc = 0; argc <= maxargc; argc++) {
+                if (argc >= minargc)
+                    result.addAll(argcTypes);
+                if (argc >= maxargc)
+                    break;
+                ArrayList<MethodType> prevTypes = argcTypes;
+                argcTypes = new ArrayList<MethodType>();
+                for (MethodType prevType : prevTypes) {
+                    for (Class<?> ptype : types) {
+                        argcTypes.add(prevType.insertParameterTypes(argc, ptype));
+                    }
+                }
+            }
+        }
+        return Collections.unmodifiableList(result);
+    }
+    static List<MethodType> allMethodTypes(int argc, Class<?>... types) {
+        return allMethodTypes(argc, argc, types);
+    }
+
+    interface RandomInterface { }
+
+    MethodHandle toString_MH;
+
+    @Test
+    public void testReferenceConversions() throws Throwable {
+        startTest("testReferenceConversions");
+        toString_MH = LOOKUP.
+            findVirtual(Object.class, "toString", MethodType.methodType(String.class));
+        String[] args = { "one", "two" };
+        for (MethodType type : allMethodTypes(2, Object.class, String.class, RandomInterface.class)) {
+            testReferenceConversions(type, args);
+        }
+    }
+    public void testReferenceConversions(MethodType type, Object... args) throws Throwable {
+        countTest();
+        if (verbosity > 3)  System.out.println("target type: "+type);
+        MethodHandle mh = callable(type.parameterList());
+        MethodHandle tsdrop = MethodHandles.dropArguments(toString_MH, 1, type.parameterList());
+        mh = MethodHandles.foldArguments(tsdrop, mh);
+        mh = mh.asType(type);
+        Object res = mh.invokeGeneric((String)args[0], (Object)args[1]);
+        //System.out.println(res);
+        assertEquals(Arrays.asList(args).toString(), res);
+    }
+
+
+    @Test @Ignore("known failure pending 6939861")
+    public void testBoxConversions() throws Throwable {
+        startTest("testBoxConversions");
+        countTest();
+        Integer[] args = { 1, 2 };
+        MethodHandle mh = callable(Object.class, int.class);
+        Object res; List resl;
+        res = resl = (List) mh.invokeGeneric((int)args[0], (Object)args[1]);
+        //System.out.println(res);
+        assertEquals(Arrays.asList(args), res);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary example code used in javadoc for java.lang.invoke API
+ * @compile -XDallowTransitionalJSR292=no JavaDocExamplesTest.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.JavaDocExamplesTest
+ */
+
+/*
+---- To run outside jtreg:
+$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
+   $DAVINCI/sources/jdk/test/java/lang/invoke/JavaDocExamplesTest.java
+$ $JAVA7X_HOME/bin/java   -cp $JUNIT4_JAR:/tmp/Classes \
+   -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
+   -Dtest.java.lang.invoke.JavaDocExamplesTest.verbosity=1 \
+     test.java.lang.invoke.JavaDocExamplesTest
+----
+*/
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+
+/**
+ * @author jrose
+ */
+public class JavaDocExamplesTest {
+    /** Wrapper for running the JUnit tests in this module.
+     *  Put JUnit on the classpath!
+     */
+    public static void main(String... ignore) {
+        org.junit.runner.JUnitCore.runClasses(JavaDocExamplesTest.class);
+    }
+    // How much output?
+    static int verbosity = Integer.getInteger("test.java.lang.invoke.JavaDocExamplesTest.verbosity", 0);
+
+{}
+static final private Lookup LOOKUP = lookup();
+// static final private MethodHandle CONCAT_1 = LOOKUP.findVirtual(String.class,
+//     "concat", methodType(String.class, String.class));
+// static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class,
+//     "hashCode", methodType(int.class));
+
+// form required if ReflectiveOperationException is intercepted:
+static final private MethodHandle CONCAT_2, HASHCODE_2;
+static {
+  try {
+    CONCAT_2 = LOOKUP.findVirtual(String.class,
+      "concat", methodType(String.class, String.class));
+    HASHCODE_2 = LOOKUP.findVirtual(Object.class,
+      "hashCode", methodType(int.class));
+   } catch (ReflectiveOperationException ex) {
+     throw new RuntimeException(ex);
+   }
+}
+{}
+
+    @Test public void testFindVirtual() throws Throwable {
+{}
+MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class,
+  "hashCode", methodType(int.class));
+//assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y"));
+assertEquals("xy", (String) CONCAT_2.invokeExact("x", "y"));
+assertEquals("xy", (String) CONCAT_3.invokeExact("x", "y"));
+//assertEquals("xy".hashCode(), (int) HASHCODE_1.invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) HASHCODE_2.invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy"));
+{}
+    }
+    @Test public void testDropArguments() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
+MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
+assertEquals(bigType, d0.type());
+assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
+            }}
+        {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle d0 = dropArguments(cat, 0, String.class);
+assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
+MethodHandle d1 = dropArguments(cat, 1, String.class);
+assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
+MethodHandle d2 = dropArguments(cat, 2, String.class);
+assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
+MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
+            }}
+    }
+
+    @Test public void testFilterArguments() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle upcase = lookup().findVirtual(String.class,
+  "toUpperCase", methodType(String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle f0 = filterArguments(cat, 0, upcase);
+assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
+MethodHandle f1 = filterArguments(cat, 1, upcase);
+assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
+MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
+assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
+            }}
+    }
+
+    static void assertEquals(Object exp, Object act) {
+        if (verbosity > 0)
+            System.out.println("result: "+act);
+        Assert.assertEquals(exp, act);
+    }
+
+    @Test public void testMethodHandlesSummary() throws Throwable {
+        {{
+{} /// JAVADOC
+Object x, y; String s; int i;
+MethodType mt; MethodHandle mh;
+MethodHandles.Lookup lookup = MethodHandles.lookup();
+// mt is (char,char)String
+mt = MethodType.methodType(String.class, char.class, char.class);
+mh = lookup.findVirtual(String.class, "replace", mt);
+s = (String) mh.invokeExact("daddy",'d','n');
+// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
+assert(s.equals("nanny"));
+// weakly typed invocation (using MHs.invoke)
+s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
+assert(s.equals("savvy"));
+// mt is (Object[])List
+mt = MethodType.methodType(java.util.List.class, Object[].class);
+mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
+assert(mh.isVarargsCollector());
+x = mh.invokeGeneric("one", "two");
+// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
+assert(x.equals(java.util.Arrays.asList("one","two")));
+// mt is (Object,Object,Object)Object
+mt = MethodType.genericMethodType(3);
+mh = mh.asType(mt);
+x = mh.invokeExact((Object)1, (Object)2, (Object)3);
+// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+assert(x.equals(java.util.Arrays.asList(1,2,3)));
+// mt is { =&gt; int}
+mt = MethodType.methodType(int.class);
+mh = lookup.findVirtual(java.util.List.class, "size", mt);
+i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
+// invokeExact(Ljava/util/List;)I
+assert(i == 3);
+mt = MethodType.methodType(void.class, String.class);
+mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
+mh.invokeExact(System.out, "Hello, world.");
+// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
+{}
+            }}
+    }
+
+    @Test public void testAsVarargsCollector() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle asList = publicLookup()
+  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
+  .asVarargsCollector(Object[].class);
+assertEquals("[]", asList.invokeGeneric().toString());
+assertEquals("[1]", asList.invokeGeneric(1).toString());
+assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString());
+Object[] argv = { "three", "thee", "tee" };
+assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString());
+List ls = (List) asList.invokeGeneric((Object)argv);
+assertEquals(1, ls.size());
+assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
+            }}
+    }
+
+    @Test public void testVarargsCollectorSuppression() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle vamh = publicLookup()
+  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
+  .asVarargsCollector(Object[].class);
+MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
+assert(vamh.type().equals(mh.type()));
+assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString());
+boolean failed = false;
+try { mh.invokeGeneric(1,2,3); }
+catch (WrongMethodTypeException ex) { failed = true; }
+assert(failed);
+{}
+            }}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,2400 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandles
+ * @compile -source 7 -target 7 -XDallowTransitionalJSR292=no MethodHandlesTest.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.MethodHandlesTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.*;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.reflect.*;
+import java.util.*;
+import org.junit.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+
+/**
+ *
+ * @author jrose
+ */
+public class MethodHandlesTest {
+    // How much output?
+    static int verbosity = 0;
+    static {
+        String vstr = System.getProperty("test.java.lang.invoke.MethodHandlesTest.verbosity");
+        if (vstr != null)  verbosity = Integer.parseInt(vstr);
+    }
+
+    // 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 = true;
+
+    @Test
+    public void testFirst() throws Throwable {
+        verbosity += 9; try {
+            // left blank for debugging
+        } finally { printCounts(); verbosity -= 9; }
+    }
+
+    // current failures
+    @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
+    public void testFail_1() throws Throwable {
+        // AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters
+        testSpreadArguments(int.class, 0, 6);
+    }
+    @Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args")
+    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 {
+        // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
+        testSpreadArguments(int.class, 1, 2);
+    }
+    @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
+    public void testFail_4() throws Throwable {
+        // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
+        testCollectArguments(int.class, 1, 2);
+    }
+    @Test @Ignore("cannot collect leading primitive types")
+    public void testFail_5() throws Throwable {
+        // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
+        testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
+    }
+    @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit")
+    public void testFail_6() throws Throwable {
+        // ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13
+        testInsertArguments(0, 0, MAX_ARG_INCREASE+10);
+    }
+    static final int MAX_ARG_INCREASE = 3;
+
+    public MethodHandlesTest() {
+    }
+
+    @Before
+    public void checkImplementedPlatform() {
+        boolean platformOK = false;
+        Properties properties = System.getProperties();
+        String vers = properties.getProperty("java.vm.version");
+        String name = properties.getProperty("java.vm.name");
+        String arch = properties.getProperty("os.arch");
+        if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
+             arch.equals("sparc") || arch.equals("sparcv9")) &&
+            (name.contains("Client") || name.contains("Server"))
+            ) {
+            platformOK = true;
+        } else {
+            System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
+        }
+        assumeTrue(platformOK);
+    }
+
+    String testName;
+    static int allPosTests, allNegTests;
+    int posTests, negTests;
+    @After
+    public void printCounts() {
+        if (verbosity >= 2 && (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");
+            allPosTests += posTests;
+            allNegTests += negTests;
+            posTests = negTests = 0;
+        }
+    }
+    void countTest(boolean positive) {
+        if (positive) ++posTests;
+        else          ++negTests;
+    }
+    void countTest() { countTest(true); }
+    void startTest(String name) {
+        if (testName != null)  printCounts();
+        if (verbosity >= 1)
+            System.out.println(name);
+        posTests = negTests = 0;
+        testName = name;
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        calledLog.clear();
+        calledLog.add(null);
+        nextArgVal = INITIAL_ARG_VAL;
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+        int posTests = allPosTests, negTests = allNegTests;
+        if (verbosity >= 2 && (posTests | negTests) != 0) {
+            System.out.println();
+            if (posTests != 0)  System.out.println("=== "+posTests+" total positive test cases");
+            if (negTests != 0)  System.out.println("=== "+negTests+" total negative test cases");
+        }
+    }
+
+    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) && verbosity < 9)  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", expected, actual);
+    }
+    static void printCalled(MethodHandle target, String name, Object... args) {
+        if (verbosity >= 3)
+            System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
+    }
+
+    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 final int ONE_MILLION = (1000*1000),  // first int value
+                     TEN_BILLION = (10*1000*1000*1000),  // scale factor to reach upper 32 bits
+                     INITIAL_ARG_VAL = ONE_MILLION << 1;  // <<1 makes space for sign bit;
+    static long nextArgVal;
+    static long nextArg(boolean moreBits) {
+        long val = nextArgVal++;
+        long sign = -(val & 1); // alternate signs
+        val >>= 1;
+        if (moreBits)
+            // Guarantee some bits in the high word.
+            // In any case keep the decimal representation simple-looking,
+            // with lots of zeroes, so as not to make the printed decimal
+            // strings unnecessarily noisy.
+            val += (val % ONE_MILLION) * TEN_BILLION;
+        return val ^ sign;
+    }
+    static int nextArg() {
+        // Produce a 32-bit result something like ONE_MILLION+(smallint).
+        // Example: 1_000_042.
+        return (int) nextArg(false);
+    }
+    static long nextArg(Class<?> kind) {
+        if (kind == long.class   || kind == Long.class ||
+            kind == double.class || kind == Double.class)
+            // produce a 64-bit result something like
+            // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
+            // Example: 10_000_420_001_000_042.
+            return nextArg(true);
+        return (long) nextArg();
+    }
+
+    static Object randomArg(Class<?> param) {
+        Object wrap = castToWrapperOrNull(nextArg(param), param);
+        if (wrap != null) {
+            return wrap;
+        }
+//        import sun.invoke.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()) {
+            for (Class<?> c : param.getClasses()) {
+                if (param.isAssignableFrom(c) && !c.isInterface())
+                    { param = c; break; }
+            }
+        }
+        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();
+    }
+
+    /** Return lambda(arg...[arity]) { new Object[]{ arg... } } */
+    static MethodHandle varargsList(int arity) {
+        return ValueConversions.varargsList(arity);
+    }
+    /** Return lambda(arg...[arity]) { Arrays.asList(arg...) } */
+    static MethodHandle varargsArray(int arity) {
+        return ValueConversions.varargsArray(arity);
+    }
+    /** Variation of varargsList, but with the given rtype. */
+    static MethodHandle varargsList(int arity, Class<?> rtype) {
+        MethodHandle list = varargsList(arity);
+        MethodType listType = list.type().changeReturnType(rtype);
+        if (List.class.isAssignableFrom(rtype) || rtype == void.class || rtype == Object.class) {
+            // OK
+        } else if (rtype.isAssignableFrom(String.class)) {
+            if (LIST_TO_STRING == null)
+                try {
+                    LIST_TO_STRING = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToString",
+                                                        MethodType.methodType(String.class, List.class));
+                } catch (Exception ex) { throw new RuntimeException(ex); }
+            list = MethodHandles.filterReturnValue(list, LIST_TO_STRING);
+        } else if (rtype.isPrimitive()) {
+            if (LIST_TO_INT == null)
+                try {
+                    LIST_TO_INT = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToInt",
+                                                     MethodType.methodType(int.class, List.class));
+                } catch (Exception ex) { throw new RuntimeException(ex); }
+            list = MethodHandles.filterReturnValue(list, LIST_TO_INT);
+            list = MethodHandles.explicitCastArguments(list, listType);
+        } else {
+            throw new RuntimeException("varargsList: "+rtype);
+        }
+        return list.asType(listType);
+    }
+    private static MethodHandle LIST_TO_STRING, LIST_TO_INT;
+    private static String listToString(List x) { return x.toString(); }
+    private static int listToInt(List x) { return x.toString().hashCode(); }
+
+    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); }
+
+        static final Lookup EXAMPLE = MethodHandles.lookup();  // for testing findSpecial
+    }
+    static final Lookup EXAMPLE = Example.EXAMPLE;
+    public static class PubExample extends Example {
+        public PubExample() { super("PubExample#"+nextArg()); }
+    }
+    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();
+        public static class Impl implements IntExample {
+            public void        v0()     { called("Int/v0", this); }
+            final String name;
+            public Impl() { name = "Impl#"+nextArg(); }
+            @Override public String toString() { return name; }
+        }
+    }
+
+    static final Object[][][] ACCESS_CASES = {
+        { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false
+        { { false, PUBLIC }, { false, PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[1]: only PRIVATE
+        { { false, PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[2]: PUBLIC false
+        { { true,  PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[3]: all true
+    };
+
+    static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) {
+        Object[][] cases;
+        if (name.contains("pri_") || isSpecial) {
+            cases = ACCESS_CASES[1]; // PRIVATE only
+        } else if (name.contains("pkg_") || !Modifier.isPublic(defc.getModifiers())) {
+            cases = ACCESS_CASES[2]; // not PUBLIC
+        } else {
+            assertTrue(name.indexOf('_') < 0);
+            boolean pubc = Modifier.isPublic(defc.getModifiers());
+            if (pubc)
+                cases = ACCESS_CASES[3]; // all access levels
+            else
+                cases = ACCESS_CASES[2]; // PACKAGE but not PUBLIC
+        }
+        if (defc != Example.class && cases[cases.length-1][1] == EXAMPLE)
+            cases = Arrays.copyOfRange(cases, 0, cases.length-1);
+        return cases;
+    }
+    static Object[][] accessCases(Class<?> defc, String name) {
+        return accessCases(defc, name, false);
+    }
+
+    @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;
+        Exception noAccess = null;
+        try {
+            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+            target = lookup.in(defc).findStatic(defc, name, type);
+        } catch (ReflectiveOperationException ex) {
+            noAccess = ex;
+            if (name.contains("bogus"))
+                assertTrue(noAccess instanceof NoSuchMethodException);
+            else
+                assertTrue(noAccess instanceof IllegalAccessException);
+        }
+        if (verbosity >= 3)
+            System.out.println("findStatic "+lookup+": "+defc.getName()+"."+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());
+        assertNameStringContains(target, name);
+        if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
+        Object[] args = randomArgs(params);
+        printCalled(target, name, args);
+        target.invokeWithArguments(args);
+        assertCalled(name, args);
+        if (verbosity >= 1)
+            System.out.print(':');
+    }
+
+    // rough check of name string
+    static void assertNameStringContains(Object x, String s) {
+        if (x.toString().contains(s))  return;
+        assertEquals(s, x);
+    }
+
+    @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;
+        Exception noAccess = null;
+        try {
+            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+            target = lookup.in(defc).findVirtual(defc, methodName, type);
+        } catch (ReflectiveOperationException ex) {
+            noAccess = ex;
+            if (name.contains("bogus"))
+                assertTrue(noAccess instanceof NoSuchMethodException);
+            else
+                assertTrue(noAccess instanceof IllegalAccessException);
+        }
+        if (verbosity >= 3)
+            System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+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);
+        assertEquals(typeWithSelf, target.type());
+        assertNameStringContains(target, methodName);
+        if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
+        Object[] argsWithSelf = randomArgs(paramsWithSelf);
+        if (rcvc != defc)  argsWithSelf[0] = randomArg(rcvc);
+        printCalled(target, name, argsWithSelf);
+        target.invokeWithArguments(argsWithSelf);
+        assertCalled(name, argsWithSelf);
+        if (verbosity >= 1)
+            System.out.print(':');
+    }
+
+    @Test
+    public void testFindSpecial() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("findSpecial");
+        testFindSpecial(SubExample.class, Example.class, void.class, "v0");
+        testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0");
+        // Do some negative testing:
+        testFindSpecial(false, EXAMPLE, SubExample.class, Example.class, void.class, "bogus");
+        testFindSpecial(false, PRIVATE, SubExample.class, Example.class, void.class, "bogus");
+        for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) {
+            testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0");
+            testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class);
+            testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0");
+        }
+    }
+
+    void testFindSpecial(Class<?> specialCaller,
+                         Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        testFindSpecial(true,  EXAMPLE, specialCaller, defc, ret, name, params);
+        testFindSpecial(true,  PRIVATE, specialCaller, defc, ret, name, params);
+        testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params);
+        testFindSpecial(false, PUBLIC,  specialCaller, defc, ret, name, params);
+    }
+    void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller,
+                         Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        countTest(positive);
+        MethodType type = MethodType.methodType(ret, params);
+        MethodHandle target = null;
+        Exception noAccess = null;
+        try {
+            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+            if (verbosity >= 5)  System.out.println("  lookup => "+lookup.in(specialCaller));
+            target = lookup.in(specialCaller).findSpecial(defc, name, type, specialCaller);
+        } catch (ReflectiveOperationException ex) {
+            noAccess = ex;
+            if (name.contains("bogus"))
+                assertTrue(noAccess instanceof NoSuchMethodException);
+            else
+                assertTrue(noAccess instanceof IllegalAccessException);
+        }
+        if (verbosity >= 3)
+            System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target
+                               +(target == null ? "" : target.type())
+                               +(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(specialCaller, target.type().parameterType(0));
+        assertEquals(type,          target.type().dropParameterTypes(0,1));
+        Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params);
+        MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
+        assertNameStringContains(target, name);
+        if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE)  return;
+        Object[] args = randomArgs(paramsWithSelf);
+        printCalled(target, name, args);
+        target.invokeWithArguments(args);
+        assertCalled(name, args);
+    }
+
+    @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;
+        Exception noAccess = null;
+        try {
+            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+            target = lookup.in(defc).bind(receiver, methodName, type);
+        } catch (ReflectiveOperationException ex) {
+            noAccess = ex;
+            if (name.contains("bogus"))
+                assertTrue(noAccess instanceof NoSuchMethodException);
+            else
+                assertTrue(noAccess instanceof IllegalAccessException);
+        }
+        if (verbosity >= 3)
+            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.invokeWithArguments(args);
+        Object[] argsWithReceiver = cat(array(Object[].class, receiver), args);
+        assertCalled(name, argsWithReceiver);
+        if (verbosity >= 1)
+            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)) {
+            testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params);
+        }
+    }
+    void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        for (Object[] ac : accessCases(defc, name)) {
+            testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
+        }
+    }
+    void testUnreflectMaybeSpecial(Class<?> specialCaller,
+                                   boolean positive, Lookup lookup,
+                                   Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        countTest(positive);
+        MethodType type = MethodType.methodType(ret, params);
+        Method rmethod = defc.getDeclaredMethod(name, params);
+        MethodHandle target = null;
+        Exception noAccess = null;
+        boolean isStatic = (rcvc == null);
+        boolean isSpecial = (specialCaller != null);
+        try {
+            if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+            if (isSpecial)
+                target = lookup.in(specialCaller).unreflectSpecial(rmethod, specialCaller);
+            else
+                target = lookup.in(defc).unreflect(rmethod);
+        } catch (ReflectiveOperationException ex) {
+            noAccess = ex;
+            if (name.contains("bogus"))
+                assertTrue(noAccess instanceof NoSuchMethodException);
+            else
+                assertTrue(noAccess instanceof IllegalAccessException);
+        }
+        if (verbosity >= 3)
+            System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type
+                               +(!isSpecial ? "" : " specialCaller="+specialCaller)
+                               +( isStatic  ? "" : " receiver="+rcvc)
+                               +" => "+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(isStatic, Modifier.isStatic(rmethod.getModifiers()));
+        Class<?>[] paramsMaybeWithSelf = params;
+        if (!isStatic) {
+            paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params);
+        }
+        MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf);
+        if (isStatic) {
+            assertEquals(typeMaybeWithSelf, target.type());
+        } else {
+            if (isSpecial)
+                assertEquals(specialCaller, target.type().parameterType(0));
+            else
+                assertEquals(defc, target.type().parameterType(0));
+            assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc));
+        }
+        Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf);
+        printCalled(target, name, argsMaybeWithSelf);
+        target.invokeWithArguments(argsMaybeWithSelf);
+        assertCalled(name, argsMaybeWithSelf);
+        if (verbosity >= 1)
+            System.out.print(':');
+    }
+
+    void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+        for (Object[] ac : accessCases(defc, name, true)) {
+            Class<?> specialCaller = rcvc;
+            testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
+        }
+    }
+
+    @Test
+    public void testUnreflectSpecial() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("unreflectSpecial");
+        testUnreflectSpecial(Example.class,    Example.class, void.class, "v0");
+        testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0");
+        testUnreflectSpecial(Example.class,    Example.class, void.class, "pkg_v0");
+        testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0");
+        testUnreflectSpecial(Example.class,    Example.class, Object.class, "v2", int.class, int.class);
+        testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class);
+        testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0");
+    }
+
+    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++;
+                        assertTrue(value.equals(v));
+                    }
+                    assertTrue(name.equals(field.getName()));
+                    assertTrue(type.equals(field.getType()));
+                    assertTrue(isStatic == (Modifier.isStatic(field.getModifiers())));
+                    cases.add(new Object[]{ field, value });
+                }
+            }
+            cases.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class });
+            cases.add(new Object[]{ new Object[]{ true,  HasFields.class, "bogus_sL", Object.class }, Error.class });
+            CASES = cases.toArray(new Object[0][]);
+        }
+    }
+
+    static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC = 3, TEST_SETTER = 0x10;
+    static boolean testModeMatches(int testMode, boolean isStatic) {
+        switch (testMode) {
+        case TEST_FIND_STATIC:          return isStatic;
+        case TEST_FIND_FIELD:           return !isStatic;
+        case TEST_UNREFLECT:            return true;  // unreflect matches both
+        }
+        throw new InternalError("testMode="+testMode);
+    }
+
+    @Test
+    public void testUnreflectGetter() throws Throwable {
+        startTest("unreflectGetter");
+        testGetter(TEST_UNREFLECT);
+    }
+    @Test
+    public void testFindGetter() throws Throwable {
+        startTest("findGetter");
+        testGetter(TEST_FIND_FIELD);
+    }
+    @Test
+    public void testFindStaticGetter() throws Throwable {
+        startTest("findStaticGetter");
+        testGetter(TEST_FIND_STATIC);
+    }
+    public void testGetter(int testMode) throws Throwable {
+        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
+        for (Object[] c : HasFields.CASES) {
+            boolean positive = (c[1] != Error.class);
+            testGetter(positive, lookup, c[0], c[1], testMode);
+        }
+        testGetter(true, lookup,
+                   new Object[]{ true,  System.class, "out", java.io.PrintStream.class },
+                   System.out, testMode);
+        for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
+            testGetter(false, lookup,
+                       new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
+                       null, testMode);
+        }
+    }
+    public void testGetter(boolean positive, MethodHandles.Lookup lookup,
+                           Object fieldRef, Object value, int testMode) throws Throwable {
+        testAccessor(positive, lookup, fieldRef, value, testMode);
+    }
+
+    public void testAccessor(boolean positive, MethodHandles.Lookup lookup,
+                             Object fieldRef, Object value, int testMode0) throws Throwable {
+        boolean isGetter = ((testMode0 & TEST_SETTER) == 0);
+        int testMode = testMode0 & ~TEST_SETTER;
+        boolean isStatic;
+        Class<?> fclass;
+        String   fname;
+        Class<?> ftype;
+        Field f = (fieldRef instanceof Field ? (Field)fieldRef : null);
+        if (f != null) {
+            isStatic = Modifier.isStatic(f.getModifiers());
+            fclass   = f.getDeclaringClass();
+            fname    = f.getName();
+            ftype    = f.getType();
+        } else {
+            Object[] scnt = (Object[]) fieldRef;
+            isStatic = (Boolean)  scnt[0];
+            fclass   = (Class<?>) scnt[1];
+            fname    = (String)   scnt[2];
+            ftype    = (Class<?>) scnt[3];
+            try {
+                f = fclass.getDeclaredField(fname);
+            } catch (ReflectiveOperationException ex) {
+                f = null;
+            }
+        }
+        if (!testModeMatches(testMode, isStatic))  return;
+        if (f == null && testMode == TEST_UNREFLECT)  return;
+        countTest(positive);
+        MethodType expType;
+        if (isGetter)
+            expType = MethodType.methodType(ftype, HasFields.class);
+        else
+            expType = MethodType.methodType(void.class, HasFields.class, ftype);
+        if (isStatic)  expType = expType.dropParameterTypes(0, 1);
+        Exception noAccess = null;
+        MethodHandle mh;
+        try {
+            switch (testMode0) {
+            case TEST_UNREFLECT:   mh = lookup.unreflectGetter(f);                      break;
+            case TEST_FIND_FIELD:  mh = lookup.findGetter(fclass, fname, ftype);        break;
+            case TEST_FIND_STATIC: mh = lookup.findStaticGetter(fclass, fname, ftype);  break;
+            case TEST_SETTER|
+                 TEST_UNREFLECT:   mh = lookup.unreflectSetter(f);                      break;
+            case TEST_SETTER|
+                 TEST_FIND_FIELD:  mh = lookup.findSetter(fclass, fname, ftype);        break;
+            case TEST_SETTER|
+                 TEST_FIND_STATIC: mh = lookup.findStaticSetter(fclass, fname, ftype);  break;
+            default:
+                throw new InternalError("testMode="+testMode);
+            }
+        } catch (ReflectiveOperationException ex) {
+            mh = null;
+            noAccess = ex;
+            if (fname.contains("bogus"))
+                assertTrue(noAccess instanceof NoSuchFieldException);
+            else
+                assertTrue(noAccess instanceof IllegalAccessException);
+        }
+        if (verbosity >= 3)
+            System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype
+                               +" => "+mh
+                               +(noAccess == null ? "" : " !! "+noAccess));
+        if (positive && noAccess != null)  throw new RuntimeException(noAccess);
+        assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, mh != null);
+        if (!positive)  return; // negative test failed as expected
+        assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount());
+
+
+        assertSame(mh.type(), expType);
+        assertNameStringContains(mh, fname);
+        HasFields fields = new HasFields();
+        Object sawValue;
+        Class<?> vtype = ftype;
+        if (ftype != int.class)  vtype = Object.class;
+        if (isGetter) {
+            mh = MethodHandles.convertArguments(mh, mh.type().generic()
+                                                .changeReturnType(vtype));
+        } else {
+            int last = mh.type().parameterCount() - 1;
+            mh = MethodHandles.convertArguments(mh, mh.type().generic()
+                                                .changeReturnType(void.class)
+                                                .changeParameterType(last, vtype));
+        }
+        if (f != null && f.getDeclaringClass() == HasFields.class) {
+            assertEquals(f.get(fields), value);  // clean to start with
+        }
+        if (isGetter) {
+            Object expValue = value;
+            for (int i = 0; i <= 1; i++) {
+                if (isStatic) {
+                    if (ftype == int.class)
+                        sawValue = (int) mh.invokeExact();  // do these exactly
+                    else
+                        sawValue = mh.invokeExact();
+                } else {
+                    if (ftype == int.class)
+                        sawValue = (int) mh.invokeExact((Object) fields);
+                    else
+                        sawValue = mh.invokeExact((Object) fields);
+                }
+                assertEquals(sawValue, expValue);
+                if (f != null && f.getDeclaringClass() == HasFields.class
+                    && !Modifier.isFinal(f.getModifiers())) {
+                    Object random = randomArg(ftype);
+                    f.set(fields, random);
+                    expValue = random;
+                } else {
+                    break;
+                }
+            }
+        } else {
+            for (int i = 0; i <= 1; i++) {
+                Object putValue = randomArg(ftype);
+                if (isStatic) {
+                    if (ftype == int.class)
+                        mh.invokeExact((int)putValue);  // do these exactly
+                    else
+                        mh.invokeExact(putValue);
+                } else {
+                    if (ftype == int.class)
+                        mh.invokeExact((Object) fields, (int)putValue);
+                    else
+                        mh.invokeExact((Object) fields, putValue);
+                }
+                if (f != null && f.getDeclaringClass() == HasFields.class) {
+                    assertEquals(f.get(fields), putValue);
+                }
+            }
+        }
+        if (f != null && f.getDeclaringClass() == HasFields.class) {
+            f.set(fields, value);  // put it back
+        }
+    }
+
+
+    @Test
+    public void testUnreflectSetter() throws Throwable {
+        startTest("unreflectSetter");
+        testSetter(TEST_UNREFLECT);
+    }
+    @Test
+    public void testFindSetter() throws Throwable {
+        startTest("findSetter");
+        testSetter(TEST_FIND_FIELD);
+    }
+    @Test
+    public void testFindStaticSetter() throws Throwable {
+        startTest("findStaticSetter");
+        testSetter(TEST_FIND_STATIC);
+    }
+    public void testSetter(int testMode) throws Throwable {
+        Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
+        startTest("unreflectSetter");
+        for (Object[] c : HasFields.CASES) {
+            boolean positive = (c[1] != Error.class);
+            testSetter(positive, lookup, c[0], c[1], testMode);
+        }
+        for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
+            testSetter(false, lookup,
+                       new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
+                       null, testMode);
+        }
+    }
+    public void testSetter(boolean positive, MethodHandles.Lookup lookup,
+                           Object fieldRef, Object value, int testMode) throws Throwable {
+        testAccessor(positive, lookup, fieldRef, value, testMode | TEST_SETTER);
+    }
+
+    @Test
+    public void testArrayElementGetter() throws Throwable {
+        startTest("arrayElementGetter");
+        testArrayElementGetterSetter(false);
+    }
+
+    @Test
+    public void testArrayElementSetter() throws Throwable {
+        startTest("arrayElementSetter");
+        testArrayElementGetterSetter(true);
+    }
+
+    public void testArrayElementGetterSetter(boolean testSetter) throws Throwable {
+        testArrayElementGetterSetter(new Object[10], testSetter);
+        testArrayElementGetterSetter(new String[10], testSetter);
+        testArrayElementGetterSetter(new boolean[10], testSetter);
+        testArrayElementGetterSetter(new byte[10], testSetter);
+        testArrayElementGetterSetter(new char[10], testSetter);
+        testArrayElementGetterSetter(new short[10], testSetter);
+        testArrayElementGetterSetter(new int[10], testSetter);
+        testArrayElementGetterSetter(new float[10], testSetter);
+        testArrayElementGetterSetter(new long[10], testSetter);
+        testArrayElementGetterSetter(new double[10], testSetter);
+    }
+
+    public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
+        countTest(true);
+        if (verbosity >= 2)  System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]");
+        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);
+        if (elemType != int.class && elemType != boolean.class) {
+            MethodType gtype;
+            if (true) { // FIXME: remove this path (and remove <void> below in the mh.invokes)
+                gtype = mh.type().changeParameterType(0, Object.class);
+                if (testSetter)
+                    gtype = gtype.changeParameterType(2, Object.class);
+                else
+                    gtype = gtype.changeReturnType(Object.class);
+            } else
+                // FIXME: This simpler path hits a bug in convertArguments => ToGeneric
+                gtype = mh.type().generic().changeParameterType(1, int.class);
+            mh = MethodHandles.convertArguments(mh, gtype);
+        }
+        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.invokeExact((int[]) array, i, (int)random);
+                else if (elemType == boolean.class)
+                    mh.invokeExact((boolean[]) array, i, (boolean)random);
+                else
+                    mh.invokeExact(array, i, random);
+                assertEquals(model, array2list(array));
+            } else {
+                Array.set(array, i, random);
+            }
+            if (verbosity >= 5) {
+                List<Object> array2list = array2list(array);
+                System.out.println("a["+i+"]="+random+" => "+array2list);
+                if (!array2list.equals(model))
+                    System.out.println("***   != "+model);
+            }
+            // observe array element
+            sawValue = Array.get(array, i);
+            if (!testSetter) {
+                expValue = sawValue;
+                if (elemType == int.class)
+                    sawValue = (int) mh.invokeExact((int[]) array, i);
+                else if (elemType == boolean.class)
+                    sawValue = (boolean) mh.invokeExact((boolean[]) array, i);
+                else
+                    sawValue = mh.invokeExact(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";
+            try {
+                return PRIVATE.findStatic(Callee.class, name, type);
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    @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);
+        testConvert(Callee.ofType(1), null, "id", char.class);
+        testConvert(Callee.ofType(1), null, "id", byte.class);
+    }
+
+    void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
+        testConvert(true, false, id, rtype, name, params);
+        testConvert(true, true,  id, rtype, name, params);
+    }
+
+    void testConvert(boolean positive, boolean useAsType,
+                     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.invokeWithArguments(convArgs);
+        {
+            Class<?> dst = newType.returnType();
+            Class<?> src = idType.returnType();
+            if (src != dst)
+                convResult = castToWrapper(convResult, dst);
+        }
+        MethodHandle target = null;
+        RuntimeException error = null;
+        try {
+            if (useAsType)
+                target = id.asType(newType);
+            else
+                target = MethodHandles.convertArguments(id, newType);
+        } catch (RuntimeException ex) {
+            error = ex;
+        }
+        if (verbosity >= 3)
+            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.invokeWithArguments(args);
+        assertCalled(name, convArgs);
+        assertEquals(convResult, result);
+        if (verbosity >= 1)
+            System.out.print(':');
+    }
+
+    @Test
+    public void testVarargsCollector() throws Throwable {
+        MethodHandle vac0 = PRIVATE.findStatic(MethodHandlesTest.class, "called",
+                               MethodType.methodType(Object.class, String.class, Object[].class));
+        vac0 = vac0.bindTo("vac");
+        MethodHandle vac = vac0.asVarargsCollector(Object[].class);
+        testConvert(true,  true,  vac.asType(MethodType.genericMethodType(0)), null, "vac");
+        testConvert(true,  true,  vac.asType(MethodType.genericMethodType(0)), null, "vac");
+        for (Class<?> at : new Class[] { Object.class, String.class, Integer.class }) {
+            testConvert(true,  true,  vac.asType(MethodType.genericMethodType(1)), null, "vac", at);
+            testConvert(true,  true,  vac.asType(MethodType.genericMethodType(2)), null, "vac", at, at);
+        }
+    }
+
+    @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 >= 2)
+            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;
+        assertTrue(inargs == types.length);
+        if (verbosity >= 3)
+            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 >= 4) {
+            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(varargsList(outargs), outType);
+        MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
+        Object result = newTarget.invokeWithArguments(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 >= 3)
+                System.out.println("spreadArguments "+argType);
+            // FIXME: enable _adapter_spread_args and fix Fail_2
+            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 = varargsArray(nargs);
+        MethodHandle target2 = changeArgTypes(target, argType);
+        if (verbosity >= 3)
+            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.invokeWithArguments(args);
+            assertArrayEquals(args, check);
+            switch (nargs) {
+                case 0:
+                    check = (Object[]) target.invokeExact();
+                    assertArrayEquals(args, check);
+                    break;
+                case 1:
+                    check = (Object[]) target.invokeExact(args[0]);
+                    assertArrayEquals(args, check);
+                    break;
+                case 2:
+                    check = (Object[]) target.invokeExact(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 = target2.asSpreader(Object[].class, nargs-pos).asType(newType);
+        Object[] returnValue;
+        if (pos == 0) {
+            // In the following line, the first cast implies
+            // normal Object return value for the MH call (Object[])->Object,
+            // while the second cast dynamically converts to an Object array.
+            // Such a double cast is typical of MH.invokeExact.
+            returnValue = (Object[]) (Object) result.invokeExact(args);
+        } else {
+            Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
+            args1[pos] = Arrays.copyOfRange(args, pos, args.length);
+            returnValue = (Object[]) result.invokeWithArguments(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 >= 3)
+                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 = 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 = varargsArray(pos+1);
+        target = changeArgTypes(target, 0, pos, argType);
+        target = changeArgTypes(target, pos, pos+1, Object[].class);
+        if (verbosity >= 3)
+            System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
+        MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType);
+        Object[] returnValue = (Object[]) result.invokeWithArguments(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 = 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 >= 3)
+            System.out.println("insert: "+argsToInsert+" into "+target);
+        MethodHandle target2 = MethodHandles.insertArguments(target, pos,
+                (Object[]) argsToInsert.toArray());
+        argsToInsert.clear();  // remove from argsToInsert
+        Object res2 = target2.invokeWithArguments(argsToPass);
+        Object res2List = Arrays.asList((Object[])res2);
+        if (verbosity >= 3)
+            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 testFilterReturnValue() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("filterReturnValue");
+        Class<?> classOfVCList = varargsList(1).invokeWithArguments(0).getClass();
+        assertTrue(List.class.isAssignableFrom(classOfVCList));
+        for (int nargs = 0; nargs <= 3; nargs++) {
+            for (Class<?> rtype : new Class[] { Object.class,
+                                                List.class,
+                                                int.class,
+                                                //byte.class, //FIXME: add this
+                                                //long.class, //FIXME: add this
+                                                CharSequence.class,
+                                                String.class }) {
+                testFilterReturnValue(nargs, rtype);
+            }
+        }
+    }
+
+    void testFilterReturnValue(int nargs, Class<?> rtype) throws Throwable {
+        countTest();
+        MethodHandle target = varargsList(nargs, rtype);
+        MethodHandle filter;
+        if (List.class.isAssignableFrom(rtype) || rtype.isAssignableFrom(List.class))
+            filter = varargsList(1);  // add another layer of list-ness
+        else
+            filter = MethodHandles.identity(rtype);
+        filter = filter.asType(MethodType.methodType(target.type().returnType(), rtype));
+        Object[] argsToPass = randomArgs(nargs, Object.class);
+        if (verbosity >= 3)
+            System.out.println("filter "+target+" to "+rtype.getSimpleName()+" with "+filter);
+        MethodHandle target2 = MethodHandles.filterReturnValue(target, filter);
+        if (verbosity >= 4)
+            System.out.println("filtered target: "+target2);
+        // Simulate expected effect of filter on return value:
+        Object unfiltered = target.invokeWithArguments(argsToPass);
+        Object expected = filter.invokeWithArguments(unfiltered);
+        if (verbosity >= 4)
+            System.out.println("unfiltered: "+unfiltered+" : "+unfiltered.getClass().getSimpleName());
+        if (verbosity >= 4)
+            System.out.println("expected: "+expected+" : "+expected.getClass().getSimpleName());
+        Object result = target2.invokeWithArguments(argsToPass);
+        if (verbosity >= 3)
+            System.out.println("result: "+result+" : "+result.getClass().getSimpleName());
+        if (!expected.equals(result))
+            System.out.println("*** fail at n/rt = "+nargs+"/"+rtype.getSimpleName()+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
+        assertEquals(expected, result);
+    }
+
+    @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 = varargsList(nargs);
+        MethodHandle filter = varargsList(1);
+        filter = MethodHandles.convertArguments(filter, filter.type().generic());
+        Object[] argsToPass = randomArgs(nargs, Object.class);
+        if (verbosity >= 3)
+            System.out.println("filter "+target+" at "+pos+" with "+filter);
+        MethodHandle target2 = MethodHandles.filterArguments(target, pos, filter);
+        // Simulate expected effect of filter on arglist:
+        Object[] filteredArgs = argsToPass.clone();
+        filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]);
+        List<Object> expected = Arrays.asList(filteredArgs);
+        Object result = target2.invokeWithArguments(argsToPass);
+        if (verbosity >= 3)
+            System.out.println("result: "+result);
+        if (!expected.equals(result))
+            System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
+        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 = varargsList(1 + nargs);
+        MethodHandle combine = varargsList(fold).asType(MethodType.genericMethodType(fold));
+        List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
+        if (verbosity >= 3)
+            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 >= 3)
+            System.out.println("fold: "+argsToFold+" into "+target2);
+        Object foldedArgs = combine.invokeWithArguments(argsToFold);
+        argsToFold.add(0, foldedArgs);
+        Object result = target2.invokeWithArguments(argsToPass);
+        if (verbosity >= 3)
+            System.out.println("result: "+result);
+        if (!expected.equals(result))
+            System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected);
+        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 = 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.invokeWithArguments(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 >= 3)
+            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));
+        assertTrue(target.isVarargsCollector());
+        target = target.asType(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.invokeWithArguments(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.invokeExact(target);
+                break;
+            case 1:
+                result = inv.invokeExact(target, args[0]);
+                break;
+            case 2:
+                result = inv.invokeExact(target, args[0], args[1]);
+                break;
+            case 3:
+                result = inv.invokeExact(target, args[0], args[1], args[2]);
+                break;
+            }
+            if (testRetCode)  assertEquals(code, result);
+            assertCalled("invokee", args);
+        }
+        calledLog.clear();
+        result = inv.invokeWithArguments(targetPlusArgs);
+        if (testRetCode)  assertEquals(code, result);
+        assertCalled("invokee", args);
+        // varargs invoker #0
+        calledLog.clear();
+        inv = MethodHandles.spreadInvoker(type, 0);
+        result = inv.invokeExact(target, args);
+        if (testRetCode)  assertEquals(code, result);
+        assertCalled("invokee", args);
+        if (nargs >= 1) {
+            // varargs invoker #1
+            calledLog.clear();
+            inv = MethodHandles.spreadInvoker(type, 1);
+            result = inv.invokeExact(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.spreadInvoker(type, 2);
+            result = inv.invokeExact(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.spreadInvoker(type, 3);
+            result = inv.invokeExact(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.spreadInvoker(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.invokeWithArguments(targetPlusVarArgs);
+            if (testRetCode)  assertEquals(code, result);
+            assertCalled("invokee", args);
+        }
+
+        // dynamic invoker
+        countTest();
+        CallSite site = new MutableCallSite(type);
+        inv = site.dynamicInvoker();
+
+        // see if we get the result of the original target:
+        try {
+            result = inv.invokeWithArguments(args);
+            assertTrue("should not reach here", false);
+        } catch (IllegalStateException ex) {
+            String msg = ex.getMessage();
+            assertTrue(msg, msg.contains("site"));
+        }
+
+        // set new target after invoker is created, to make sure we track target
+        site.setTarget(target);
+        calledLog.clear();
+        result = inv.invokeWithArguments(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 >= 3)
+                System.out.println(logEntry(willCall, argList));
+            Object result = mh.invokeWithArguments(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 >= 3)
+            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.asType(MethodType.genericMethodType(2));
+        while (thrower.type().parameterCount() < nargs)
+            thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class);
+        MethodHandle catcher = varargsList(1+nargs).asType(MethodType.genericMethodType(1+nargs));
+        MethodHandle target = MethodHandles.catchException(thrower,
+                thrown.getClass(), catcher);
+        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.invokeWithArguments(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());
+        target = MethodHandles.convertArguments(target, target.type().generic());
+        Throwable caught = null;
+        try {
+            Object res = target.invokeExact((Object) 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 {
+        public MethodHandle asMethodHandle() {
+            return VALUE.bindTo(this);
+        }
+        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 VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY;
+        static {
+            try {
+                VALUE = PRIVATE.findVirtual(
+                    Surprise.class, "value",
+                        MethodType.methodType(Object.class, Object.class));
+                REF_IDENTITY = PRIVATE.findStatic(
+                    Surprise.class, "refIdentity",
+                        MethodType.methodType(Object.class, Object.class));
+                BOX_IDENTITY = PRIVATE.findStatic(
+                    Surprise.class, "boxIdentity",
+                        MethodType.methodType(Integer.class, Integer.class));
+                INT_IDENTITY = PRIVATE.findStatic(
+                    Surprise.class, "intIdentity",
+                        MethodType.methodType(int.class, int.class));
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    void testCastFailure(String mode, int okCount) throws Throwable {
+        countTest(false);
+        if (verbosity > 2)  System.out.println("mode="+mode);
+        Surprise boo = new Surprise();
+        MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0;
+        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, 0, surprise);
+                identity = MethodHandles.filterArguments(callee, 0, identity);
+            }
+        }
+        assertNotSame(mode, surprise, surprise0);
+        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.invokeExact(x);
+            assertEquals(x, y);
+            Object z = surprise.invokeExact(x);
+            assertEquals(x, z);
+        }
+        boo.boo("Boo!");
+        Object y = identity.invokeExact(x);
+        assertEquals(x, y);
+        try {
+            Object z = surprise.invokeExact(x);
+            System.out.println("Failed to throw; got z="+z);
+            assertTrue(false);
+        } catch (Exception ex) {
+            if (verbosity > 2)
+                System.out.println("caught "+ex);
+            if (verbosity > 3)
+                ex.printStackTrace();
+            assertTrue(ex instanceof ClassCastException
+                    // FIXME: accept only one of the two for any given unit test
+                    || ex instanceof WrongMethodTypeException
+                    );
+        }
+    }
+
+    static Example userMethod(Object o, String s, int i) {
+        called("userMethod", o, s, i);
+        return null;
+    }
+
+    @Test
+    public void testUserClassInSignature() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("testUserClassInSignature");
+        Lookup lookup = MethodHandles.lookup();
+        String name; MethodType mt; MethodHandle mh;
+        Object[] args;
+
+        // Try a static method.
+        name = "userMethod";
+        mt = MethodType.methodType(Example.class, Object.class, String.class, int.class);
+        mh = lookup.findStatic(lookup.lookupClass(), name, mt);
+        assertEquals(mt, mh.type());
+        assertEquals(Example.class, mh.type().returnType());
+        args = randomArgs(mh.type().parameterArray());
+        mh.invokeWithArguments(args);
+        assertCalled(name, args);
+
+        // Try a virtual method.
+        name = "v2";
+        mt = MethodType.methodType(Object.class, Object.class, int.class);
+        mh = lookup.findVirtual(Example.class, name, mt);
+        assertEquals(mt, mh.type().dropParameterTypes(0,1));
+        assertTrue(mh.type().parameterList().contains(Example.class));
+        args = randomArgs(mh.type().parameterArray());
+        mh.invokeWithArguments(args);
+        assertCalled(name, args);
+    }
+
+    static void runForRunnable() {
+        called("runForRunnable");
+    }
+    private interface Fooable {
+        Object foo(Fooable x, Object y);
+        // this is for randomArg:
+        public class Impl implements Fooable {
+            public Object foo(Fooable x, Object y) {
+                throw new RuntimeException("do not call");
+            }
+            final String name;
+            public Impl() { name = "Fooable#"+nextArg(); }
+            @Override public String toString() { return name; }
+        }
+    }
+    static Object fooForFooable(Fooable x, Object y) {
+        return called("fooForFooable", x, y);
+    }
+    private static class MyCheckedException extends Exception {
+    }
+    private interface WillThrow {
+        void willThrow() throws MyCheckedException;
+    }
+
+    @Test
+    public void testAsInstance() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        Lookup lookup = MethodHandles.lookup();
+        {
+            MethodType mt = MethodType.methodType(void.class);
+            MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt);
+            Runnable proxy = MethodHandles.asInstance(mh, Runnable.class);
+            proxy.run();
+            assertCalled("runForRunnable");
+        }
+        {
+            MethodType mt = MethodType.methodType(Object.class, Fooable.class, Object.class);
+            MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", mt);
+            Fooable proxy = MethodHandles.asInstance(mh, Fooable.class);
+            Object[] args = randomArgs(mt.parameterArray());
+            Object result = proxy.foo((Fooable) args[0], args[1]);
+            assertCalled("fooForFooable", args);
+            assertEquals(result, logEntry("fooForFooable", args));
+        }
+        for (Throwable ex : new Throwable[] { new NullPointerException("ok"),
+                                              new InternalError("ok"),
+                                              new Throwable("fail"),
+                                              new Exception("fail"),
+                                              new MyCheckedException()
+                                            }) {
+            MethodHandle mh = MethodHandles.throwException(void.class, Throwable.class);
+            mh = MethodHandles.insertArguments(mh, 0, ex);
+            WillThrow proxy = MethodHandles.asInstance(mh, WillThrow.class);
+            try {
+                proxy.willThrow();
+                System.out.println("Failed to throw: "+ex);
+                assertTrue(false);
+            } catch (Throwable ex1) {
+                if (verbosity > 2) {
+                    System.out.println("throw "+ex);
+                    System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1));
+                }
+                if (ex instanceof RuntimeException ||
+                    ex instanceof Error) {
+                    assertSame("must pass unchecked exception out without wrapping", ex, ex1);
+                } else if (ex instanceof MyCheckedException) {
+                    assertSame("must pass declared exception out without wrapping", ex, ex1);
+                } else {
+                    assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1);
+                    UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1;
+                    assertSame(ex, utex.getCause());
+                }
+            }
+        }
+        // Test error checking:
+        for (Class<?> nonSAM : new Class[] { Object.class,
+                                             String.class,
+                                             CharSequence.class,
+                                             Example.class }) {
+            try {
+                MethodHandles.asInstance(varargsArray(0), nonSAM);
+                System.out.println("Failed to throw");
+                assertTrue(false);
+            } catch (IllegalArgumentException ex) {
+            }
+        }
+    }
+}
+// Local abbreviated copy of sun.invoke.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 (ReflectiveOperationException ex) {
+                // break from loop!
+            }
+            if (array == null)  break;
+            arrays.add(array);
+        }
+        assertTrue(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: cannot form a varargs array of length "+nargs);
+    }
+
+    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> lists = new ArrayList<MethodHandle>();
+        MethodHandles.Lookup lookup = IMPL_LOOKUP;
+        for (;;) {
+            int nargs = lists.size();
+            MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
+            String name = "list";
+            MethodHandle list = null;
+            try {
+                list = lookup.findStatic(ValueConversions.class, name, type);
+            } catch (ReflectiveOperationException ex) {
+                // break from loop!
+            }
+            if (list == null)  break;
+            lists.add(list);
+        }
+        assertTrue(lists.size() == 11);  // current number of methods
+        return lists.toArray(new MethodHandle[0]);
+    }
+    static final MethodHandle[] LISTS = makeLists();
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns List.
+     */
+    public static MethodHandle varargsList(int nargs) {
+        if (nargs < LISTS.length)
+            return LISTS[nargs];
+        // else need to spin bytecode or do something else fancy
+        throw new UnsupportedOperationException("NYI");
+    }
+}
+// This guy tests access from outside the same package member, but inside
+// the package itself.
+class PackageSibling {
+    static Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/MethodTypeTest.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,567 @@
+/*
+ * Copyright 2008, 2011 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.lang.invoke.MethodType
+ * @compile MethodTypeTest.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.MethodTypeTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+
+import java.util.*;
+import org.junit.*;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author jrose
+ */
+public class MethodTypeTest {
+
+    private Class<?> rtype;
+    private Class<?>[] ptypes;
+    private MethodType mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov;
+    private MethodType mt_iSI, mt_ISi, mt_ISI, mt_iSi;
+    private MethodType mt_viO, mt_iO2, mt_OOi, mt_iOi;
+    private MethodType mt_VIO, mt_IO2, mt_OOI, mt_IOI, mt_VIS;
+    private MethodType mt_vOiSzA, mt_OO99;
+    private MethodType[] GALLERY;
+    private Method compareTo;
+
+    @Before
+    public void setUp() throws Exception {
+        rtype = void.class;
+        ptypes = new Class<?>[] { int.class, String.class };
+
+        mt_viS = MethodType.methodType(void.class, int.class, String.class);
+        mt_OO = MethodType.methodType(Object.class, Object.class);
+        mt_OO2 = MethodType.methodType(Object.class, Object.class, Object.class);
+        mt_vv = MethodType.methodType(void.class);
+        mt_Vv = MethodType.methodType(Void.class);
+        mt_Ov = MethodType.methodType(Object.class);
+        mt_iSI = MethodType.methodType(int.class, String.class, Integer.class);
+        mt_ISi = MethodType.methodType(Integer.class, String.class, int.class);
+        mt_ISI = MethodType.methodType(Integer.class, String.class, Integer.class);
+        mt_iSi = MethodType.methodType(int.class, String.class, int.class);
+
+        compareTo = String.class.getDeclaredMethod("compareTo", String.class);
+
+        mt_viO = MethodType.methodType(void.class, int.class, Object.class);
+        mt_iO2 = MethodType.methodType(int.class, Object.class, Object.class);
+        mt_OOi = MethodType.methodType(Object.class, Object.class, int.class);
+        mt_iOi = MethodType.methodType(int.class, Object.class, int.class);
+
+        mt_VIO = MethodType.methodType(Void.class, Integer.class, Object.class);
+        mt_IO2 = MethodType.methodType(Integer.class, Object.class, Object.class);
+        mt_OOI = MethodType.methodType(Object.class, Object.class, Integer.class);
+        mt_IOI = MethodType.methodType(Integer.class, Object.class, Integer.class);
+        mt_VIS = MethodType.methodType(Void.class, Integer.class, String.class);
+
+        mt_vOiSzA = MethodType.methodType(void.class, Object.class, int.class, String.class, boolean.class, Object[].class);
+        mt_OO99 = MethodType.genericMethodType(99);
+
+        GALLERY = new MethodType[] {
+            mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov,
+            mt_iSI, mt_ISi, mt_ISI, mt_iSi,
+            mt_viO, mt_iO2, mt_OOi, mt_iOi,
+            mt_VIO, mt_IO2, mt_OOI, mt_IOI,
+            mt_VIS, mt_vOiSzA, mt_OO99
+        };
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /** Make sure the method types are all distinct. */
+    @Test
+    public void testDistinct() {
+        List<MethodType> gallery2 = new ArrayList<>();
+        for (MethodType mt : GALLERY) {
+            assertFalse(mt.toString(), gallery2.contains(mt));
+            gallery2.add(mt);
+        }
+        // check self-equality also:
+        assertEquals(Arrays.asList(GALLERY), gallery2);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_Class_ClassArr() {
+        System.out.println("make (from type array)");
+        MethodType result = MethodType.methodType(rtype, ptypes);
+        assertSame(mt_viS, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_Class_List() {
+        System.out.println("make (from type list)");
+        MethodType result = MethodType.methodType(rtype, Arrays.asList(ptypes));
+        assertSame(mt_viS, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_3args() {
+        System.out.println("make (from type with varargs)");
+        MethodType result = MethodType.methodType(rtype, ptypes[0], ptypes[1]);
+        assertSame(mt_viS, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_Class() {
+        System.out.println("make (from single type)");
+        Class<?> rt = Integer.class;
+        MethodType expResult = MethodType.methodType(rt, new Class<?>[0]);
+        MethodType result = MethodType.methodType(rt);
+        assertSame(expResult, result);
+    }
+
+    @Test
+    public void testMakeGeneric() {
+        System.out.println("makeGeneric");
+        int objectArgCount = 2;
+        MethodType expResult = mt_OO2;
+        MethodType result = MethodType.genericMethodType(objectArgCount);
+        assertSame(expResult, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_MethodType() {
+        System.out.println("make (from rtype, MethodType)");
+        MethodType expResult = mt_iO2;
+        MethodType result = MethodType.methodType(int.class, mt_IO2);
+        assertSame(expResult, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_String_ClassLoader() {
+        System.out.println("make (from bytecode signature)");
+        ClassLoader loader = null;
+        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        String obj = "Ljava/lang/Object;";
+        assertEquals(obj, concat(Object.class));
+        String[] expResults = {
+            "(ILjava/lang/String;)V",
+            concat("(", obj, 2, ")", Object.class),
+            "()V", "()"+obj,
+            concat("(", String.class, Integer.class, ")I"),
+            concat("(", String.class, "I)", Integer.class),
+            concat("(", String.class, Integer.class, ")", Integer.class),
+            concat("(", String.class, "I)I")
+        };
+        for (int i = 0; i < instances.length; i++) {
+            MethodType instance = instances[i];
+            String result = instance.toMethodDescriptorString();
+            assertEquals("#"+i, expResults[i], result);
+            MethodType parsed = MethodType.fromMethodDescriptorString(result, loader);
+            assertSame("--#"+i, instance, parsed);
+        }
+    }
+    private static String concat(Object... parts) {
+        StringBuilder sb = new StringBuilder();
+        Object prevPart = "";
+        for (Object part : parts) {
+            if (part instanceof Class) {
+                part = "L"+((Class)part).getName()+";";
+            }
+            if (part instanceof Integer) {
+                for (int n = (Integer) part; n > 1; n--)
+                    sb.append(prevPart);
+                part = "";
+            }
+            sb.append(part);
+            prevPart = part;
+        }
+        return sb.toString().replace('.', '/');
+    }
+
+    @Test
+    public void testHasPrimitives() {
+        System.out.println("hasPrimitives");
+        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        boolean[] expResults =   {true,   false,  true,  false, true,   true,   false,  true};
+        for (int i = 0; i < instances.length; i++) {
+            boolean result = instances[i].hasPrimitives();
+            assertEquals("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testHasWrappers() {
+        System.out.println("hasWrappers");
+        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        boolean[] expResults =   {false,  false,  false, false, true,   true,   true,   false};
+        for (int i = 0; i < instances.length; i++) {
+            System.out.println("  hasWrappers "+instances[i]);
+            boolean result = instances[i].hasWrappers();
+            assertEquals("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testErase() {
+        System.out.println("erase");
+        MethodType[] instances  = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        MethodType[] expResults = {mt_viO, mt_OO2, mt_vv, mt_Ov, mt_iO2, mt_OOi, mt_OO2, mt_iOi};
+        for (int i = 0; i < instances.length; i++) {
+            MethodType result = instances[i].erase();
+            assertSame("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testGeneric() {
+        System.out.println("generic");
+        MethodType[] instances =  {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        MethodType[] expResults = {mt_OO2, mt_OO2, mt_Ov, mt_Ov, mt_OO2, mt_OO2, mt_OO2, mt_OO2};
+        for (int i = 0; i < instances.length; i++) {
+            MethodType result = instances[i].generic();
+            assertSame("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testWrap() {
+        System.out.println("wrap");
+        MethodType[] instances =  {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        MethodType[] expResults = {mt_VIS, mt_OO2, mt_Vv, mt_Ov, mt_ISI, mt_ISI, mt_ISI, mt_ISI};
+        for (int i = 0; i < instances.length; i++) {
+            MethodType result = instances[i].wrap();
+            assertSame("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testUnwrap() {
+        System.out.println("unwrap");
+        MethodType[] instances =  {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        MethodType[] expResults = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSi, mt_iSi, mt_iSi, mt_iSi};
+        for (int i = 0; i < instances.length; i++) {
+            MethodType result = instances[i].unwrap();
+            assertSame("#"+i, expResults[i], result);
+        }
+    }
+
+    /**
+     * Test of parameterType method, of class MethodType.
+     */
+    @Test
+    public void testParameterType() {
+        System.out.println("parameterType");
+        for (int num = 0; num < ptypes.length; num++) {
+            MethodType instance = mt_viS;
+            Class<?> expResult = ptypes[num];
+            Class<?> result = instance.parameterType(num);
+            assertSame(expResult, result);
+        }
+    }
+
+    /**
+     * Test of parameterCount method, of class MethodType.
+     */
+    @Test
+    public void testParameterCount() {
+        System.out.println("parameterCount");
+        MethodType instance = mt_viS;
+        int expResult = 2;
+        int result = instance.parameterCount();
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of returnType method, of class MethodType.
+     */
+    @Test
+    public void testReturnType() {
+        System.out.println("returnType");
+        MethodType instance = mt_viS;
+        Class<?> expResult = void.class;
+        Class<?> result = instance.returnType();
+        assertSame(expResult, result);
+    }
+
+    /**
+     * Test of parameterList method, of class MethodType.
+     */
+    @Test
+    public void testParameterList() {
+        System.out.println("parameterList");
+        MethodType instance = mt_viS;
+        List<Class<?>> expResult = Arrays.asList(ptypes);
+        List<Class<?>> result = instance.parameterList();
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of parameterArray method, of class MethodType.
+     */
+    @Test
+    public void testParameterArray() {
+        System.out.println("parameterArray");
+        MethodType instance = mt_viS;
+        Class<?>[] expResult = ptypes;
+        Class<?>[] result = instance.parameterArray();
+        assertEquals(Arrays.asList(expResult), Arrays.asList(result));
+    }
+
+    /**
+     * Test of equals method, of class MethodType.
+     */
+    @Test
+    public void testEquals_Object() {
+        System.out.println("equals");
+        Object x = null;
+        MethodType instance = mt_viS;
+        boolean expResult = false;
+        boolean result = instance.equals(x);
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of equals method, of class MethodType.
+     */
+    @Test
+    public void testEquals_MethodType() {
+        System.out.println("equals");
+        MethodType that = mt_viS;
+        MethodType instance = mt_viS;
+        boolean expResult = true;
+        boolean result = instance.equals(that);
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of hashCode method, of class MethodType.
+     */
+    @Test
+    public void testHashCode() {
+        System.out.println("hashCode");
+        MethodType instance = mt_viS;
+        ArrayList<Class<?>> types = new ArrayList<Class<?>>();
+        types.add(instance.returnType());
+        types.addAll(instance.parameterList());
+        int expResult = types.hashCode();
+        int result = instance.hashCode();
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of toString method, of class MethodType.
+     */
+    @Test
+    public void testToString() {
+        System.out.println("toString");
+        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        //String expResult = "void[int, class java.lang.String]";
+        String[] expResults = {
+            "(int,String)void",
+            "(Object,Object)Object",
+            "()void",
+            "()Object",
+            "(String,Integer)int",
+            "(String,int)Integer",
+            "(String,Integer)Integer",
+            "(String,int)int"
+        };
+        for (int i = 0; i < instances.length; i++) {
+            MethodType instance = instances[i];
+            String result = instance.toString();
+            System.out.println("#"+i+":"+result);
+            assertEquals("#"+i, expResults[i], result);
+        }
+    }
+
+    private static byte[] writeSerial(Object x) throws java.io.IOException {
+        try (java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
+             java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(bout)
+             ) {
+            out.writeObject(x);
+            out.flush();
+            return bout.toByteArray();
+        }
+    }
+    private static Object readSerial(byte[] wire) throws java.io.IOException, ClassNotFoundException {
+        try (java.io.ByteArrayInputStream bin = new java.io.ByteArrayInputStream(wire);
+             java.io.ObjectInputStream in = new java.io.ObjectInputStream(bin)) {
+            return in.readObject();
+        }
+    }
+    private static void testSerializedEquality(Object x) throws java.io.IOException, ClassNotFoundException {
+        if (x instanceof Object[])
+            x = Arrays.asList((Object[]) x);  // has proper equals method
+        byte[] wire = writeSerial(x);
+        Object y = readSerial(wire);
+        assertEquals(x, y);
+    }
+
+    /** Test (de-)serialization. */
+    @Test
+    public void testSerialization() throws Throwable {
+        System.out.println("serialization");
+        for (MethodType mt : GALLERY) {
+            testSerializedEquality(mt);
+        }
+        testSerializedEquality(GALLERY);
+
+        // Make a list of mixed objects:
+        List<Object> stuff = new ArrayList<>();
+        Collections.addAll(stuff, GALLERY);  // copy #1
+        Object[] triples = Arrays.copyOfRange(GALLERY, 0, GALLERY.length/2);
+        Collections.addAll(stuff, triples);  // copy #3 (partial)
+        for (MethodType mt : GALLERY) {
+            Collections.addAll(stuff, mt.parameterArray());
+        }
+        Collections.shuffle(stuff, new Random(292));
+        Collections.addAll(stuff, GALLERY);  // copy #2
+        testSerializedEquality(stuff);
+    }
+
+    /** Test serialization formats. */
+    @Test
+    public void testPortableSerialFormat() throws Throwable {
+        System.out.println("portable serial format");
+        boolean generateData = false;
+        //generateData = true;  // set this true to generate the following input data:
+        Object[][] cases = {
+            { mt_vv, new byte[] {  // ()void
+                    (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+                    (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+                    (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x6f, (byte)0x69, (byte)0x64,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00,
+                    (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e,
+                    (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61,
+                    (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab, (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb,
+                    (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+                } },
+            { mt_OO, new byte[] {  // (Object)Object
+                    (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+                    (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+                    (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61,
+                    (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62,
+                    (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+                    (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00, (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a,
+                    (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
+                    (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61, (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab,
+                    (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb, (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02,
+                    (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01,
+                    (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x03, (byte)0x78,
+                } },
+            { mt_vOiSzA, new byte[] {  // (Object,int,String,boolean,Object[])void
+                    (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+                    (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+                    (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x6f, (byte)0x69, (byte)0x64,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00,
+                    (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e,
+                    (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61,
+                    (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab, (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb,
+                    (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00,
+                    (byte)0x03, (byte)0x69, (byte)0x6e, (byte)0x74, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+                    (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76,
+                    (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x53,
+                    (byte)0x74, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x67, (byte)0xa0, (byte)0xf0, (byte)0xa4,
+                    (byte)0x38, (byte)0x7a, (byte)0x3b, (byte)0xb3, (byte)0x42, (byte)0x02, (byte)0x00, (byte)0x00,
+                    (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x07, (byte)0x62, (byte)0x6f,
+                    (byte)0x6f, (byte)0x6c, (byte)0x65, (byte)0x61, (byte)0x6e, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x13, (byte)0x5b, (byte)0x4c,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74,
+                    (byte)0x3b, (byte)0x90, (byte)0xce, (byte)0x58, (byte)0x9f, (byte)0x10, (byte)0x73, (byte)0x29,
+                    (byte)0x6c, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x78,
+                } },
+        };
+        for (Object[] c : cases) {
+            MethodType mt = (MethodType) c[0];
+            System.out.println("deserialize "+mt);
+            byte[] wire = (byte[]) c[1];
+            if (generateData) {
+                System.out.println("<generateData>");
+                wire = writeSerial(mt);
+                final String INDENT = "                ";
+                System.out.print("{  // "+mt);
+                for (int i = 0; i < wire.length; i++) {
+                    if (i % 8 == 0) { System.out.println(); System.out.print(INDENT+"   "); }
+                    String hex = Integer.toHexString(wire[i] & 0xFF);
+                    if (hex.length() == 1)  hex = "0"+hex;
+                    System.out.print(" (byte)0x"+hex+",");
+                }
+                System.out.println();
+                System.out.println(INDENT+"}");
+                System.out.println("</generateData>");
+                System.out.flush();
+            }
+            Object decode;
+            try {
+                decode = readSerial(wire);
+            } catch (Exception ex) {
+                decode = ex;  // oops!
+            }
+            assertEquals(mt, decode);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/indify/Indify.java	Thu Mar 24 00:17:59 2011 -0700
@@ -0,0 +1,1906 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package indify;
+
+import java.util.*;
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.regex.*;
+
+/**
+ * Transform one or more class files to incorporate JSR 292 features,
+ * such as {@code invokedynamic}.
+ * <p>
+ * This is a standalone program in a single source file.
+ * In this form, it may be useful for test harnesses, small experiments, and javadoc examples.
+ * Copies of this file may show up in multiple locations for standalone usage.
+ * The primary maintained location of this file is as follows:
+ * <a href="http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java">
+ * http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java</a>
+ * <p>
+ * Static private methods named MH_x and MT_x (where x is arbitrary)
+ * must be stereotyped generators of MethodHandle and MethodType
+ * constants.  All calls to them are transformed to {@code CONSTANT_MethodHandle}
+ * and {@code CONSTANT_MethodType} "ldc" instructions.
+ * The stereotyped code must create method types by calls to {@code methodType} or
+ * {@code fromMethodDescriptorString}.  The "lookup" argument must be created
+ * by calls to {@code java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
+ * The class and string arguments must be constant.
+ * The following methods of {@code java.lang.invoke.MethodHandle.Lookup Lookup} are
+ * allowed for method handle creation: {@code findStatic}, {@code findVirtual},
+ * {@code findConstructor}, {@code findSpecial},
+ * {@code findGetter}, {@code findSetter},
+ * {@code findStaticGetter}, or {@code findStaticSetter}.
+ * The call to one of these methods must be followed immediately
+ * by an {@code areturn} instruction.
+ * The net result of the call to the MH_x or MT_x method must be
+ * the creation of a constant method handle.  Thus, replacing calls
+ * to MH_x or MT_x methods by {@code ldc} instructions should leave
+ * the meaning of the program unchanged.
+ * <p>
+ * Static private methods named INDY_x must be stereotyped generators
+ * of {@code invokedynamic} call sites.
+ * All calls to them must be immediately followed by
+ * {@code invokeExact} calls.
+ * All such pairs of calls are transformed to {@code invokedynamic}
+ * instructions.  Each INDY_x method must begin with a call to a
+ * MH_x method, which is taken to be its bootstrap method.
+ * The method must be immediately invoked (via {@code invokeGeneric}
+ * on constant lookup, name, and type arguments.  An object array of
+ * constants may also be appended to the {@code invokeGeneric call}.
+ * This call must be cast to {@code CallSite}, and the result must be
+ * immediately followed by a call to {@code dynamicInvoker}, with the
+ * resulting method handle returned.
+ * <p>
+ * The net result of all of these actions is equivalent to the JVM's
+ * execution of an {@code invokedynamic} instruction in the unlinked state.
+ * Running this code once should produce the same results as running
+ * the corresponding {@code invokedynamic} instruction.
+ * In order to model the caching behavior, the code of an INDY_x
+ * method is allowed to begin with getstatic, aaload, and if_acmpne
+ * instructions which load a static method handle value and return it
+ * if the value is non-null.
+ * <p>
+ * Example usage:
+ * <blockquote><pre>
+$ JAVA_HOME=(some recent OpenJDK 7 build)
+$ ant
+$ $JAVA_HOME/bin/java -cp build/classes indify.Indify --overwrite --dest build/testout build/classes/indify/Example.class
+$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/classes indify.Example
+MT = (java.lang.Object)java.lang.Object
+MH = adder(int,int)java.lang.Integer
+adder(1,2) = 3
+calling indy:  42
+$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/testout indify.Example
+(same output as above)
+ * </pre></blockquote>
+ * <p>
+ * Before OpenJDK build b123, the format of {@code CONSTANT_InvokeDynamic} is in transition,
+ * and the switch {@code --transitionalJSR292=yes} is recommended.
+ * It is turned <em>off</em> by default, but users of earlier builds may need to turn it on.
+ * <p>
+ * A version of this transformation built on top of <a href="http://asm.ow2.org/">http://asm.ow2.org/</a> would be welcome.
+ * @author John Rose
+ */
+public class Indify {
+    public static void main(String... av) throws IOException {
+        new Indify().run(av);
+    }
+
+    public File dest;
+    public String[] classpath = {"."};
+    public boolean keepgoing = false;
+    public boolean expandProperties = false;
+    public boolean overwrite = false;
+    public boolean quiet = false;
+    public boolean verbose = false;
+    public boolean transitionalJSR292 = false;  // final version is distributed
+    public boolean all = false;
+    public int verifySpecifierCount = -1;
+
+    public void run(String... av) throws IOException {
+        List<String> avl = new ArrayList<>(Arrays.asList(av));
+        parseOptions(avl);
+        if (avl.isEmpty())
+            throw new IllegalArgumentException("Usage: indify [--dest dir] [option...] file...");
+        if ("--java".equals(avl.get(0))) {
+            avl.remove(0);
+            try {
+                runApplication(avl.toArray(new String[0]));
+            } catch (Exception ex) {
+                if (ex instanceof RuntimeException)  throw (RuntimeException) ex;
+                throw new RuntimeException(ex);
+            }
+            return;
+        }
+        Exception err = null;
+        for (String a : avl) {
+            try {
+                indify(a);
+            } catch (Exception ex) {
+                if (err == null)  err = ex;
+                System.err.println("failure on "+a);
+                if (!keepgoing)  break;
+            }
+        }
+        if (err != null) {
+            if (err instanceof IOException)  throw (IOException) err;
+            throw (RuntimeException) err;
+        }
+    }
+
+    /** Execute the given application under a class loader which indifies all application classes. */
+    public void runApplication(String... av) throws Exception {
+        List<String> avl = new ArrayList<>(Arrays.asList(av));
+        String mainClassName = avl.remove(0);
+        av = avl.toArray(new String[0]);
+        Class<?> mainClass = Class.forName(mainClassName, true, makeClassLoader());
+        java.lang.reflect.Method main = mainClass.getMethod("main", String[].class);
+        try { main.setAccessible(true); } catch (SecurityException ex) { }
+        main.invoke(null, (Object) av);
+    }
+
+    public void parseOptions(List<String> av) throws IOException {
+        for (; !av.isEmpty(); av.remove(0)) {
+            String a = av.get(0);
+            if (a.startsWith("-")) {
+                String a2 = null;
+                int eq = a.indexOf('=');
+                if (eq > 0) {
+                    a2 = maybeExpandProperties(a.substring(eq+1));
+                    a = a.substring(0, eq+1);
+                }
+                switch (a) {
+                case "--java":
+                    return;  // keep this argument
+                case "-d": case "--dest": case "-d=": case "--dest=":
+                    dest = new File(a2 != null ? a2 : maybeExpandProperties(av.remove(1)));
+                    break;
+                case "-cp": case "--classpath":
+                    classpath = maybeExpandProperties(av.remove(1)).split("["+File.pathSeparatorChar+"]");
+                    break;
+                case "-k": case "--keepgoing": case "--keepgoing=":
+                    keepgoing = booleanOption(a2);  // print errors but keep going
+                    break;
+                case "--expand-properties": case "--expand-properties=":
+                    expandProperties = booleanOption(a2);  // expand property references in subsequent arguments
+                    break;
+                case "--verify-specifier-count": case "--verify-specifier-count=":
+                    verifySpecifierCount = Integer.valueOf(a2);
+                    break;
+                case "--overwrite": case "--overwrite=":
+                    overwrite = booleanOption(a2);  // overwrite output files
+                    break;
+                case "--all": case "--all=":
+                    all = booleanOption(a2);  // copy all classes, even if no patterns
+                    break;
+                case "-q": case "--quiet": case "--quiet=":
+                    quiet = booleanOption(a2);  // less output
+                    break;
+                case "-v": case "--verbose": case "--verbose=":
+                    verbose = booleanOption(a2);  // more output
+                    break;
+                case "--transitionalJSR292": case "--transitionalJSR292=":
+                    transitionalJSR292 = booleanOption(a2);  // use older invokedynamic format
+                    break;
+                default:
+                    throw new IllegalArgumentException("unrecognized flag: "+a);
+                }
+                continue;
+            } else {
+                break;
+            }
+        }
+        if (dest == null && !overwrite)
+            throw new RuntimeException("no output specified; need --dest d or --overwrite");
+        if (expandProperties) {
+            for (int i = 0; i < av.size(); i++)
+                av.set(i, maybeExpandProperties(av.get(i)));
+        }
+    }
+
+    private boolean booleanOption(String s) {
+        if (s == null)  return true;
+        switch (s) {
+        case "true":  case "yes": case "on":  case "1": return true;
+        case "false": case "no":  case "off": case "0": return false;
+        }
+        throw new IllegalArgumentException("unrecognized boolean flag="+s);
+    }
+
+    private String maybeExpandProperties(String s) {
+        if (!expandProperties)  return s;
+        Set<String> propsDone = new HashSet<>();
+        while (s.contains("${")) {
+            int lbrk = s.indexOf("${");
+            int rbrk = s.indexOf('}', lbrk);
+            if (rbrk < 0)  break;
+            String prop = s.substring(lbrk+2, rbrk);
+            if (!propsDone.add(prop))  break;
+            String value = System.getProperty(prop);
+            if (verbose)  System.err.println("expanding ${"+prop+"} => "+value);
+            if (value == null)  break;
+            s = s.substring(0, lbrk) + value + s.substring(rbrk+1);
+        }
+        return s;
+    }
+
+    public void indify(String a) throws IOException {
+        File f = new File(a);
+        String fn = f.getName();
+        if (fn.endsWith(".class") && f.isFile())
+            indifyFile(f, dest);
+        else if (fn.endsWith(".jar") && f.isFile())
+            indifyJar(f, dest);
+        else if (f.isDirectory())
+            indifyTree(f, dest);
+        else if (!keepgoing)
+            throw new RuntimeException("unrecognized file: "+a);
+    }
+
+    private void ensureDirectory(File dir) {
+        if (dir.mkdirs() && !quiet)
+            System.err.println("created "+dir);
+    }
+
+    public void indifyFile(File f, File dest) throws IOException {
+        if (verbose)  System.err.println("reading "+f);
+        ClassFile cf = new ClassFile(f);
+        Logic logic = new Logic(cf);
+        boolean changed = logic.transform();
+        logic.reportPatternMethods(quiet, keepgoing);
+        if (changed || all) {
+            File outfile;
+            if (dest != null) {
+                ensureDirectory(dest);
+                outfile = classPathFile(dest, cf.nameString());
+            } else {
+                outfile = f;  // overwrite input file, no matter where it is
+            }
+            cf.writeTo(outfile);
+            if (!quiet)  System.err.println("wrote "+outfile);
+        }
+    }
+
+    File classPathFile(File pathDir, String className) {
+        String qualname = className.replace('.','/')+".class";
+        qualname = qualname.replace('/', File.separatorChar);
+        return new File(pathDir, qualname);
+    }
+
+    public void indifyJar(File f, Object dest) throws IOException {
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    public void indifyTree(File f, File dest) throws IOException {
+        if (verbose)  System.err.println("reading directory: "+f);
+        for (File f2 : f.listFiles(new FilenameFilter() {
+                public boolean accept(File dir, String name) {
+                    if (name.endsWith(".class"))  return true;
+                    if (name.contains("."))  return false;
+                    // return true if it might be a package name:
+                    return Character.isJavaIdentifierStart(name.charAt(0));
+                }})) {
+            if (f2.getName().endsWith(".class"))
+                indifyFile(f2, dest);
+            else if (f2.isDirectory())
+                indifyTree(f2, dest);
+        }
+    }
+
+    public ClassLoader makeClassLoader() {
+        return new Loader();
+    }
+    private class Loader extends ClassLoader {
+        Loader() {
+            this(Indify.class.getClassLoader());
+        }
+        Loader(ClassLoader parent) {
+            super(parent);
+        }
+        public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+            File f = findClassInPath(name);
+            if (f != null) {
+                try {
+                    Class<?> c = transformAndLoadClass(f);
+                    if (c != null) {
+                        if (resolve)  resolveClass(c);
+                        return c;
+                    }
+                } catch (Exception ex) {
+                    if (ex instanceof IllegalArgumentException)
+                        // pass error from reportPatternMethods
+                        throw (IllegalArgumentException) ex;
+                }
+            }
+            return super.loadClass(name, resolve);
+        }
+        private File findClassInPath(String name) {
+            for (String s : classpath) {
+                File f = classPathFile(new File(s), name);
+                //System.out.println("Checking for "+f);
+                if (f.exists() && f.canRead()) {
+                    return f;
+                }
+            }
+            return null;
+        }
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            try {
+                File f = findClassInPath(name);
+                if (f != null) {
+                    Class<?> c = transformAndLoadClass(f);
+                    if (c != null)  return c;
+                }
+            } catch (IOException ex) {
+                throw new ClassNotFoundException("IO error", ex);
+            }
+            throw new ClassNotFoundException();
+        }
+        private Class<?> transformAndLoadClass(File f) throws ClassNotFoundException, IOException {
+            if (verbose)  System.err.println("Loading class from "+f);
+            ClassFile cf = new ClassFile(f);
+            Logic logic = new Logic(cf);
+            boolean changed = logic.transform();
+            if (verbose && !changed)  System.err.println("(no change)");
+            logic.reportPatternMethods(!verbose, keepgoing);
+            byte[] bytes = cf.toByteArray();
+            return defineClass(null, bytes, 0, bytes.length);
+        }
+    }
+
+    private class Logic {
+        // Indify logic, per se.
+        ClassFile cf;
+        final char[] poolMarks;
+        final Map<Method,Constant> constants = new HashMap<>();
+        final Map<Method,String> indySignatures = new HashMap<>();
+        Logic(ClassFile cf) {
+            this.cf = cf;
+            poolMarks = new char[cf.pool.size()];
+        }
+        boolean transform() {
+            if (!initializeMarks())  return false;
+            if (!findPatternMethods())  return false;
+            Pool pool = cf.pool;
+            //for (Constant c : cp)  System.out.println("  # "+c);
+            for (Method m : cf.methods) {
+                if (constants.containsKey(m))  continue;  // don't bother
+                // Transform references.
+                int blab = 0;
+                for (Instruction i = m.instructions(); i != null; i = i.next()) {
+                    if (i.bc != opc_invokestatic)  continue;
+                    int methi = i.u2At(1);
+                    if (poolMarks[methi] == 0)  continue;
+                    Short[] ref = pool.getMemberRef((short)methi);
+                    Method conm = findMember(cf.methods, ref[1], ref[2]);
+                    if (conm == null)  continue;
+                    Constant con = constants.get(conm);
+                    if (con == null)  continue;
+                    if (blab++ == 0 && !quiet)
+                        System.err.println("patching "+cf.nameString()+"."+m);
+                    //if (blab == 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println("  |"+j); }
+                    if (con.tag == CONSTANT_InvokeDynamic ||
+                        con.tag == CONSTANT_InvokeDynamic_17) {
+                        // need to patch the following instruction too,
+                        // but there are usually intervening argument pushes too
+                        Instruction i2 = findPop(i);
+                        Short[] ref2 = null;
+                        short ref2i = 0;
+                        if (i2 != null && i2.bc == opc_invokevirtual &&
+                                poolMarks[(char)(ref2i = (short) i2.u2At(1))] == 'D')
+                            ref2 = pool.getMemberRef(ref2i);
+                        if (ref2 == null || !"invokeExact".equals(pool.getString(ref2[1]))) {
+                            System.err.println(m+": failed to create invokedynamic at "+i.pc);
+                            continue;
+                        }
+                        String invType = pool.getString(ref2[2]);
+                        String bsmType = indySignatures.get(conm);
+                        if (!invType.equals(bsmType)) {
+                            System.err.println(m+": warning: "+conm+" call type and local invoke type differ: "
+                                    +bsmType+", "+invType);
+                        }
+                        assert(i.len == 3 || i2.len == 3);
+                        if (!quiet)  System.err.println(i+" "+conm+";...; "+i2+" => invokedynamic "+con);
+                        int start = i.pc + 3, end = i2.pc;
+                        System.arraycopy(i.codeBase, start, i.codeBase, i.pc, end-start);
+                        i.forceNext(0);  // force revisit of new instruction
+                        i2.u1AtPut(-3, opc_invokedynamic);
+                        i2.u2AtPut(-2, con.index);
+                        i2.u2AtPut(0, (short)0);
+                        i2.u1AtPut(2, opc_nop);
+                        //System.out.println(new Instruction(i.codeBase, i2.pc-3));
+                    } else {
+                        if (!quiet)  System.err.println(i+" "+conm+" => ldc "+con);
+                        assert(i.len == 3);
+                        i.u1AtPut(0, opc_ldc_w);
+                        i.u2AtPut(1, con.index);
+                    }
+                }
+                //if (blab >= 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println("    |"+j); }
+            }
+            cf.methods.removeAll(constants.keySet());
+            return true;
+        }
+
+        // Scan forward from the instruction to find where the stack p
+        // below the current sp at the instruction.
+        Instruction findPop(Instruction i) {
+            //System.out.println("findPop from "+i);
+            Pool pool = cf.pool;
+            JVMState jvm = new JVMState();
+        decode:
+            for (i = i.clone().next(); i != null; i = i.next()) {
+                String pops = INSTRUCTION_POPS[i.bc];
+                //System.out.println("  "+i+" "+jvm.stack+" : "+pops.replace("$", " => "));
+                if (pops == null)  break;
+                if (jvm.stackMotion(i.bc))  continue decode;
+                if (pops.indexOf('Q') >= 0) {
+                    Short[] ref = pool.getMemberRef((short) i.u2At(1));
+                    String type = simplifyType(pool.getString(CONSTANT_Utf8, ref[2]));
+                    switch (i.bc) {
+                    case opc_getstatic:
+                    case opc_getfield:
+                    case opc_putstatic:
+                    case opc_putfield:
+                        pops = pops.replace("Q", type);
+                        break;
+                    default:
+                        if (!type.startsWith("("))
+                            throw new InternalError(i.toString());
+                        pops = pops.replace("Q$Q", type.substring(1).replace(")","$"));
+                        break;
+                    }
+                    //System.out.println("special type: "+type+" => "+pops);
+                }
+                int npops = pops.indexOf('$');
+                if (npops < 0)  throw new InternalError();
+                if (npops > jvm.sp())  return i;
+                List<Object> args = jvm.args(npops);
+                int k = 0;
+                for (Object x : args) {
+                    char have = (Character) x;
+                    char want = pops.charAt(k++);
+                    if (have == 'X' || want == 'X')  continue;
+                    if (have != want)  break decode;
+                }
+                if (pops.charAt(k++) != '$')  break decode;
+                args.clear();
+                while (k < pops.length())
+                    args.add(pops.charAt(k++));
+            }
+            System.err.println("*** bailout on jvm: "+jvm.stack+" "+i);
+            return null;
+        }
+
+        boolean findPatternMethods() {
+            boolean found = false;
+            for (char mark : "THI".toCharArray()) {
+                for (Method m : cf.methods) {
+                    if (!Modifier.isPrivate(m.access))  continue;
+                    if (!Modifier.isStatic(m.access))  continue;
+                    if (nameAndTypeMark(m.name, m.type) == mark) {
+                        Constant con = scanPattern(m, mark);
+                        if (con == null)  continue;
+                        constants.put(m, con);
+                        found = true;
+                    }
+                }
+            }
+            return found;
+        }
+
+        void reportPatternMethods(boolean quietly, boolean allowMatchFailure) {
+            if (!quietly && !constants.keySet().isEmpty())
+                System.err.println("pattern methods removed: "+constants.keySet());
+            for (Method m : cf.methods) {
+                if (nameMark(cf.pool.getString(m.name)) != 0 &&
+                    constants.get(m) == null) {
+                    String failure = "method has special name but fails to match pattern: "+m;
+                    if (!allowMatchFailure)
+                        throw new IllegalArgumentException(failure);
+                    else if (!quietly)
+                        System.err.println("warning: "+failure);
+                }
+            }
+            if (verifySpecifierCount >= 0) {
+                List<Object[]> specs = bootstrapMethodSpecifiers(false);
+                int specsLen = (specs == null ? 0 : specs.size());
+                if (specsLen != verifySpecifierCount) {
+                    throw new IllegalArgumentException("BootstrapMethods length is "+specsLen+" but should be "+verifySpecifierCount);
+                }
+            }
+            if (!quiet)  System.err.flush();
+        }
+
+        // mark constant pool entries according to participation in patterns
+        boolean initializeMarks() {
+            boolean changed = false;
+            for (;;) {
+                boolean changed1 = false;
+                int cpindex = -1;
+                for (Constant e : cf.pool) {
+                    ++cpindex;
+                    if (e == null)  continue;
+                    char mark = poolMarks[cpindex];
+                    if (mark != 0)  continue;
+                    switch (e.tag) {
+                    case CONSTANT_Utf8:
+                        mark = nameMark(e.itemString()); break;
+                    case CONSTANT_NameAndType:
+                        mark = nameAndTypeMark(e.itemIndexes()); break;
+                    case CONSTANT_Class: {
+                        int n1 = e.itemIndex();
+                        char nmark = poolMarks[(char)n1];
+                        if ("DJ".indexOf(nmark) >= 0)
+                            mark = nmark;
+                        break;
+                    }
+                    case CONSTANT_Field:
+                    case CONSTANT_Method: {
+                        Short[] n12 = e.itemIndexes();
+                        short cl = n12[0];
+                        short nt = n12[1];
+                        char cmark = poolMarks[(char)cl];
+                        if (cmark != 0) {
+                            mark = cmark;  // it is a java.dyn.* or java.lang.* method
+                            break;
+                        }
+                        String cls = cf.pool.getString(CONSTANT_Class, cl);
+                        if (cls.equals(cf.nameString())) {
+                            switch (poolMarks[(char)nt]) {
+                            // it is a private MH/MT/INDY method
+                            case 'T': case 'H': case 'I':
+                                mark = poolMarks[(char)nt];
+                                break;
+                            }
+                        }
+                        break;
+                    }
+                    default:  break;
+                    }
+                    if (mark != 0) {
+                        poolMarks[cpindex] = mark;
+                        changed1 = true;
+                    }
+                }
+                if (!changed1)
+                    break;
+                changed = true;
+            }
+            return changed;
+        }
+        char nameMark(String s) {
+            if (s.startsWith("MT_"))                return 'T';
+            else if (s.startsWith("MH_"))           return 'H';
+            else if (s.startsWith("INDY_"))         return 'I';
+            else if (transitionalJSR292 &&
+                     s.startsWith("java/dyn/"))     return 'D';
+            else if (s.startsWith("java/lang/invoke/"))  return 'D';
+            else if (s.startsWith("java/lang/"))    return 'J';
+            return 0;
+        }
+        char nameAndTypeMark(Short[] n12) {
+            return nameAndTypeMark(n12[0], n12[1]);
+        }
+        char nameAndTypeMark(short n1, short n2) {
+            char mark = poolMarks[(char)n1];
+            if (mark == 0)  return 0;
+            String descr = cf.pool.getString(CONSTANT_Utf8, n2);
+            String requiredType;
+            switch (poolMarks[(char)n1]) {
+            case 'H': requiredType = "()Ljava/lang/invoke/MethodHandle;";  break;
+            case 'T': requiredType = "()Ljava/lang/invoke/MethodType;";    break;
+            case 'I': requiredType = "()Ljava/lang/invoke/MethodHandle;";  break;
+            default:  return 0;
+            }
+            if (matchType(descr, requiredType))  return mark;
+            return 0;
+        }
+
+        boolean matchType(String descr, String requiredType) {
+            if (descr.equals(requiredType))  return true;
+            if (transitionalJSR292) {
+                String oldType = requiredType.replace("Ljava/lang/invoke/", "Ljava/dyn/");
+                if (descr.equals(oldType))  return true;
+            }
+            return false;
+        }
+
+        private class JVMState {
+            final List<Object> stack = new ArrayList<>();
+            int sp() { return stack.size(); }
+            void push(Object x) { stack.add(x); }
+            void push2(Object x) { stack.add(EMPTY_SLOT); stack.add(x); }
+            void pushAt(int pos, Object x) { stack.add(stack.size()+pos, x); }
+            Object pop() { return stack.remove(sp()-1); }
+            Object top() { return stack.get(sp()-1); }
+            List<Object> args(boolean hasRecv, String type) {
+                return args(argsize(type) + (hasRecv ? 1 : 0));
+            }
+            List<Object> args(int argsize) {
+                return stack.subList(sp()-argsize, sp());
+            }
+            boolean stackMotion(int bc) {
+                switch (bc) {
+                case opc_pop:    pop();             break;
+                case opc_pop2:   pop(); pop();      break;
+                case opc_swap:   pushAt(-1, pop()); break;
+                case opc_dup:    push(top());       break;
+                case opc_dup_x1: pushAt(-2, top()); break;
+                case opc_dup_x2: pushAt(-3, top()); break;
+                // ? also: dup2{,_x1,_x2}
+                default:  return false;
+                }
+                return true;
+            }
+        }
+        private final String EMPTY_SLOT = "_";
+        private void removeEmptyJVMSlots(List<Object> args) {
+            for (;;) {
+                int i = args.indexOf(EMPTY_SLOT);
+                if (i >= 0 && i+1 < args.size()
+                    && (isConstant(args.get(i+1), CONSTANT_Long) ||
+                        isConstant(args.get(i+1), CONSTANT_Double)))
+                    args.remove(i);
+                else  break;
+            }
+        }
+
+        private Constant scanPattern(Method m, char patternMark) {
+            if (verbose)  System.err.println("scan "+m+" for pattern="+patternMark);
+            int wantTag;
+            switch (patternMark) {
+            case 'T': wantTag = CONSTANT_MethodType; break;
+            case 'H': wantTag = CONSTANT_MethodHandle; break;
+            case 'I': wantTag = CONSTANT_InvokeDynamic; break;
+            default: throw new InternalError();
+            }
+            Instruction i = m.instructions();
+            JVMState jvm = new JVMState();
+            Pool pool = cf.pool;
+            int branchCount = 0;
+            Object arg;
+            List<Object> args;
+            List<Object> bsmArgs = null;  // args to invokeGeneric
+        decode:
+            for (; i != null; i = i.next()) {
+                //System.out.println(jvm.stack+" "+i);
+                int bc = i.bc;
+                switch (bc) {
+                case opc_ldc:           jvm.push(pool.get(i.u1At(1)));   break;
+                case opc_ldc_w:         jvm.push(pool.get(i.u2At(1)));   break;
+                case opc_ldc2_w:        jvm.push2(pool.get(i.u2At(1)));  break;
+                case opc_aconst_null:   jvm.push(null);                  break;
+                case opc_bipush:        jvm.push((int)(byte) i.u1At(1)); break;
+                case opc_sipush:        jvm.push((int)(short)i.u2At(1)); break;
+
+                // these support creation of a restarg array
+                case opc_anewarray:
+                    arg = jvm.pop();
+                    if (!(arg instanceof Integer))  break decode;
+                    arg = Arrays.asList(new Object[(Integer)arg]);
+                    jvm.push(arg);
+                    break;
+                case opc_dup:
+                    jvm.push(jvm.top()); break;
+                case opc_aastore:
+                    args = jvm.args(3);  // array, index, value
+                    if (args.get(0) instanceof List &&
+                        args.get(1) instanceof Integer) {
+                        ((List<Object>)args.get(0)).set( (Integer)args.get(1), args.get(2) );
+                    }
+                    args.clear();
+                    break;
+
+                case opc_new:
+                {
+                    String type = pool.getString(CONSTANT_Class, (short)i.u2At(1));
+                    //System.out.println("new "+type);
+                    switch (type) {
+                    case "java/lang/StringBuilder":
+                        jvm.push("StringBuilder");
+                        continue decode;  // go to next instruction
+                    }
+                    break decode;  // bail out
+                }
+
+                case opc_getstatic:
+                {
+                    // int.class compiles to getstatic Integer.TYPE
+                    int fieldi = i.u2At(1);
+                    char mark = poolMarks[fieldi];
+                    //System.err.println("getstatic "+fieldi+Arrays.asList(pool.getStrings(pool.getMemberRef((short)fieldi)))+mark);
+                    if (mark == 'J') {
+                        Short[] ref = pool.getMemberRef((short) fieldi);
+                        String name = pool.getString(CONSTANT_Utf8, ref[1]);
+                        if ("TYPE".equals(name)) {
+                            String wrapperName = pool.getString(CONSTANT_Class, ref[0]).replace('/', '.');
+                            // a primitive type descriptor
+                            Class<?> primClass;
+                            try {
+                                primClass = (Class<?>) Class.forName(wrapperName).getField(name).get(null);
+                            } catch (Exception ex) {
+                                throw new InternalError("cannot load "+wrapperName+"."+name);
+                            }
+                            jvm.push(primClass);
+                            break;
+                        }
+                    }
+                    // unknown field; keep going...
+                    jvm.push(UNKNOWN_CON);
+                    break;
+                }
+                case opc_putstatic:
+                {
+                    if (patternMark != 'I')  break decode;
+                    jvm.pop();
+                    // unknown field; keep going...
+                    break;
+                }
+
+                case opc_invokestatic:
+                case opc_invokevirtual:
+                case opc_invokespecial:
+                {
+                    boolean hasRecv = (bc != opc_invokestatic);
+                    int methi = i.u2At(1);
+                    char mark = poolMarks[methi];
+                    Short[] ref = pool.getMemberRef((short)methi);
+                    String type = pool.getString(CONSTANT_Utf8, ref[2]);
+                    //System.out.println("invoke "+pool.getString(CONSTANT_Utf8, ref[1])+" "+Arrays.asList(ref)+" : "+type);
+                    args = jvm.args(hasRecv, type);
+                    String intrinsic = null;
+                    Constant con;
+                    if (mark == 'D' || mark == 'J') {
+                        intrinsic = pool.getString(CONSTANT_Utf8, ref[1]);
+                        if (mark == 'J') {
+                            String cls = pool.getString(CONSTANT_Class, ref[0]);
+                            cls = cls.substring(1+cls.lastIndexOf('/'));
+                            intrinsic = cls+"."+intrinsic;
+                        }
+                        //System.out.println("recognized intrinsic "+intrinsic);
+                        byte refKind = -1;
+                        switch (intrinsic) {
+                        case "findGetter":          refKind = REF_getField;         break;
+                        case "findStaticGetter":    refKind = REF_getStatic;        break;
+                        case "findSetter":          refKind = REF_putField;         break;
+                        case "findStaticSetter":    refKind = REF_putStatic;        break;
+                        case "findVirtual":         refKind = REF_invokeVirtual;    break;
+                        case "findStatic":          refKind = REF_invokeStatic;     break;
+                        case "findSpecial":         refKind = REF_invokeSpecial;    break;
+                        case "findConstructor":     refKind = REF_newInvokeSpecial; break;
+                        }
+                        if (refKind >= 0 && (con = parseMemberLookup(refKind, args)) != null) {
+                            args.clear(); args.add(con);
+                            continue;
+                        }
+                    }
+                    Method ownMethod = null;
+                    if (mark == 'T' || mark == 'H' || mark == 'I') {
+                        ownMethod = findMember(cf.methods, ref[1], ref[2]);
+                    }
+                    //if (intrinsic != null)  System.out.println("intrinsic = "+intrinsic);
+                    switch (intrinsic == null ? "" : intrinsic) {
+                    case "fromMethodDescriptorString":
+                        con = makeMethodTypeCon(args.get(0));
+                        args.clear(); args.add(con);
+                        continue;
+                    case "methodType": {
+                        flattenVarargs(args);  // there are several overloadings, some with varargs
+                        StringBuilder buf = new StringBuilder();
+                        String rtype = null;
+                        for (Object typeArg : args) {
+                            if (typeArg instanceof Class) {
+                                Class<?> argClass = (Class<?>) typeArg;
+                                if (argClass.isPrimitive()) {
+                                    char tchar;
+                                    switch (argClass.getName()) {
+                                    case "void":    tchar = 'V'; break;
+                                    case "boolean": tchar = 'Z'; break;
+                                    case "byte":    tchar = 'B'; break;
+                                    case "char":    tchar = 'C'; break;
+                                    case "short":   tchar = 'S'; break;
+                                    case "int":     tchar = 'I'; break;
+                                    case "long":    tchar = 'J'; break;
+                                    case "float":   tchar = 'F'; break;
+                                    case "double":  tchar = 'D'; break;
+                                    default:  throw new InternalError(argClass.toString());
+                                    }
+                                    buf.append(tchar);
+                                } else {
+                                    // should not happen, but...
+                                    buf.append('L').append(argClass.getName().replace('.','/')).append(';');
+                                }
+                            } else if (typeArg instanceof Constant) {
+                                Constant argCon = (Constant) typeArg;
+                                if (argCon.tag == CONSTANT_Class) {
+                                    String cn = pool.get(argCon.itemIndex()).itemString();
+                                    if (cn.endsWith(";"))
+                                        buf.append(cn);
+                                    else
+                                        buf.append('L').append(cn).append(';');
+                                } else {
+                                    break decode;
+                                }
+                            } else {
+                                break decode;
+                            }
+                            if (rtype == null) {
+                                // first arg is treated differently
+                                rtype = buf.toString();
+                                buf.setLength(0);
+                                buf.append('(');
+                            }
+                        }
+                        buf.append(')').append(rtype);
+                        con = con = makeMethodTypeCon(buf.toString());
+                        args.clear(); args.add(con);
+                        continue;
+                    }
+                    case "lookup":
+                    case "dynamicInvoker":
+                        args.clear(); args.add(intrinsic);
+                        continue;
+                    case "lookupClass":
+                        if (args.equals(Arrays.asList("lookup"))) {
+                            // fold lookup().lookupClass() to the enclosing class
+                            args.clear(); args.add(pool.get(cf.thisc));
+                            continue;
+                        }
+                        break;
+                    case "invokeGeneric":
+                    case "invokeWithArguments":
+                        if (patternMark != 'I')  break decode;
+                        if ("invokeWithArguments".equals(intrinsic))
+                            flattenVarargs(args);
+                        bsmArgs = new ArrayList(args);
+                        args.clear(); args.add("invokeGeneric");
+                        continue;
+                    case "Integer.valueOf":
+                    case "Float.valueOf":
+                    case "Long.valueOf":
+                    case "Double.valueOf":
+                        removeEmptyJVMSlots(args);
+                        if (args.size() == 1) {
+                            arg = args.remove(0);
+                            assert(3456 == (CONSTANT_Integer*1000 + CONSTANT_Float*100 + CONSTANT_Long*10 + CONSTANT_Double));
+                            if (isConstant(arg, CONSTANT_Integer + "IFLD".indexOf(intrinsic.charAt(0)))
+                                || arg instanceof Number) {
+                                args.add(arg); continue;
+                            }
+                        }
+                        break decode;
+                    case "StringBuilder.append":
+                        // allow calls like ("value = "+x)
+                        removeEmptyJVMSlots(args);
+                        args.subList(1, args.size()).clear();
+                        continue;
+                    case "StringBuilder.toString":
+                        args.clear();
+                        args.add(intrinsic);
+                        continue;
+                    }
+                    if (!hasRecv && ownMethod != null && patternMark != 0) {
+                        con = constants.get(ownMethod);
+                        if (con == null)  break decode;
+                        args.clear(); args.add(con);
+                        continue;
+                    } else if (type.endsWith(")V")) {
+                        // allow calls like println("reached the pattern method")
+                        args.clear();
+                        continue;
+                    }
+                    break decode;  // bail out for most calls
+                }
+                case opc_areturn:
+                {
+                    ++branchCount;
+                    if (bsmArgs != null) {
+                        // parse bsmArgs as (MH, lookup, String, MT, [extra])
+                        Constant indyCon = makeInvokeDynamicCon(bsmArgs);
+                        if (indyCon != null) {
+                            Constant typeCon = (Constant) bsmArgs.get(3);
+                            indySignatures.put(m, pool.getString(typeCon.itemIndex()));
+                            return indyCon;
+                        }
+                        System.err.println(m+": inscrutable bsm arguments: "+bsmArgs);
+                        break decode;  // bail out
+                    }
+                    arg = jvm.pop();
+                    if (branchCount == 2 && UNKNOWN_CON.equals(arg))
+                        break;  // merge to next path
+                    if (isConstant(arg, wantTag))
+                        return (Constant) arg;
+                    break decode;  // bail out
+                }
+                default:
+                    if (jvm.stackMotion(i.bc))  break;
+                    if (bc >= opc_nconst_MIN && bc <= opc_nconst_MAX)
+                        { jvm.push(INSTRUCTION_CONSTANTS[bc - opc_nconst_MIN]); break; }
+                    if (patternMark == 'I') {
+                        // these support caching paths in INDY_x methods
+                        if (bc == opc_aload || bc >= opc_aload_0 && bc <= opc_aload_MAX)
+                            { jvm.push(UNKNOWN_CON); break; }
+                        if (bc == opc_astore || bc >= opc_astore_0 && bc <= opc_astore_MAX)
+                            { jvm.pop(); break; }
+                        switch (bc) {
+                        case opc_getfield:
+                        case opc_aaload:
+                            jvm.push(UNKNOWN_CON); break;
+                        case opc_ifnull:
+                        case opc_ifnonnull:
+                            // ignore branch target
+                            if (++branchCount != 1)  break decode;
+                            jvm.pop();
+                            break;
+                        case opc_checkcast:
+                            arg = jvm.top();
+                            if ("invokeWithArguments".equals(arg) ||
+                                "invokeGeneric".equals(arg))
+                                break;  // assume it is a helpful cast
+                            break decode;
+                        default:
+                            break decode;  // bail out
+                        }
+                        continue decode; // go to next instruction
+                    }
+                    break decode;  // bail out
+                } //end switch
+            }
+            System.err.println(m+": bailout on "+i+" jvm stack: "+jvm.stack);
+            return null;
+        }
+        private final String UNKNOWN_CON = "<unknown>";
+
+        private void flattenVarargs(List<Object> args) {
+            int size = args.size();
+            if (size > 0 && args.get(size-1) instanceof List)
+                args.addAll((List<Object>) args.remove(size-1));
+        }
+
+        private boolean isConstant(Object x, int tag) {
+            return x instanceof Constant && ((Constant)x).tag == tag;
+        }
+        private Constant makeMethodTypeCon(Object x) {
+            short utfIndex;
+            if (x instanceof String)
+                utfIndex = (short) cf.pool.addConstant(CONSTANT_Utf8, x).index;
+            else if (isConstant(x, CONSTANT_String))
+                utfIndex = ((Constant)x).itemIndex();
+            else  return null;
+            return cf.pool.addConstant(CONSTANT_MethodType, utfIndex);
+        }
+        private Constant parseMemberLookup(byte refKind, List<Object> args) {
+            // E.g.: lookup().findStatic(Foo.class, "name", MethodType)
+            if (args.size() != 4)  return null;
+            int argi = 0;
+            if (!"lookup".equals(args.get(argi++)))  return null;
+            short refindex, cindex, ntindex, nindex, tindex;
+            Object con;
+            if (!isConstant(con = args.get(argi++), CONSTANT_Class))  return null;
+            cindex = (short)((Constant)con).index;
+            if (!isConstant(con = args.get(argi++), CONSTANT_String))  return null;
+            nindex = ((Constant)con).itemIndex();
+            if (isConstant(con = args.get(argi++), CONSTANT_MethodType) ||
+                isConstant(con, CONSTANT_Class)) {
+                tindex = ((Constant)con).itemIndex();
+            } else return null;
+            ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
+                    new Short[]{ nindex, tindex }).index;
+            byte reftag = CONSTANT_Method;
+            if (refKind <= REF_putStatic)
+                reftag = CONSTANT_Field;
+            else if (refKind == REF_invokeInterface)
+                reftag = CONSTANT_InterfaceMethod;
+            Constant ref = cf.pool.addConstant(reftag, new Short[]{ cindex, ntindex });
+            return cf.pool.addConstant(CONSTANT_MethodHandle, new Object[]{ refKind, (short)ref.index });
+        }
+        private Constant makeInvokeDynamicCon(List<Object> args) {
+            // E.g.: MH_bsm.invokeGeneric(lookup(), "name", MethodType, "extraArg")
+            removeEmptyJVMSlots(args);
+            if (args.size() != 4 && args.size() != 5)  return null;
+            int argi = 0;
+            short nindex, tindex, ntindex, bsmindex;
+            Object con;
+            if (!isConstant(con = args.get(argi++), CONSTANT_MethodHandle))  return null;
+            bsmindex = (short) ((Constant)con).index;
+            if (!"lookup".equals(args.get(argi++)))  return null;
+            if (!isConstant(con = args.get(argi++), CONSTANT_String))  return null;
+            nindex = ((Constant)con).itemIndex();
+            if (!isConstant(con = args.get(argi++), CONSTANT_MethodType))  return null;
+            tindex = ((Constant)con).itemIndex();
+            ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
+                                                  new Short[]{ nindex, tindex }).index;
+            if (transitionalJSR292) {
+                if (argi != args.size()) {
+                    System.err.println("BSM specifier has extra arguments but transitionalJSR292=1");
+                    return null;
+                }
+                return cf.pool.addConstant(CONSTANT_InvokeDynamic_17,
+                        new Short[]{ bsmindex, ntindex });
+            }
+            List<Object> extraArgs = Collections.emptyList();
+            if (argi < args.size()) {
+                Object arg = args.get(argi);
+                if (arg instanceof List)
+                    extraArgs = (List<Object>) arg;
+                else
+                    extraArgs = Arrays.asList(arg);
+                removeEmptyJVMSlots(args);
+            }
+            List<Short> extraArgIndexes = new CountedList<>(Short.class);
+            for (Object x : extraArgs) {
+                if (x instanceof Number) {
+                    Object num = null; byte numTag = 0;
+                    if (x instanceof Integer) { num = x; numTag = CONSTANT_Integer; }
+                    if (x instanceof Float)   { num = Float.floatToRawIntBits((Float)x); numTag = CONSTANT_Float; }
+                    if (x instanceof Long)    { num = x; numTag = CONSTANT_Long; }
+                    if (x instanceof Double)  { num = Double.doubleToRawLongBits((Double)x); numTag = CONSTANT_Double; }
+                    if (num != null)  x = cf.pool.addConstant(numTag, x);
+                }
+                if (!(x instanceof Constant))  return null;
+                extraArgIndexes.add((short) ((Constant)x).index);
+            }
+            List<Object[]> specs = bootstrapMethodSpecifiers(true);
+            int specindex = -1;
+            Object[] spec = new Object[]{ bsmindex, extraArgIndexes };
+            for (Object[] spec1 : specs) {
+                if (Arrays.equals(spec1, spec)) {
+                    specindex = specs.indexOf(spec1);
+                    if (verbose)  System.err.println("reusing BSM specifier: "+spec1[0]+spec1[1]);
+                    break;
+                }
+            }
+            if (specindex == -1) {
+                specindex = (short) specs.size();
+                specs.add(spec);
+                if (verbose)  System.err.println("adding BSM specifier: "+spec[0]+spec[1]);
+            }
+            return cf.pool.addConstant(CONSTANT_InvokeDynamic,
+                        new Short[]{ (short)specindex, ntindex });
+        }
+
+        List<Object[]> bootstrapMethodSpecifiers(boolean createIfNotFound) {
+            Attr bsms = cf.findAttr("BootstrapMethods");
+            if (bsms == null) {
+                if (!createIfNotFound)  return null;
+                bsms = new Attr(cf, "BootstrapMethods", new byte[]{0,0});
+                assert(bsms == cf.findAttr("BootstrapMethods"));
+            }
+            if (bsms.item instanceof byte[]) {
+                // unflatten
+                List<Object[]> specs = new CountedList<>(Object[].class);
+                DataInputStream in = new DataInputStream(new ByteArrayInputStream((byte[]) bsms.item));
+                try {
+                    int len = (char) in.readShort();
+                    for (int i = 0; i < len; i++) {
+                        short bsm = in.readShort();
+                        int argc = (char) in.readShort();
+                        List<Short> argv = new CountedList<>(Short.class);
+                        for (int j = 0; j < argc; j++)
+                            argv.add(in.readShort());
+                        specs.add(new Object[]{ bsm, argv });
+                    }
+                } catch (IOException ex) { throw new InternalError(); }
+                bsms.item = specs;
+            }
+            return (List<Object[]>) bsms.item;
+        }
+    }
+
+    private DataInputStream openInput(File f) throws IOException {
+        return new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
+    }
+
+    private DataOutputStream openOutput(File f) throws IOException {
+        if (!overwrite && f.exists())
+            throw new IOException("file already exists: "+f);
+        ensureDirectory(f.getParentFile());
+        return new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
+    }
+
+    static byte[] readRawBytes(DataInputStream in, int size) throws IOException {
+        byte[] bytes = new byte[size];
+        int nr = in.read(bytes);
+        if (nr != size)
+            throw new InternalError("wrong size: "+nr);
+        return bytes;
+    }
+
+    private interface Chunk {
+        void readFrom(DataInputStream in) throws IOException;
+        void writeTo(DataOutputStream out) throws IOException;
+    }
+
+    private static class CountedList<T> extends ArrayList<T> implements Chunk {
+        final Class<? extends T> itemClass;
+        final int rowlen;
+        CountedList(Class<? extends T> itemClass, int rowlen) {
+            this.itemClass = itemClass;
+            this.rowlen = rowlen;
+        }
+        CountedList(Class<? extends T> itemClass) { this(itemClass, -1); }
+        public void readFrom(DataInputStream in) throws IOException {
+            int count = in.readUnsignedShort();
+            while (size() < count) {
+                if (rowlen < 0) {
+                    add(readInput(in, itemClass));
+                } else {
+                    Class<?> elemClass = itemClass.getComponentType();
+                    Object[] row = (Object[]) java.lang.reflect.Array.newInstance(elemClass, rowlen);
+                    for (int i = 0; i < rowlen; i++)
+                        row[i] = readInput(in, elemClass);
+                    add(itemClass.cast(row));
+                }
+            }
+        }
+        public void writeTo(DataOutputStream out) throws IOException {
+            out.writeShort((short)size());
+            for (T item : this) {
+                writeOutput(out, item);
+            }
+        }
+    }
+
+    private static <T> T readInput(DataInputStream in, Class<T> dataClass) throws IOException {
+        Object data;
+        if (dataClass == Integer.class) {
+            data = in.readInt();
+        } else if (dataClass == Short.class) {
+            data = in.readShort();
+        } else if (dataClass == Byte.class) {
+            data = in.readByte();
+        } else if (dataClass == String.class) {
+            data = in.readUTF();
+        } else if (Chunk.class.isAssignableFrom(dataClass)) {
+            T obj;
+            try { obj = dataClass.newInstance(); }
+                catch (Exception ex) { throw new RuntimeException(ex); }
+            ((Chunk)obj).readFrom(in);
+            data = obj;
+        } else {
+            throw new InternalError("bad input datum: "+dataClass);
+        }
+        return dataClass.cast(data);
+    }
+    private static <T> T readInput(byte[] bytes, Class<T> dataClass) {
+        try {
+            return readInput(new DataInputStream(new ByteArrayInputStream(bytes)), dataClass);
+        } catch (IOException ex) {
+            throw new InternalError();
+        }
+    }
+    private static void readInputs(DataInputStream in, Object... data) throws IOException {
+        for (Object x : data)  ((Chunk)x).readFrom(in);
+    }
+
+    private static void writeOutput(DataOutputStream out, Object data) throws IOException {
+        if (data == null) {
+            return;
+        } if (data instanceof Integer) {
+            out.writeInt((Integer)data);
+        } else if (data instanceof Long) {
+            out.writeLong((Long)data);
+        } else if (data instanceof Short) {
+            out.writeShort((Short)data);
+        } else if (data instanceof Byte) {
+            out.writeByte((Byte)data);
+        } else if (data instanceof String) {
+            out.writeUTF((String)data);
+        } else if (data instanceof byte[]) {
+            out.write((byte[])data);
+        } else if (data instanceof Object[]) {
+            for (Object x : (Object[]) data)
+                writeOutput(out, x);
+        } else if (data instanceof Chunk) {
+            Chunk x = (Chunk) data;
+            x.writeTo(out);
+        } else if (data instanceof List) {
+            for (Object x : (List<?>) data)
+                writeOutput(out, x);
+        } else {
+            throw new InternalError("bad output datum: "+data+" : "+data.getClass().getName());
+        }
+    }
+    private static void writeOutputs(DataOutputStream out, Object... data) throws IOException {
+        for (Object x : data)  writeOutput(out, x);
+    }
+
+    public static abstract class Outer {
+        public abstract List<? extends Inner> inners();
+        protected void linkInners() {
+            for (Inner i : inners()) {
+                i.linkOuter(this);
+                if (i instanceof Outer)
+                    ((Outer)i).linkInners();
+            }
+        }
+        public <T extends Outer> T outer(Class<T> c) {
+            for (Outer walk = this;; walk = ((Inner)walk).outer()) {
+                if (c.isInstance(walk))
+                    return c.cast(walk);
+                //if (!(walk instanceof Inner))  return null;
+            }
+        }
+
+        public abstract List<Attr> attrs();
+        public Attr findAttr(String name) {
+            return findAttr(outer(ClassFile.class).pool.stringIndex(name, false));
+        }
+        public Attr findAttr(int name) {
+            if (name == 0)  return null;
+            for (Attr a : attrs()) {
+                if (a.name == name)  return a;
+            }
+            return null;
+        }
+    }
+    public interface Inner { Outer outer(); void linkOuter(Outer o); }
+    public static abstract class InnerOuter extends Outer implements Inner {
+        public Outer outer;
+        public Outer outer() { return outer; }
+        public void linkOuter(Outer o) { assert(outer == null); outer = o; }
+    }
+    public static class Constant<T> implements Chunk {
+        public final byte tag;
+        public final T item;
+        public final int index;
+        public Constant(int index, byte tag, T item) {
+            this.index = index;
+            this.tag = tag;
+            this.item = item;
+        }
+        public Constant checkTag(byte tag) {
+            if (this.tag != tag)  throw new InternalError(this.toString());
+            return this;
+        }
+        public String itemString() { return (String)item; }
+        public Short itemIndex() { return (Short)item; }
+        public Short[] itemIndexes() { return (Short[])item; }
+        public void readFrom(DataInputStream in) throws IOException {
+            throw new InternalError("do not call");
+        }
+        public void writeTo(DataOutputStream out) throws IOException {
+            writeOutputs(out, tag, item);
+        }
+        public boolean equals(Object x) { return (x instanceof Constant && equals((Constant)x)); }
+        public boolean equals(Constant that) {
+            return (this.tag == that.tag && this.itemAsComparable().equals(that.itemAsComparable()));
+        }
+        public int hashCode() { return (tag * 31) + this.itemAsComparable().hashCode(); }
+        public Object itemAsComparable() {
+            switch (tag) {
+            case CONSTANT_Double:   return Double.longBitsToDouble((Long)item);
+            case CONSTANT_Float:    return Float.intBitsToFloat((Integer)item);
+            }
+            return (item instanceof Object[] ? Arrays.asList((Object[])item) : item);
+        }
+        public String toString() {
+            String itstr = String.valueOf(itemAsComparable());
+            return (index + ":" + tagName(tag) + (itstr.startsWith("[")?"":"=") + itstr);
+        }
+        private static String[] TAG_NAMES;
+        public static String tagName(byte tag) {  // used for error messages
+            if (TAG_NAMES == null)
+                TAG_NAMES = ("None Utf8 Unicode Integer Float Long Double Class String"
+                             +" Fieldref Methodref InterfaceMethodref NameAndType #13 #14"
+                             +" MethodHandle MethodType InvokeDynamic#17 InvokeDynamic").split(" ");
+            if ((tag & 0xFF) >= TAG_NAMES.length)  return "#"+(tag & 0xFF);
+            return TAG_NAMES[tag & 0xFF];
+        }
+    }
+
+    public static class Pool extends CountedList<Constant> implements Chunk {
+        private Map<String,Short> strings = new TreeMap<>();
+
+        public Pool() {
+            super(Constant.class);
+        }
+        public void readFrom(DataInputStream in) throws IOException {
+            int count = in.readUnsignedShort();
+            add(null);  // always ignore first item
+            while (size() < count) {
+                readConstant(in);
+            }
+        }
+        public <T> Constant<T> addConstant(byte tag, T item) {
+            Constant<T> con = new Constant<>(size(), tag, item);
+            int idx = indexOf(con);
+            if (idx >= 0)  return get(idx);
+            add(con);
+            if (tag == CONSTANT_Utf8)  strings.put((String)item, (short) con.index);
+            return con;
+        }
+        private void readConstant(DataInputStream in) throws IOException {
+            byte tag = in.readByte();
+            int index = size();
+            Object arg;
+            switch (tag) {
+            case CONSTANT_Utf8:
+                arg = in.readUTF();
+                strings.put((String) arg, (short) size());
+                break;
+            case CONSTANT_Integer:
+            case CONSTANT_Float:
+                arg = in.readInt(); break;
+            case CONSTANT_Long:
+            case CONSTANT_Double:
+                add(new Constant(index, tag, in.readLong()));
+                add(null);
+                return;
+            case CONSTANT_Class:
+            case CONSTANT_String:
+                arg = in.readShort(); break;
+            case CONSTANT_Field:
+            case CONSTANT_Method:
+            case CONSTANT_InterfaceMethod:
+            case CONSTANT_NameAndType:
+            case CONSTANT_InvokeDynamic_17:
+            case CONSTANT_InvokeDynamic:
+                // read an ordered pair
+                arg = new Short[] { in.readShort(), in.readShort() };
+                break;
+            case CONSTANT_MethodHandle:
+                // read an ordered pair; first part is a u1 (not u2)
+                arg = new Object[] { in.readByte(), in.readShort() };
+                break;
+            case CONSTANT_MethodType:
+                arg = in.readShort(); break;
+            default:
+                throw new InternalError("bad CP tag "+tag);
+            }
+            add(new Constant(index, tag, arg));
+        }
+
+        // Access:
+        public Constant get(int index) {
+            // extra 1-bits get into the shorts
+            return super.get((char) index);
+        }
+        String getString(byte tag, short index) {
+            get(index).checkTag(tag);
+            return getString(index);
+        }
+        String getString(short index) {
+            Object v = get(index).item;
+            if (v instanceof Short)
+                v = get((Short)v).checkTag(CONSTANT_Utf8).item;
+            return (String) v;
+        }
+        String[] getStrings(Short[] indexes) {
+            String[] res = new String[indexes.length];
+            for (int i = 0; i < indexes.length; i++)
+                res[i] = getString(indexes[i]);
+            return res;
+        }
+        int stringIndex(String name, boolean createIfNotFound) {
+            Short x = strings.get(name);
+            if (x != null)  return (char)(int) x;
+            if (!createIfNotFound)  return 0;
+            return addConstant(CONSTANT_Utf8, name).index;
+        }
+        Short[] getMemberRef(short index) {
+            Short[] cls_nnt = get(index).itemIndexes();
+            Short[] name_type = get(cls_nnt[1]).itemIndexes();
+            return new Short[]{ cls_nnt[0], name_type[0], name_type[1] };
+        }
+    }
+
+    public class ClassFile extends Outer implements Chunk {
+        ClassFile(File f) throws IOException {
+            DataInputStream in = openInput(f);
+            try {
+                readFrom(in);
+            } finally {
+                if (in != null)  in.close();
+            }
+        }
+
+        public int                magic, version;  // <min:maj>
+        public final Pool         pool       = new Pool();
+        public short              access, thisc, superc;
+        public final List<Short>  interfaces = new CountedList<>(Short.class);
+        public final List<Field>  fields     = new CountedList<>(Field.class);
+        public final List<Method> methods    = new CountedList<>(Method.class);
+        public final List<Attr>   attrs      = new CountedList<>(Attr.class);
+
+        public final void readFrom(DataInputStream in) throws IOException {
+            magic = in.readInt(); version = in.readInt();
+            if (magic != 0xCAFEBABE)  throw new IOException("bad magic number");
+            pool.readFrom(in);
+            Code_index = pool.stringIndex("Code", false);
+            access = in.readShort(); thisc = in.readShort(); superc = in.readShort();
+            readInputs(in, interfaces, fields, methods, attrs);
+            if (in.read() >= 0)  throw new IOException("junk after end of file");
+            linkInners();
+        }
+
+        void writeTo(File f) throws IOException {
+            DataOutputStream out = openOutput(f);
+            try {
+                writeTo(out);
+            } finally {
+                out.close();
+            }
+        }
+
+        public void writeTo(DataOutputStream out) throws IOException {
+            writeOutputs(out, magic, version, pool,
+                         access, thisc, superc, interfaces,
+                         fields, methods, attrs);
+        }
+
+        public byte[] toByteArray() {
+            try {
+                ByteArrayOutputStream buf = new ByteArrayOutputStream();
+                writeTo(new DataOutputStream(buf));
+                return buf.toByteArray();
+            } catch (IOException ex) {
+                throw new InternalError();
+            }
+        }
+
+        public List<Inner> inners() {
+            List<Inner> inns = new ArrayList<>();
+            inns.addAll(fields); inns.addAll(methods); inns.addAll(attrs);
+            return inns;
+        }
+        public List<Attr> attrs() { return attrs; }
+
+        // derived stuff:
+        public String nameString() { return pool.getString(CONSTANT_Class, thisc); }
+        int Code_index;
+    }
+
+    private static <T extends Member> T findMember(List<T> mems, int name, int type) {
+        if (name == 0 || type == 0)  return null;
+        for (T m : mems) {
+            if (m.name == name && m.type == type)  return m;
+        }
+        return null;
+    }
+
+    public static class Member extends InnerOuter implements Chunk {
+        public short access, name, type;
+        public final List<Attr> attrs = new CountedList<>(Attr.class);
+        public void readFrom(DataInputStream in) throws IOException {
+            access = in.readShort(); name = in.readShort(); type = in.readShort();
+            readInputs(in, attrs);
+        }
+        public void writeTo(DataOutputStream out) throws IOException {
+            writeOutputs(out, access, name, type, attrs);
+        }
+        public List<Attr> inners() { return attrs; }
+        public List<Attr> attrs() { return attrs; }
+        public ClassFile outer() { return (ClassFile) outer; }
+        public String nameString() { return outer().pool.getString(CONSTANT_Utf8, name); }
+        public String typeString() { return outer().pool.getString(CONSTANT_Utf8, type); }
+        public String toString() {
+            if (outer == null)  return super.toString();
+            return nameString() + (this instanceof Method ? "" : ":")
+                    + simplifyType(typeString());
+        }
+    }
+    public static class Field extends Member {
+    }
+    public static class Method extends Member {
+        public Code code() {
+            Attr a = findAttr("Code");
+            if (a == null)  return null;
+            return (Code) a.item;
+        }
+        public Instruction instructions() {
+            Code code = code();
+            if (code == null)  return null;
+            return code.instructions();
+        }
+    }
+
+    public static class Attr extends InnerOuter implements Chunk {
+        public short name;
+        public int size = -1;  // no pre-declared size
+        public Object item;
+
+        public Attr() {}
+        public Attr(Outer outer, String name, Object item) {
+            ClassFile cf = outer.outer(ClassFile.class);
+            linkOuter(outer);
+            this.name = (short) cf.pool.stringIndex(name, true);
+            this.item = item;
+            outer.attrs().add(this);
+        }
+        public void readFrom(DataInputStream in) throws IOException {
+            name = in.readShort();
+            size = in.readInt();
+            item = readRawBytes(in, size);
+        }
+        public void writeTo(DataOutputStream out) throws IOException {
+            out.writeShort(name);
+            // write the 4-byte size header and then the contents:
+            byte[] bytes;
+            int trueSize;
+            if (item instanceof byte[]) {
+                bytes = (byte[]) item;
+                out.writeInt(trueSize = bytes.length);
+                out.write(bytes);
+            } else {
+                trueSize = flatten(out);
+                //if (!(item instanceof Code))  System.err.println("wrote complex attr name="+(int)(char)name+" size="+trueSize+" data="+Arrays.toString(flatten()));
+            }
+            if (trueSize != size && size >= 0)
+                System.err.println("warning: attribute size changed "+size+" to "+trueSize);
+        }
+        public void linkOuter(Outer o) {
+            super.linkOuter(o);
+            if (item instanceof byte[] &&
+                outer instanceof Method &&
+                ((Method)outer).outer().Code_index == name) {
+                    item = readInput((byte[])item, Code.class);
+            }
+        }
+        public List<Inner> inners() {
+            if (item instanceof Inner)
+                return Collections.nCopies(1, (Inner)item);
+            return Collections.emptyList();
+        }
+        public List<Attr> attrs() { return null; }  // Code overrides this
+        public byte[] flatten() {
+            ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
+            flatten(buf);
+            return buf.toByteArray();
+        }
+        public int flatten(DataOutputStream out) throws IOException {
+            ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
+            int trueSize = flatten(buf);
+            out.writeInt(trueSize);
+            buf.writeTo(out);
+            return trueSize;
+        }
+        private int flatten(ByteArrayOutputStream buf) {
+            try {
+                writeOutput(new DataOutputStream(buf), item);
+                return buf.size();
+            } catch (IOException ex) {
+                throw new InternalError();
+            }
+        }
+        public String nameString() {
+            ClassFile cf = outer(ClassFile.class);
+            if (cf == null)  return "#"+name;
+            return cf.pool.getString(name);
+        }
+        public String toString() {
+            return nameString()+(size < 0 ? "=" : "["+size+"]=")+item;
+        }
+    }
+
+    public static class Code extends InnerOuter implements Chunk {
+        public short stacks, locals;
+        public byte[] bytes;
+        public final List<Short[]> etable = new CountedList<>(Short[].class, 4);
+        public final List<Attr> attrs = new CountedList<>(Attr.class);
+        // etable[N] = (N)*{ startpc, endpc, handlerpc, catchtype }
+        public void readFrom(DataInputStream in) throws IOException {
+            stacks = in.readShort(); locals = in.readShort();
+            bytes = readRawBytes(in, in.readInt());
+            readInputs(in, etable, attrs);
+        }
+        public void writeTo(DataOutputStream out) throws IOException {
+            writeOutputs(out, stacks, locals, bytes.length, bytes, etable, attrs);
+        }
+        public List<Attr> inners() { return attrs; }
+        public List<Attr> attrs() { return attrs; }
+        public Instruction instructions() {
+            return new Instruction(bytes, 0);
+        }
+    }
+
+    // lots of constants
+    private static final byte
+        CONSTANT_Utf8              = 1,
+        CONSTANT_Integer           = 3,
+        CONSTANT_Float             = 4,
+        CONSTANT_Long              = 5,
+        CONSTANT_Double            = 6,
+        CONSTANT_Class             = 7,
+        CONSTANT_String            = 8,
+        CONSTANT_Field             = 9,
+        CONSTANT_Method            = 10,
+        CONSTANT_InterfaceMethod   = 11,
+        CONSTANT_NameAndType       = 12,
+        CONSTANT_MethodHandle      = 15,  // JSR 292
+        CONSTANT_MethodType        = 16,  // JSR 292
+        CONSTANT_InvokeDynamic_17  = 17,  // JSR 292, only occurs in old class files
+        CONSTANT_InvokeDynamic     = 18;  // JSR 292
+    private static final byte
+        REF_getField               = 1,
+        REF_getStatic              = 2,
+        REF_putField               = 3,
+        REF_putStatic              = 4,
+        REF_invokeVirtual          = 5,
+        REF_invokeStatic           = 6,
+        REF_invokeSpecial          = 7,
+        REF_newInvokeSpecial       = 8,
+        REF_invokeInterface        = 9;
+
+    private static final int
+        opc_nop                    = 0,
+        opc_aconst_null            = 1,
+        opc_nconst_MIN             = 2,  // iconst_m1
+        opc_nconst_MAX             = 15, // dconst_1
+        opc_bipush                 = 16,
+        opc_sipush                 = 17,
+        opc_ldc                    = 18,
+        opc_ldc_w                  = 19,
+        opc_ldc2_w                 = 20,
+        opc_aload                  = 25,
+        opc_aload_0                = 42,
+        opc_aload_MAX              = 45,
+        opc_aaload                 = 50,
+        opc_astore                 = 58,
+        opc_astore_0               = 75,
+        opc_astore_MAX             = 78,
+        opc_aastore                = 83,
+        opc_pop                    = 87,
+        opc_pop2                   = 88,
+        opc_dup                    = 89,
+        opc_dup_x1                 = 90,
+        opc_dup_x2                 = 91,
+        opc_dup2                   = 92,
+        opc_dup2_x1                = 93,
+        opc_dup2_x2                = 94,
+        opc_swap                   = 95,
+        opc_tableswitch            = 170,
+        opc_lookupswitch           = 171,
+        opc_areturn                = 176,
+        opc_getstatic              = 178,
+        opc_putstatic              = 179,
+        opc_getfield               = 180,
+        opc_putfield               = 181,
+        opc_invokevirtual          = 182,
+        opc_invokespecial          = 183,
+        opc_invokestatic           = 184,
+        opc_invokeinterface        = 185,
+        opc_invokedynamic          = 186,
+        opc_new                    = 187,
+        opc_anewarray              = 189,
+        opc_checkcast              = 192,
+        opc_ifnull                 = 198,
+        opc_ifnonnull              = 199,
+        opc_wide                   = 196;
+
+    private static final Object[] INSTRUCTION_CONSTANTS = {
+        -1, 0, 1, 2, 3, 4, 5, 0L, 1L, 0.0F, 1.0F, 2.0F, 0.0D, 1.0D
+    };
+
+    private static final String INSTRUCTION_FORMATS =
+        "nop$ aconst_null$L iconst_m1$I iconst_0$I iconst_1$I "+
+        "iconst_2$I iconst_3$I iconst_4$I iconst_5$I lconst_0$J_ "+
+        "lconst_1$J_ fconst_0$F fconst_1$F fconst_2$F dconst_0$D_ "+
+        "dconst_1$D_ bipush=bx$I sipush=bxx$I ldc=bk$X ldc_w=bkk$X "+
+        "ldc2_w=bkk$X_ iload=bl/wbll$I lload=bl/wbll$J_ fload=bl/wbll$F "+
+        "dload=bl/wbll$D_ aload=bl/wbll$L iload_0$I iload_1$I "+
+        "iload_2$I iload_3$I lload_0$J_ lload_1$J_ lload_2$J_ "+
+        "lload_3$J_ fload_0$F fload_1$F fload_2$F fload_3$F dload_0$D_ "+
+        "dload_1$D_ dload_2$D_ dload_3$D_ aload_0$L aload_1$L "+
+        "aload_2$L aload_3$L iaload$LI$I laload$LI$J_ faload$LI$F "+
+        "daload$LI$D_ aaload$LI$L baload$LI$I caload$LI$I saload$LI$I "+
+        "istore=bl/wbll$I$ lstore=bl/wbll$J_$ fstore=bl/wbll$F$ "+
+        "dstore=bl/wbll$D_$ astore=bl/wbll$L$ istore_0$I$ istore_1$I$ "+
+        "istore_2$I$ istore_3$I$ lstore_0$J_$ lstore_1$J_$ "+
+        "lstore_2$J_$ lstore_3$J_$ fstore_0$F$ fstore_1$F$ fstore_2$F$ "+
+        "fstore_3$F$ dstore_0$D_$ dstore_1$D_$ dstore_2$D_$ "+
+        "dstore_3$D_$ astore_0$L$ astore_1$L$ astore_2$L$ astore_3$L$ "+
+        "iastore$LII$ lastore$LIJ_$ fastore$LIF$ dastore$LID_$ "+
+        "aastore$LIL$ bastore$LII$ castore$LII$ sastore$LII$ pop$X$ "+
+        "pop2$XX$ dup$X$XX dup_x1$XX$XXX dup_x2$XXX$XXXX dup2$XX$XXXX "+
+        "dup2_x1$XXX$XXXXX dup2_x2$XXXX$XXXXXX swap$XX$XX "+
+        "iadd$II$I ladd$J_J_$J_ fadd$FF$F dadd$D_D_$D_ isub$II$I "+
+        "lsub$J_J_$J_ fsub$FF$F dsub$D_D_$D_ imul$II$I lmul$J_J_$J_ "+
+        "fmul$FF$F dmul$D_D_$D_ idiv$II$I ldiv$J_J_$J_ fdiv$FF$F "+
+        "ddiv$D_D_$D_ irem$II$I lrem$J_J_$J_ frem$FF$F drem$D_D_$D_ "+
+        "ineg$I$I lneg$J_$J_ fneg$F$F dneg$D_$D_ ishl$II$I lshl$J_I$J_ "+
+        "ishr$II$I lshr$J_I$J_ iushr$II$I lushr$J_I$J_ iand$II$I "+
+        "land$J_J_$J_ ior$II$I lor$J_J_$J_ ixor$II$I lxor$J_J_$J_ "+
+        "iinc=blx/wbllxx$ i2l$I$J_ i2f$I$F i2d$I$D_ l2i$J_$I l2f$J_$F "+
+        "l2d$J_$D_ f2i$F$I f2l$F$J_ f2d$F$D_ d2i$D_$I d2l$D_$J_ "+
+        "d2f$D_$F i2b$I$I i2c$I$I i2s$I$I lcmp fcmpl fcmpg dcmpl dcmpg "+
+        "ifeq=boo ifne=boo iflt=boo ifge=boo ifgt=boo ifle=boo "+
+        "if_icmpeq=boo if_icmpne=boo if_icmplt=boo if_icmpge=boo "+
+        "if_icmpgt=boo if_icmple=boo if_acmpeq=boo if_acmpne=boo "+
+        "goto=boo jsr=boo ret=bl/wbll tableswitch=* lookupswitch=* "+
+        "ireturn lreturn freturn dreturn areturn return "+
+        "getstatic=bkf$Q putstatic=bkf$Q$ getfield=bkf$L$Q "+
+        "putfield=bkf$LQ$ invokevirtual=bkm$LQ$Q "+
+        "invokespecial=bkm$LQ$Q invokestatic=bkm$Q$Q "+
+        "invokeinterface=bkixx$LQ$Q invokedynamic=bkd__$Q$Q new=bkc$L "+
+        "newarray=bx$I$L anewarray=bkc$I$L arraylength$L$I athrow "+
+        "checkcast=bkc$L$L instanceof=bkc$L$I monitorenter$L "+
+        "monitorexit$L wide=* multianewarray=bkcx ifnull=boo "+
+        "ifnonnull=boo goto_w=boooo jsr_w=boooo ";
+    private static final String[] INSTRUCTION_NAMES;
+    private static final String[] INSTRUCTION_POPS;
+    private static final int[] INSTRUCTION_INFO;
+    static {
+        String[] insns = INSTRUCTION_FORMATS.split(" ");
+        assert(insns[opc_lookupswitch].startsWith("lookupswitch"));
+        assert(insns[opc_tableswitch].startsWith("tableswitch"));
+        assert(insns[opc_wide].startsWith("wide"));
+        assert(insns[opc_invokedynamic].startsWith("invokedynamic"));
+        int[] info = new int[256];
+        String[] names = new String[256];
+        String[] pops = new String[256];
+        for (int i = 0; i < insns.length; i++) {
+            String insn = insns[i];
+            int dl = insn.indexOf('$');
+            if (dl > 0) {
+                String p = insn.substring(dl+1);
+                if (p.indexOf('$') < 0)  p = "$" + p;
+                pops[i] = p;
+                insn = insn.substring(0, dl);
+            }
+            int eq = insn.indexOf('=');
+            if (eq < 0) {
+                info[i] = 1;
+                names[i] = insn;
+                continue;
+            }
+            names[i] = insn.substring(0, eq);
+            String fmt = insn.substring(eq+1);
+            if (fmt.equals("*")) {
+                info[i] = 0;
+                continue;
+            }
+            int sl = fmt.indexOf('/');
+            if (sl < 0) {
+                info[i] = (char) fmt.length();
+            } else {
+                String wfmt = fmt.substring(sl+1);
+                fmt = fmt.substring(0, sl);
+                info[i] = (char)( fmt.length() + (wfmt.length() * 16) );
+            }
+        }
+        INSTRUCTION_INFO = info;
+        INSTRUCTION_NAMES = names;
+        INSTRUCTION_POPS = pops;
+    }
+
+    public static class Instruction implements Cloneable {
+        byte[] codeBase;
+        int pc;
+        int bc;
+        int info;
+        int wide;
+        int len;
+        Instruction(byte[] codeBase, int pc) {
+            this.codeBase = codeBase;
+            init(pc);
+        }
+        public Instruction clone() {
+            try {
+                return (Instruction) super.clone();
+            } catch (CloneNotSupportedException ex) {
+                throw new InternalError();
+            }
+        }
+        private Instruction init(int pc) {
+            this.pc = pc;
+            this.bc = codeBase[pc] & 0xFF;
+            this.info = INSTRUCTION_INFO[bc];
+            this.wide = 0;
+            this.len = (info & 0x0F);
+            if (len == 0)
+                computeLength();
+            return this;
+        }
+        Instruction next() {
+            if (len == 0 && bc != 0)  throw new InternalError();
+            int npc = pc + len;
+            if (npc == codeBase.length)
+                return null;
+            return init(npc);
+        }
+        void forceNext(int newLen) {
+            bc = opc_nop;
+            len = newLen;
+        }
+
+        public String toString() {
+            StringBuilder buf = new StringBuilder();
+            buf.append(pc).append(":").append(INSTRUCTION_NAMES[bc]);
+            switch (len) {
+            case 3: buf.append(" ").append(u2At(1)); break;
+            case 5: buf.append(" ").append(u2At(1)).append(" ").append(u2At(3)); break;
+            default:  for (int i = 1; i < len; i++)  buf.append(" ").append(u1At(1));
+            }
+            return buf.toString();
+        }
+
+        // these are the hard parts
+        private void computeLength() {
+            int cases;
+            switch (bc) {
+            case opc_wide:
+                bc = codeBase[pc + 1];
+                info = INSTRUCTION_INFO[bc];
+                len = ((info >> 4) & 0x0F);
+                if (len == 0)  throw new RuntimeException("misplaced wide bytecode: "+bc);
+                return;
+
+            case opc_tableswitch:
+                cases = (u4At(alignedIntOffset(2)) - u4At(alignedIntOffset(1)) + 1);
+                len = alignedIntOffset(3 + cases*1);
+                return;
+
+            case opc_lookupswitch:
+                cases = u4At(alignedIntOffset(1));
+                len = alignedIntOffset(2 + cases*2);
+                return;
+
+            default:
+                throw new RuntimeException("unknown bytecode: "+bc);
+            }
+        }
+        // switch code
+        // clget the Nth int (where 0 is the first after the opcode itself)
+        public int alignedIntOffset(int n) {
+            int pos = pc + 1;
+            pos += ((-pos) & 0x03);  // align it
+            pos += (n * 4);
+            return pos - pc;
+        }
+        public int u1At(int pos) {
+            return (codeBase[pc+pos] & 0xFF);
+        }
+        public int u2At(int pos) {
+            return (u1At(pos+0)<<8) + u1At(pos+1);
+        }
+        public int u4At(int pos) {
+            return (u2At(pos+0)<<16) + u2At(pos+2);
+        }
+        public void u1AtPut(int pos, int x) {
+            codeBase[pc+pos] = (byte)x;
+        }
+        public void u2AtPut(int pos, int x) {
+            codeBase[pc+pos+0] = (byte)(x >> 8);
+            codeBase[pc+pos+1] = (byte)(x >> 0);
+        }
+    }
+
+    static String simplifyType(String type) {
+        String simpleType = OBJ_SIGNATURE.matcher(type).replaceAll("L");
+        assert(simpleType.matches("^\\([A-Z]*\\)[A-Z]$"));
+        // change (DD)D to (D_D_)D_
+        simpleType = WIDE_SIGNATURE.matcher(simpleType).replaceAll("\\0_");
+        return simpleType;
+    }
+    static int argsize(String type) {
+        return simplifyType(type).length()-3;
+    }
+    private static final Pattern OBJ_SIGNATURE = Pattern.compile("\\[*L[^;]*;|\\[+[A-Z]");
+    private static final Pattern WIDE_SIGNATURE = Pattern.compile("[JD]");
+}