--- /dev/null	2009-01-20 02:47:41.000000000 -0800
+++ new/src/share/projects/meth/src/java/dyn/MethodHandles.java	2009-01-20 02:47:40.000000000 -0800
@@ -0,0 +1,940 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.dyn;
+
+import impl.java.dyn.Access;
+import impl.java.dyn.MemberName;
+import impl.java.dyn.MethodHandleImpl;
+import impl.java.dyn.util.MethodHandleInvoker;
+import impl.java.dyn.util.VerifyAccess;
+import impl.java.dyn.util.Wrappers;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import sun.reflect.Reflection;
+import static impl.java.dyn.MemberName.newIllegalArgumentException;
+import static impl.java.dyn.MemberName.newNoAccessException;
+
+/**
+ * Fundamental operations and utilities for MethodHandle.
+ * <p>
+ * <em>API Note:</em>  The matching of method types in this API cannot
+ * be completely checked by Java's generic type system for three reasons:
+ * <ol>
+ * <li>Method types range over all possible arities,
+ * from no arguments to an arbitrary number of arguments.
+ * Generics are not variadic, and so cannot represent this.</li>
+ * <li>Method types can specify arguments of primitive types,
+ * which Java generic types cannot range over.</li>
+ * <li>Method types can optionally specify varargs (ellipsis).</li>
+ * </ol>
+ * @author John Rose, JSR 292 EG
+ */
+public class MethodHandles {
+
+    private MethodHandles() { }  // do not instantiate
+
+    private static final Access IMPL_TOKEN = Access.getToken();
+    private static final MemberName.Factory IMPL_LOOKUP = MemberName.getFactory(IMPL_TOKEN);
+
+    //// Method handle creation from ordinary methods.
+
+    /**
+     * Produce a method handle for a static method.
+     * The type of the method handle will be that of the method.
+     * The method and all its argument types must be accessible to the caller.
+     * If the method's class has not yet been initialized, that is done
+     * immediately, before the method handle is returned.
+     * @param defc 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, or null if no such method exists
+     * @exception SecurityException <em>TBD</em>
+     * @exception NoAccessException if access checking fails
+     */
+    public static
+    MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        MemberName method = IMPL_LOOKUP.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, caller);
+        checkStatic(true, method, caller);
+        return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, caller);
+    }
+
+    private static void checkStatic(boolean wantStatic, MemberName m, Class<?> caller) {
+        if (wantStatic != m.isStatic()) {
+            String message = wantStatic ? "expected a static method" : "expected a non-static method";
+            throw newNoAccessException(message, m, caller);
+        }
+    }
+
+    /**
+     * Produce a method handle for a virtual method.
+     * The type of the method handle will be that of the method,
+     * with the receiver type ({@code defc}) 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
+     * 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.)
+     * @param defc 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, or null if no such method exists
+     * @exception SecurityException <em>TBD</em>
+     * @exception NoAccessException if access checking fails
+     */
+    public static
+    MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        MemberName method = IMPL_LOOKUP.resolveOrFail(new MemberName(defc, name, type), true, caller);
+        checkStatic(false, method, caller);
+        return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, caller);
+    }
+
+    /**
+     * Produce an early-bound method handle for a virtual method,
+     * or a handle for a constructor, as if called from an {@code invokespecial}
+     * instruction from {@code caller}.
+     * The type of the method handle will be that of the method or constructor,
+     * with a suitably restricted receiver type (such as {@code caller}) prepended.
+     * The method or constructor 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 actual
+     * caller of {@code findSpecial}, a security check TBD is performed.
+     * @param defc the class or interface from which the method is accessed
+     * @param name the name of the method, or "<init>" for a constructor
+     * @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, or null if no such method exists
+     * @exception SecurityException <em>TBD</em>
+     * @exception NoAccessException if access checking fails
+     */
+    public static
+    MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
+            Class<?> specialCaller) throws NoAccessException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        checkSpecialCaller(specialCaller, caller);
+        MemberName method = IMPL_LOOKUP.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
+        checkStatic(false, method, caller);
+        if (name.equals("<init>")) {
+            if (defc != specialCaller)
+                throw newNoAccessException("constructor must be local to caller", method, caller);
+        } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
+            throw newNoAccessException("method must be in a superclass of caller", method, caller);
+        }
+        return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
+    }
+
+    /**
+     * Produce 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 caller.
+     * The method and all its argument types must be accessible to the caller.
+     * The type of the method handle will be that of the method.
+     * The given receiver will be bound into the method handle.
+     * <p>
+     * Equivalent to the following expression:
+     * <code>
+     * {@link #insertArgument}({@link #findVirtual}(defc, name, type), receiver)
+     * </code>
+     * @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, or null if no such method exists
+     * @exception SecurityException <em>TBD</em>
+     * @exception NoAccessException if access checking fails
+     */
+    public static
+    MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
+        MemberName reference = new MemberName(rcvc, name, type);
+        MemberName method = IMPL_LOOKUP.resolveOrFail(reference, true, caller);
+        checkStatic(false, method, caller);
+        MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, caller);
+        MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
+        if (bmh == null)
+            throw newNoAccessException(method, caller);
+        return bmh;
+    }
+
+    /**
+     * Make a direct method handle to <i>m</i>, if the current caller 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 caller.
+     * If <i>m</i> is not public, do not share the resulting handle with untrusted callers.
+     * @param m the reflected method
+     * @return a method handle which can invoke the reflected method
+     * @exception NoAccessException if access checking fails
+     */
+    public static
+    MethodHandle unreflect(Method m) throws NoAccessException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        return unreflect(new MemberName(m), m.isAccessible(), true, caller);
+    }
+
+    /**
+     * Produce a method handle for a reflected method.
+     * It will bypass checks for overriding methods on the receiver,
+     * as if by the {@code invokespecial} instruction.
+     * The type of the method handle will be that of the method,
+     * with the receiver type prepended.
+     * If the method's {@code accessible} flag is not set,
+     * access checking is performed immediately on behalf of the caller,
+     * as if {@code invokespecial} instruction were being linked.
+     * @param m the reflected method
+     * @return a method handle which can invoke the reflected method
+     * @exception NoAccessException if access checking fails
+     */
+    public static
+    MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        checkSpecialCaller(specialCaller, caller);
+        MemberName mname = new MemberName(m);
+        checkStatic(false, mname, caller);
+        return unreflect(mname, m.isAccessible(), false, specialCaller);
+    }
+
+//    /**
+//     * Produce a method handle for a reflected constructor.
+//     * It will allow direct access to the constructor,
+//     * as if by the {@code invokespecial} instruction.
+//     * The type of the method handle will be that of the method,
+//     * with the receiver type prepended.
+//     * If the constructor's {@code accessible} flag is not set,
+//     * access checking is performed immediately on behalf of the caller,
+//     * as if {@code invokespecial} instruction were being linked.
+//     * @param ctor the reflected constructor
+//     * @param specialCaller the proposed calling class to perform the {@code invokespecial}
+//     * @return a method handle which can invoke the reflected constructor
+//     * @exception NoAccessException if access checking fails
+//     */
+//    public static
+//    MethodHandle unreflectSpecial(Constructor ctor, Class<?> specialCaller) throws NoAccessException {
+//        Class<?> caller = Reflection.getCallerClass(2);
+//        checkSpecialCaller(specialCaller, caller);
+//        MemberName m = new MemberName(ctor);
+//        checkStatic(false, m, caller);
+//        return unreflect(m, ctor.isAccessible(), false, specialCaller);
+//    }
+
+    private static
+    void checkSpecialCaller(Class<?> specialCaller, Class<?> caller) {
+        if (caller != null && !VerifyAccess.isSamePackageMember(specialCaller, caller))
+            throw newNoAccessException("no private access", new MemberName(specialCaller), caller);
+    }
+
+    // Helper for creating handles on reflected methods and constructors.
+    private static
+    MethodHandle unreflect(MemberName m, boolean isAccessible, boolean doDispatch, Class<?> caller) {
+        MethodType mtype = m.getInvocationType();
+        Class<?> defc = m.getDeclaringClass();
+        int mods = m.getModifiers();
+        if (m.isStatic()) {
+            if (!isAccessible &&
+                    VerifyAccess.isAccessible(defc, mods, false, caller) == null)
+                throw newNoAccessException(m, caller);
+        } else {
+            Class<?> constraint;
+            if (isAccessible) {
+                // abbreviated access check for "unlocked" method
+                constraint = doDispatch ? defc : caller;
+            } else {
+                constraint = VerifyAccess.isAccessible(defc, mods, doDispatch, caller);
+            }
+            if (constraint != defc && !constraint.isAssignableFrom(defc)) {
+                if (!defc.isAssignableFrom(constraint))
+                    throw newNoAccessException("receiver must be in caller class", m, caller);
+                mtype = mtype.changeParameterType(0, constraint);
+            }
+        }
+        return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, caller);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle giving read access to a reflected field.
+     * The type of the method handle will have a return type of the field's
+     * value type.  Its sole argument will be the field's containing class
+     * (but only if it is non-static).
+     * If the method's {@code accessible} flag is not set,
+     * access checking is performed immediately on behalf of the caller.
+     * @param f the reflected field
+     * @return a method handle which can load values from the reflected field
+     * @exception NoAccessException if access checking fails
+     */
+    public static
+    MethodHandle unreflectGetter(Field f) throws NoAccessException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), false, (Class)caller);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle giving write access to a reflected field.
+     * The type of the method handle will have a void return type.
+     * Its last argument will be the field's value type.
+     * Its other argument will be the field's containing class
+     * (but only if it is non-static).
+     * If the method's {@code accessible} flag is not set,
+     * access checking is performed immediately on behalf of the caller.
+     * @param f the reflected field
+     * @return a method handle which can store values into the reflected field
+     * @exception NoAccessException if access checking fails
+     */
+    public static
+    MethodHandle unreflectSetter(Field f) throws NoAccessException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), true, (Class)caller);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce 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  IllegalArgumentException if arrayClass is not an array type
+     */
+    public static
+    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, false, (Class)caller);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce 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 IllegalArgumentException if arrayClass is not an array type
+     */
+    public static
+    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
+        Class<?> caller = Reflection.getCallerClass(2);
+        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true, (Class)caller);
+    }
+
+
+    /// method handle invocation (reflective style)
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Call the {@code invoke} method of a given method handle.
+     * The given arguments must exactly match the parameter types of the method handle.
+     * <em>TBD: Fill in the details.</em>
+     * No conversions are performed except reference casting and unboxing of primitives.
+     * @param target method handle to invoke
+     * @param arguments arguments to pass to the target (with any primitives wrapped)
+     * @return the result of the method (with any primitive wrapped)
+     */
+    public static
+    Object invoke(MethodHandle target, Object... arguments) {
+        // TO DO: Remove this checking logic; must be part of the invoker anyway.
+        int length = arguments.length;
+        MethodType type = target.type();
+        if (type.parameterCount() != length)
+            throw new WrongMethodTypeException("wrong number of arguments");
+        for (int i = 0; i < length; i++) {
+            Object argument = arguments[i];
+            Class<?> ptype = type.parameterType(i);
+            if (ptype.isPrimitive()) {
+                argument.getClass();  // provoke NPE if null
+                ptype = Wrappers.asWrapperType(ptype);
+            } else if (ptype.isInterface()) {
+                ptype = Object.class;   // no check
+            }
+            if (ptype != Object.class) {
+                ptype.cast(argument);
+            }
+        }
+        // End of checking logic.
+        return MethodHandleInvoker.make(target.type()).invoke(target, arguments);
+    }
+
+    /**
+     * <em>WORK IN PROGRESS:</em>
+     * 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
+    Object checkValue(Class<?> T0, Class<?> T1, Object value)
+       throws ClassCastException
+    {
+        if (T0 == T1) {
+            // no conversion needed
+            return value;
+        }
+        boolean prim0 = T0.isPrimitive(), prim1 = T1.isPrimitive();
+        Class<?> TW;
+        if (!prim0) {
+            if (!prim1) {
+                return T1.cast(T0.cast(value));
+            }
+            // convert reference to primitive by unboxing
+            TW = Wrappers.asWrapperType(T0);
+            return T1.cast(TW.cast(value));
+        }
+        if (!prim1) {
+            // convert primitive to reference type by boxing
+            TW = Wrappers.asWrapperType(T1);
+            return TW.cast(T0.cast(value));
+        }
+        // convert primitive to primitive; this requires a real value change
+        if (value == null)
+            return Wrappers.zeroValue(T1);
+        // convert non-Number primitives to Integer:
+        if (value instanceof Character) {
+            char ch = (char) (Character) value;
+            value = Integer.valueOf(ch);
+            if (T1 == Integer.class)
+                return value;
+        } else if (value instanceof Boolean) {
+            boolean z = (boolean) (Boolean) value;
+            value = Integer.valueOf(z ? 1 : 0);
+            if (T1 == Integer.class)
+                return value;
+        }
+        Number numval = (Number) value;
+        switch (Wrappers.basicTypeChar(T1)) {
+        case 'Z': return (numval.intValue() != 0);
+        case 'B': return numval.byteValue();
+        case 'C': return (char) numval.intValue();
+        case 'S': return numval.shortValue();
+        case 'I': return numval.intValue();
+        case 'J': return numval.longValue();
+        case 'F': return numval.floatValue();
+        case 'D': return numval.doubleValue();
+        }
+        return null;
+    }
+
+    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)
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which adapts the type of the
+     * given method handle to a new type, by pairwise argument conversion,
+     * and/or varargs conversion.
+     * The original type and new type must have the same number of
+     * arguments, or else one or both them the must be varargs types.
+     * The resulting method handle is guaranteed to confess a type
+     * which is equal to the desired new type, with any varargs property erased.
+     * <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.
+     * <p>
+     * If an ordinary (non-varargs) parameter of the new type is
+     * to be boxed in a varargs parameter of the old type of type T1[],
+     * then T1 is the element type of the varargs array.
+     * Otherwise, if a varargs parameter of the new type of type T0[]
+     * is to be spread into one or more outgoing old type parameters,
+     * then T0 is the element type of the
+     * If the new type is varargs and the old type is not, the varargs
+     * argument will be checked and must be a non-null array of exactly
+     * the right length.  If there are no parameters in the old type
+     * corresponding to the new varargs parameter, the varargs argument
+     * is also allowed to be null.
+     * <p>
+     * Given those types T0, T1, one of the following conversions is applied
+     * if possible:
+     * <ul>
+     * <li>If T0 and T1 are references, then a cast to T2 is applied,
+     *     where T2 is Object if T1 is an interface, else T1.
+     *     (The types do not need to be related in any particular way.
+     *     The treatment of interfaces follows the usage of the bytecode verifier.)
+     * <li>If T0 and T1 are primitives, then a Java casting
+     *     conversion (JLS 5.5) is applied, if one exists.
+     * <li>If T0 and T1 are primitives and one is boolean,
+     *     the boolean is treated as a one-bit unsigned integer.
+     *     (This treatment follows the usage of the bytecode verifier.)
+     *     A conversion from another primitive type behaves as if
+     *     it first converts to byte, and then masks all but the low bit.
+     * <li>If T0 is a primitive and T1 a reference, a boxing
+     *     conversion is applied if one exists, possibly followed by
+     *     an reference conversion to a superclass.
+     *     T1 must be a wrapper class or a supertype of one.
+     *     If T1 is a wrapper class, T0 is converted if necessary
+     *     to T1's primitive type by one of the preceding conversions.
+     *     Otherwise, T0 is boxed, and its wrapper converted to T1.
+     * <li>If T0 is a reference and T1 a primitive, an unboxing
+     *     conversion is applied if one exists, possibly preceded by
+     *     a reference conversion to a wrapper class.
+     *     T0 must be a wrapper class or a supertype of one.
+     *     If T0 is a wrapper class, its primitive value is converted
+     *     if necessary to T1 by one of the preceding conversions.
+     *     Otherwise, T0 is converted directly to the wrapper type for T1,
+     *     which is then unboxed.
+     * <li>If T1 is void, any returned value is discarded
+     * <li>If T0 is void and T1 a reference, a null value is introduced.
+     * <li>If T0 is void and T1 a primitive, a zero value is introduced.
+     * </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
+     */
+    public static
+    MethodHandle convertArguments(MethodHandle target, MethodType newType) {
+        MethodType oldType = target.type();
+        if (oldType.equals(newType))
+            return target;
+        return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
+                                                 newType, target.type(), null);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which adapts the calling sequence of the
+     * given method handle to a new type, by reordering the arguments.
+     * Duplication and omission is allowed.
+     * The resulting method handle is guaranteed to confess a type
+     * which is equal to the desired new type.
+     * <p>
+     * The given permutation string controls the reordering.
+     * The characters of the string are treated as small integers.
+     * All the characters must be in the range zero (i.e., '\0') to
+     * the number of incoming arguments (the parameter count of the new type).
+     * The length of the string must be equal to the number of outgoing
+     * parameters (the parameter count of the original method handle's type).
+     * If the n-th character of the string denotes the integer k,
+     * then the n-th incoming argument becomes the k-th outgoing argument.
+     * <p>
+     * Pairwise conversions are applied as needed to arguments and return
+     * values, as with {@link #convertArguments}.
+     * @param target the method handle to invoke after arguments are reordered
+     * @param newType the expected type of the new method handle
+     * @param permutation a string which controls the reordering
+     * @return a method handle which delegates to {@code target} after performing
+     *           any necessary argument motion and conversions, and arranges for any
+     *           necessary return value conversions
+     */
+    public static
+    MethodHandle permuteArguments(MethodHandle target, MethodType newType, String permutation) {
+        MethodType oldType = target.type();
+        return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
+                                                 newType, target.type(),
+                                                 permutation);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which adapts the type of the
+     * given method handle to a new type, by spreading the final argument.
+     * The resulting method handle is guaranteed to confess a type
+     * which is equal to the desired new type.
+     * <p>
+     * The final parameter type of the new type must be an array type T[].
+     * This is the type of what is called the <i>spread</i> argument.
+     * All other arguments of the new type are called <i>ordinary</i> arguments.
+     * <p>
+     * The ordinary arguments of the new type are pairwise converted
+     * to the initial parameter types of the old type, according to the
+     * rules in {@link #convertArguments}.
+     * Any additional arguments in the old type
+     * are converted from the array element type T,
+     * again according to the rules in {@link #convertArguments}.
+     * The return value is converted according likewise.
+     * <p>
+     * The call verifies that the spread argument is in fact an array
+     * of exactly the type length, i.e., the excess number of
+     * arguments in the old type over the ordinary arguments in the new type.
+     * If there are no excess arguments, the spread argument is also
+     * allowed to be null.
+     * @param target the method handle to invoke after the argument is prepended
+     * @param newType the expected type of the new method handle
+     * @return a new method handle which spreads its final argument,
+     *         before calling the original method handle
+     */
+    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);
+        if (spreadPos < 0 || numSpread < 0)
+            throw newIllegalArgumentException("wrong number of arguments");
+        newType = newType.changeVarArgs(true);
+        return MethodHandleImpl.convertArguments(IMPL_TOKEN, target, newType, oldType, null);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which adapts the type of the
+     * given method handle to a new type, by collecting a series of
+     * trailing arguments into an array.
+     * The resulting method handle is guaranteed to confess a type
+     * which is equal to the desired new type.
+     * <p>
+     * This method is inverse to {@link #spreadArguments}.
+     * The final parameter type of the old type must be an array type T[],
+     * which is the type of what is called the <i>spread</i> argument.
+     * The trailing arguments of the new type which correspond to
+     * the spread argument are all converted to type T and collected
+     * into an array before the original method is called.
+     * @param target the method handle to invoke after the argument is prepended
+     * @param newType the expected type of the new method handle
+     * @return a new method handle which collects some trailings argument
+     *         into an array, before calling the original method handle
+     */
+    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");
+        oldType = oldType.changeVarArgs(true);
+        return MethodHandleImpl.convertArguments(IMPL_TOKEN, target, newType, oldType, null);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which calls the original method handle,
+     * after inserting the given argument as the first argument.
+     * The type of the new method handle will drop the first argument
+     * type from the original handle's type.
+     * <p>
+     * Equivalent to {@code insertArgument(target, value, 0)}.
+     */
+    public static
+    MethodHandle insertArgument(MethodHandle target, Object value) {
+        return insertArgument(target, value, 0);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which calls the original method handle,
+     * after appending the given argument as the final argument.
+     * The type of the new method handle will drop the last argument
+     * type from the original handle's type.
+     * <p>
+     * Equivalent to {@code insertArgument(target, value, N)},
+     * where <i>N</i> is the number of arguments to <i>target</i>.
+     */
+    public static
+    MethodHandle appendArgument(MethodHandle target, Object value) {
+        return insertArgument(target, value, target.type().parameterCount());
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce a method handle which calls the original method handle,
+     * after inserting the given argument at the given position.
+     * The type of the new method handle will drop the corresponding argument
+     * type from the original handle's type.
+     * <p>
+     * The given argument object must match the dropped argument type.
+     * If the dropped argument type is a primitive, the argument object
+     * must be a wrapper, and is unboxed to produce the primitive.
+     * <p>
+     * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
+     * where <i>N</i> is the number of argument types in <i>target</i>,
+     * meaning to insert the new argument as the first or last (respectively),
+     * or somewhere in between.
+     * @param target the method handle to invoke after the argument is inserted
+     * @param value the argument to insert
+     * @param pos where to insert the argument (zero for the first)
+     * @return a new method handle which inserts an additional argument,
+     *         before calling the original method handle
+     */
+    public static
+    MethodHandle insertArgument(MethodHandle target, Object value, int pos) {
+        MethodType oldType = target.type();
+        ArrayList<Class<?>> ptypes =
+                new ArrayList<Class<?>>(oldType.parameterList());
+        int outargs = oldType.parameterCount();
+        int inargs  = outargs - 1;
+        if (pos < 0 || pos >= outargs)
+            throw newIllegalArgumentException("no argument type to append");
+        Class<?> valueType = ptypes.remove(pos);
+        value = checkValue(valueType, value);
+        if (pos == 0 && !valueType.isPrimitive()) {
+            // At least for now, make bound method handles a special case.
+            // This lets us get by with minimal JVM support, at the expense
+            // of generating signature-specific adapters as Java bytecodes.
+            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, target, value);
+            if (bmh != null)  return bmh;
+            // else fall through to general adapter machinery
+        }
+        return MethodHandleImpl.bindArgument(IMPL_TOKEN, target, pos, value);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Produce 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-1</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.
+     * @param target the method handle to invoke after the argument is dropped
+     * @param valueTypes the type(s) of the argument to drop
+     * @param pos which argument to drop (zero for the first)
+     * @return a new method handle which drops an argument of the given type,
+     *         before calling the original method handle
+     */
+    public static
+    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
+        if (valueTypes.length == 0)  return target;
+        MethodType oldType = target.type();
+        int outargs = oldType.parameterCount();
+        int inargs  = outargs + valueTypes.length;
+        if (pos < 0 || pos >= inargs)
+            throw newIllegalArgumentException("no argument type to remove");
+        ArrayList<Class<?>> ptypes =
+                new ArrayList<Class<?>>(oldType.parameterList());
+        ptypes.addAll(pos, Arrays.asList(valueTypes));
+        MethodType newType = MethodType.make(oldType.returnType(), ptypes);
+        return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * 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.
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>
+     * signature T(A...);
+     * boolean test(A...);
+     * T target(A...);
+     * T fallback(A...);
+     * T adapter(A... a) {
+     *   if (test(a...))
+     *     return target(a...);
+     *   else
+     *     return fallback(a...);
+     * }
+     * </pre></blockquote>
+     * @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 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) {
+        if (target.type() != fallback.type())
+            throw newIllegalArgumentException("target and fallback types do not match");
+        if (target.type().changeReturnType(boolean.class) != test.type())
+            throw newIllegalArgumentException("target and test types do not match");
+        /* {
+            MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
+                return z ? t : f;
+            }
+            MethodHandle choose = findVirtual(MethodHandles.class, "choose",
+                    MethodType.make(boolean.class, MethodHandle.class, MethodHandle.class));
+            choose = appendArgument(choose, target);
+            choose = appendArgument(choose, fallback);
+            choose = combineArguments(choose, test);
+            MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
+            return checkArguments(invoke, choose, 0);
+        } */
+        return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
+    }
+
+    /**
+     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
+     * Adapt a target method handle {@code target} by first checking its arguments,
+     * and then calling the target.
+     * The check is performed by a second method handle, the {@code checker}.
+     * After this, control passes to the target method handle, with the same
+     * arguments.
+     * <p>
+     * The return value of the checker is inserted into the argument list
+     * for {@code target} at the indicated position {@code pos}, if it is non-negative.
+     * Except for this inserted argument (if any), the argument types of
+     * the target {@code target} and the {@code checker} must be identical.
+     * <p>
+     * The checker handle must have the same argument types as the
+     * target handle, but must return {@link MethodHandle} instead of
+     * the ultimate return type.  The returned method handle, in turn,
+     * is required to have exactly the given final method type.
+     * <p> Here is pseudocode for the resulting adapter:
+     * <blockquote><pre>
+     * signature V(A[pos]..., B...);
+     * signature T(A[pos]..., V, B...);
+     * T target(A... a, V, B... b);
+     * U checker(A..., B...);
+     * T adapter(A... a, B... b) {
+     *   V v = checker(a..., b...);
+     *   return target(a..., v, b...);
+     * }
+     * </pre></blockquote>
+     * @param target the method handle to invoke after arguments are checked
+     * @param checker method handle to call initially on the incoming arguments
+     * @param pos where the return value of {@code checker} is to
+     *          be inserted as an argument to {@code target}
+     * @return method handle which incorporates the specified dispatch logic
+     * @throws IllegalArgumentException if {@code checker} does not itself
+     *          return either void or the {@code pos}-th argument of {@code target},
+     *          or does not have the same argument types as {@code target}
+     *          (minus the inserted argument)
+     */
+    public static
+    MethodHandle checkArguments(MethodHandle target, MethodHandle checker, int pos) {
+        MethodType mhType = target.type();
+        Class<?> checkType = checker.type().returnType();
+        MethodType incomingArgs;
+        if (pos < 0) {
+            // No inserted argument; target & checker must have same argument types.
+            incomingArgs = mhType;
+            if (!incomingArgs.changeReturnType(checkType).equals(checker.type()))
+                throw newIllegalArgumentException("target and checker types do not match");
+        } else {
+            // Inserted argument.
+            if (pos >= mhType.parameterCount()
+                || mhType.parameterType(pos) != checkType)
+                throw newIllegalArgumentException("inserted checker argument does not match target");
+            incomingArgs = mhType.deleteParameterType(pos);
+        }
+        if (!incomingArgs.changeReturnType(checkType).equals(checker.type())) {
+            throw newIllegalArgumentException("target and checker types do not match");
+        }
+        return MethodHandleImpl.checkArguments(IMPL_TOKEN, target, checker, pos);
+    }
+
+    /// standard method handles
+
+    /**
+     * Identity function.
+     * @param x an arbitrary reference value
+     * @return the same value x
+     */
+    /*public*/ static <T>
+    T identity(T x) {
+        return x;
+    }
+
+    /**
+     * A method handle for {@link #identity}
+     */
+    /*public*/ static
+    MethodHandle identityMethod() {
+        if (IDENTITY == null)
+            IDENTITY = findStatic(MethodHandle.class, "identity", IDENTITY_TYPE);
+        return IDENTITY;
+    }
+    private static
+    MethodHandle IDENTITY;
+    private static final
+    MethodType IDENTITY_TYPE = MethodType.make(Object.class, Object.class);
+
+    /**
+     * Empty function.
+     */
+    /*public*/ static
+    void empty() {
+    }
+
+    /**
+     * A method handle for {@link #empty}
+     */
+    /*public*/ static
+    MethodHandle emptyMethod() {
+        if (EMPTY == null)
+            EMPTY = findStatic(MethodHandle.class, "empty", EMPTY_TYPE);
+        return EMPTY;
+    }
+    private static
+    MethodHandle EMPTY;
+    private static final
+    MethodType EMPTY_TYPE = MethodType.make(void.class);
+}
