jdk/src/share/classes/java/dyn/MethodHandles.java
changeset 4537 7c3c7f8d5195
parent 2764 2e45af54c0f9
child 5722 4ada807383c8
child 5506 202f599c92aa
equal deleted inserted replaced
4536:0f6ec6364a69 4537:7c3c7f8d5195
    32 import sun.dyn.util.VerifyAccess;
    32 import sun.dyn.util.VerifyAccess;
    33 import sun.dyn.util.Wrapper;
    33 import sun.dyn.util.Wrapper;
    34 import java.lang.reflect.Field;
    34 import java.lang.reflect.Field;
    35 import java.lang.reflect.Method;
    35 import java.lang.reflect.Method;
    36 import java.lang.reflect.Modifier;
    36 import java.lang.reflect.Modifier;
       
    37 import java.util.List;
    37 import java.util.ArrayList;
    38 import java.util.ArrayList;
    38 import java.util.Arrays;
    39 import java.util.Arrays;
    39 import sun.dyn.Invokers;
    40 import sun.dyn.Invokers;
    40 import sun.dyn.MethodTypeImpl;
    41 import sun.dyn.MethodTypeImpl;
    41 import sun.reflect.Reflection;
    42 import sun.reflect.Reflection;
    42 import static sun.dyn.MemberName.newIllegalArgumentException;
    43 import static sun.dyn.MemberName.newIllegalArgumentException;
    43 import static sun.dyn.MemberName.newNoAccessException;
    44 import static sun.dyn.MemberName.newNoAccessException;
    44 
    45 
    45 /**
    46 /**
    46  * Fundamental operations and utilities for MethodHandle.
    47  * Fundamental operations and utilities for MethodHandle.
       
    48  * They fall into several categories:
       
    49  * <ul>
       
    50  * <li>Reifying methods and fields.  This is subject to access checks.
       
    51  * <li>Invoking method handles on dynamically typed arguments and/or varargs arrays.
       
    52  * <li>Combining or transforming pre-existing method handles into new ones.
       
    53  * <li>Miscellaneous emulation of common JVM operations or control flow patterns.
       
    54  * </ul>
    47  * <p>
    55  * <p>
    48  * <em>API Note:</em>  The matching of method types in this API cannot
       
    49  * be completely checked by Java's generic type system for three reasons:
       
    50  * <ol>
       
    51  * <li>Method types range over all possible arities,
       
    52  * from no arguments to an arbitrary number of arguments.
       
    53  * Generics are not variadic, and so cannot represent this.</li>
       
    54  * <li>Method types can specify arguments of primitive types,
       
    55  * which Java generic types cannot range over.</li>
       
    56  * <li>Method types can optionally specify varargs (ellipsis).</li>
       
    57  * </ol>
       
    58  * @author John Rose, JSR 292 EG
    56  * @author John Rose, JSR 292 EG
    59  */
    57  */
    60 public class MethodHandles {
    58 public class MethodHandles {
    61 
    59 
    62     private MethodHandles() { }  // do not instantiate
    60     private MethodHandles() { }  // do not instantiate
    66     static { MethodHandleImpl.initStatics(); }
    64     static { MethodHandleImpl.initStatics(); }
    67     // See IMPL_LOOKUP below.
    65     // See IMPL_LOOKUP below.
    68 
    66 
    69     //// Method handle creation from ordinary methods.
    67     //// Method handle creation from ordinary methods.
    70 
    68 
       
    69     /** Create a {@link Lookup} lookup object on the caller.
       
    70      *
       
    71      */
    71     public static Lookup lookup() {
    72     public static Lookup lookup() {
    72         return new Lookup();
    73         return new Lookup();
    73     }
    74     }
    74 
    75 
    75     /**
    76     /** Version of lookup which is trusted minimally.
    76      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
    77      *  It can only be used to create method handles to
       
    78      *  publicly accessible members.
       
    79      */
       
    80     public static Lookup publicLookup() {
       
    81         return Lookup.PUBLIC_LOOKUP;
       
    82     }
       
    83 
       
    84     /**
    77      * A factory object for creating method handles, when the creation
    85      * A factory object for creating method handles, when the creation
    78      * requires access checking.  Method handles do not perform
    86      * requires access checking.  Method handles do not perform
    79      * access checks when they are called; this is a major difference
    87      * access checks when they are called; this is a major difference
    80      * from reflective {@link Method}, which performs access checking
    88      * from reflective {@link Method}, which performs access checking
    81      * against every caller, on every call.  Method handle access
    89      * against every caller, on every call.  Method handle access
   119         private final Class<?> lookupClass;
   127         private final Class<?> lookupClass;
   120 
   128 
   121         /** Which class is performing the lookup?  It is this class against
   129         /** Which class is performing the lookup?  It is this class against
   122          *  which checks are performed for visibility and access permissions.
   130          *  which checks are performed for visibility and access permissions.
   123          *  <p>
   131          *  <p>
   124          *  This value is null if and only if this lookup is {@link #PUBLIC_LOOKUP}.
   132          *  This value is null if and only if this lookup was produced
       
   133          *  by {@link MethodHandles#publicLookup}.
   125          */
   134          */
   126         public Class<?> lookupClass() {
   135         public Class<?> lookupClass() {
   127             return lookupClass;
   136             return lookupClass;
   128         }
   137         }
   129 
   138 
   133          * which in turn is called by a method not in this package.
   142          * which in turn is called by a method not in this package.
   134          * Also, don't make it private, lest javac interpose
   143          * Also, don't make it private, lest javac interpose
   135          * an access$N method.
   144          * an access$N method.
   136          */
   145          */
   137         Lookup() {
   146         Lookup() {
   138             Class caller = getCallerClassAtEntryPoint();
   147             this(IMPL_TOKEN, getCallerClassAtEntryPoint());
   139             // make sure we haven't accidentally picked up this class:
   148         }
   140             checkUnprivilegedlookupClass(caller);
   149 
   141             this.lookupClass = caller;
   150         Lookup(Access token, Class<?> lookupClass) {
       
   151             // make sure we haven't accidentally picked up a privileged class:
       
   152             checkUnprivilegedlookupClass(lookupClass);
       
   153             this.lookupClass = lookupClass;
       
   154         }
       
   155 
       
   156         /**
       
   157          * Create a lookup on the specified class.
       
   158          * The result is guaranteed to have no more access privileges
       
   159          * than the original.
       
   160          */
       
   161         public Lookup in(Class<?> newLookupClass) {
       
   162             if (this == PUBLIC_LOOKUP)  return PUBLIC_LOOKUP;
       
   163             if (newLookupClass == null)  return PUBLIC_LOOKUP;
       
   164             if (newLookupClass == lookupClass)  return this;
       
   165             if (this != IMPL_LOOKUP) {
       
   166                 if (!VerifyAccess.isSamePackage(lookupClass, newLookupClass))
       
   167                     throw newNoAccessException(new MemberName(newLookupClass), this);
       
   168                 checkUnprivilegedlookupClass(newLookupClass);
       
   169             }
       
   170             return new Lookup(newLookupClass);
   142         }
   171         }
   143 
   172 
   144         private Lookup(Class<?> lookupClass) {
   173         private Lookup(Class<?> lookupClass) {
   145             this.lookupClass = lookupClass;
   174             this.lookupClass = lookupClass;
   146         }
   175         }
       
   176 
       
   177         // Make sure outer class is initialized first.
       
   178         static { IMPL_TOKEN.getClass(); }
   147 
   179 
   148         private static final Class<?> PUBLIC_ONLY = sun.dyn.empty.Empty.class;
   180         private static final Class<?> PUBLIC_ONLY = sun.dyn.empty.Empty.class;
   149 
   181 
   150         /** Version of lookup which is trusted minimally.
   182         /** Version of lookup which is trusted minimally.
   151          *  It can only be used to create method handles to
   183          *  It can only be used to create method handles to
   152          *  publicly accessible members.
   184          *  publicly accessible members.
   153          */
   185          */
   154         public static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY);
   186         static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY);
   155 
   187 
   156         /** Package-private version of lookup which is trusted. */
   188         /** Package-private version of lookup which is trusted. */
   157         static final Lookup IMPL_LOOKUP = new Lookup(null);
   189         static final Lookup IMPL_LOOKUP = new Lookup(null);
   158         static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
   190         static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
   159 
   191 
   176         private static Class<?> getCallerClassAtEntryPoint() {
   208         private static Class<?> getCallerClassAtEntryPoint() {
   177             final int CALLER_DEPTH = 4;
   209             final int CALLER_DEPTH = 4;
   178             // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
   210             // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
   179             // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
   211             // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
   180             // Note:  This should be the only use of getCallerClass in this file.
   212             // Note:  This should be the only use of getCallerClass in this file.
       
   213             assert(Reflection.getCallerClass(CALLER_DEPTH-1) == MethodHandles.class);
   181             return Reflection.getCallerClass(CALLER_DEPTH);
   214             return Reflection.getCallerClass(CALLER_DEPTH);
   182         }
   215         }
   183 
   216 
   184         /**
   217         /**
   185          * Produce a method handle for a static method.
   218          * Produce a method handle for a static method.
   186          * The type of the method handle will be that of the method.
   219          * The type of the method handle will be that of the method.
       
   220          * (Since static methods do not take receivers, there is no
       
   221          * additional receiver argument inserted into the method handle type,
       
   222          * as there would be with {@linkplain #findVirtual} or {@linkplain #findSpecial}.)
   187          * The method and all its argument types must be accessible to the lookup class.
   223          * The method and all its argument types must be accessible to the lookup class.
   188          * If the method's class has not yet been initialized, that is done
   224          * If the method's class has not yet been initialized, that is done
   189          * immediately, before the method handle is returned.
   225          * immediately, before the method handle is returned.
   190          * @param defc the class from which the method is accessed
   226          * @param defc the class from which the method is accessed
   191          * @param name the name of the method
   227          * @param name the name of the method
   194          * @exception SecurityException <em>TBD</em>
   230          * @exception SecurityException <em>TBD</em>
   195          * @exception NoAccessException if the method does not exist or access checking fails
   231          * @exception NoAccessException if the method does not exist or access checking fails
   196          */
   232          */
   197         public
   233         public
   198         MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
   234         MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
   199             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass);
   235             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass());
   200             checkStatic(true, method, lookupClass);
   236             VerifyAccess.checkName(method, this);
       
   237             checkStatic(true, method, this);
   201             //throw NoSuchMethodException
   238             //throw NoSuchMethodException
   202             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass);
   239             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass());
   203         }
   240         }
   204 
   241 
   205         /**
   242         /**
   206          * Produce a method handle for a virtual method.
   243          * Produce a method handle for a virtual method.
   207          * The type of the method handle will be that of the method,
   244          * The type of the method handle will be that of the method,
   226          * @return the desired method handle
   263          * @return the desired method handle
   227          * @exception SecurityException <em>TBD</em>
   264          * @exception SecurityException <em>TBD</em>
   228          * @exception NoAccessException if the method does not exist or access checking fails
   265          * @exception NoAccessException if the method does not exist or access checking fails
   229          */
   266          */
   230         public MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
   267         public MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
   231             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass);
   268             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass());
   232             checkStatic(false, method, lookupClass);
   269             VerifyAccess.checkName(method, this);
   233             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass);
   270             checkStatic(false, method, this);
       
   271             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass());
   234         }
   272         }
   235 
   273 
   236         /**
   274         /**
   237          * Produce an early-bound method handle for a virtual method,
   275          * Produce an early-bound method handle for a virtual method,
   238          * as if called from an {@code invokespecial}
   276          * as if called from an {@code invokespecial}
   257          * @exception SecurityException <em>TBD</em>
   295          * @exception SecurityException <em>TBD</em>
   258          * @exception NoAccessException if the method does not exist or access checking fails
   296          * @exception NoAccessException if the method does not exist or access checking fails
   259          */
   297          */
   260         public MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
   298         public MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
   261                                         Class<?> specialCaller) throws NoAccessException {
   299                                         Class<?> specialCaller) throws NoAccessException {
   262             checkSpecialCaller(specialCaller, lookupClass);
   300             checkSpecialCaller(specialCaller, this);
   263             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
   301             Lookup slookup = this.in(specialCaller);
   264             checkStatic(false, method, lookupClass);
   302             MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, slookup.lookupClass());
       
   303             VerifyAccess.checkName(method, this);
       
   304             checkStatic(false, method, this);
   265             if (name.equals("<init>")) {
   305             if (name.equals("<init>")) {
   266                 throw newNoAccessException("cannot directly invoke a constructor", method, null);
   306                 throw newNoAccessException("cannot directly invoke a constructor", method, null);
   267             } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
   307             } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
   268                 throw newNoAccessException("method must be in a superclass of lookup class", method, lookupClass);
   308                 throw newNoAccessException("method must be in a superclass of lookup class", method, slookup.lookupClass());
   269             }
   309             }
   270             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
   310             return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, slookup.lookupClass());
   271         }
   311         }
   272 
   312 
   273         /**
   313         /**
   274          * Produce an early-bound method handle for a non-static method.
   314          * Produce an early-bound method handle for a non-static method.
   275          * The receiver must have a supertype {@code defc} in which a method
   315          * The receiver must have a supertype {@code defc} in which a method
   276          * of the given name and type is accessible to the lookup class.
   316          * of the given name and type is accessible to the lookup class.
   277          * The method and all its argument types must be accessible to the lookup class.
   317          * The method and all its argument types must be accessible to the lookup class.
   278          * The type of the method handle will be that of the method.
   318          * The type of the method handle will be that of the method,
   279          * The given receiver will be bound into the method handle.
   319          * without any insertion of an additional receiver parameter.
       
   320          * The given receiver will be bound into the method handle,
       
   321          * so that every call to the method handle will invoke the
       
   322          * requested method on the given receiver.
   280          * <p>
   323          * <p>
   281          * Equivalent to the following expression:
   324          * This is equivalent to the following expression:
   282          * <code>
   325          * <code>
   283          * {@link #insertArgument}({@link #findVirtual}(defc, name, type), receiver)
   326          * {@link #insertArguments}({@link #findVirtual}(defc, name, type), receiver)
   284          * </code>
   327          * </code>
       
   328          * where {@code defc} is either {@code receiver.getClass()} or a super
       
   329          * type of that class, in which the requested method is accessible
       
   330          * to the lookup class.
   285          * @param receiver the object from which the method is accessed
   331          * @param receiver the object from which the method is accessed
   286          * @param name the name of the method
   332          * @param name the name of the method
   287          * @param type the type of the method, with the receiver argument omitted
   333          * @param type the type of the method, with the receiver argument omitted
   288          * @return the desired method handle
   334          * @return the desired method handle
   289          * @exception SecurityException <em>TBD</em>
   335          * @exception SecurityException <em>TBD</em>
   290          * @exception NoAccessException if the method does not exist or access checking fails
   336          * @exception NoAccessException if the method does not exist or access checking fails
   291          */
   337          */
   292         public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
   338         public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
   293             Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
   339             Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
   294             MemberName reference = new MemberName(rcvc, name, type);
   340             MemberName reference = new MemberName(rcvc, name, type);
   295             MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass);
   341             MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass());
   296             checkStatic(false, method, lookupClass);
   342             VerifyAccess.checkName(method, this);
   297             MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass);
   343             checkStatic(false, method, this);
       
   344             MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass());
   298             MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
   345             MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
   299             if (bmh == null)
   346             if (bmh == null)
   300                 throw newNoAccessException(method, lookupClass);
   347                 throw newNoAccessException(method, this);
   301             return bmh;
   348             return bmh;
   302         }
   349         }
   303 
   350 
   304         /**
   351         /**
       
   352          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   305          * Make a direct method handle to <i>m</i>, if the lookup class has permission.
   353          * Make a direct method handle to <i>m</i>, if the lookup class has permission.
   306          * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
   354          * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
   307          * If <i>m</i> is virtual, overriding is respected on every call.
   355          * If <i>m</i> is virtual, overriding is respected on every call.
   308          * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
   356          * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
   309          * The type of the method handle will be that of the method,
   357          * The type of the method handle will be that of the method,
   314          * @param m the reflected method
   362          * @param m the reflected method
   315          * @return a method handle which can invoke the reflected method
   363          * @return a method handle which can invoke the reflected method
   316          * @exception NoAccessException if access checking fails
   364          * @exception NoAccessException if access checking fails
   317          */
   365          */
   318         public MethodHandle unreflect(Method m) throws NoAccessException {
   366         public MethodHandle unreflect(Method m) throws NoAccessException {
   319             return unreflectImpl(new MemberName(m), m.isAccessible(), true, lookupClass);
   367             return unreflectImpl(new MemberName(m), m.isAccessible(), true, false, this);
   320         }
   368         }
   321 
   369 
   322         /**
   370         /**
       
   371          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   323          * Produce a method handle for a reflected method.
   372          * Produce a method handle for a reflected method.
   324          * It will bypass checks for overriding methods on the receiver,
   373          * It will bypass checks for overriding methods on the receiver,
   325          * as if by the {@code invokespecial} instruction.
   374          * as if by the {@code invokespecial} instruction.
   326          * The type of the method handle will be that of the method,
   375          * The type of the method handle will be that of the method,
   327          * with the receiver type prepended.
   376          * with the receiver type prepended.
   331          * @param m the reflected method
   380          * @param m the reflected method
   332          * @return a method handle which can invoke the reflected method
   381          * @return a method handle which can invoke the reflected method
   333          * @exception NoAccessException if access checking fails
   382          * @exception NoAccessException if access checking fails
   334          */
   383          */
   335         public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
   384         public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
   336             checkSpecialCaller(specialCaller, lookupClass);
   385             checkSpecialCaller(specialCaller, this);
       
   386             Lookup slookup = this.in(specialCaller);
   337             MemberName mname = new MemberName(m);
   387             MemberName mname = new MemberName(m);
   338             checkStatic(false, mname, lookupClass);
   388             checkStatic(false, mname, this);
   339             return unreflectImpl(mname, m.isAccessible(), false, specialCaller);
   389             return unreflectImpl(mname, m.isAccessible(), false, false, slookup);
   340         }
   390         }
   341 
   391 
   342         /**
   392         /**
       
   393          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   343          * Produce a method handle for a reflected constructor.
   394          * Produce a method handle for a reflected constructor.
   344          * The type of the method handle will be that of the constructor.
   395          * The type of the method handle will be that of the constructor,
       
   396          * with the return type changed to the declaring class.
   345          * The method handle will perform a {@code newInstance} operation,
   397          * The method handle will perform a {@code newInstance} operation,
   346          * creating a new instance of the constructor's class on the
   398          * creating a new instance of the constructor's class on the
   347          * arguments passed to the method handle.
   399          * arguments passed to the method handle.
   348          * <p>
   400          * <p>
   349          * If the constructor's {@code accessible} flag is not set,
   401          * If the constructor's {@code accessible} flag is not set,
   350          * access checking is performed immediately on behalf of the lookup class,
   402          * access checking is performed immediately on behalf of the lookup class.
   351          * as if {@code invokespecial} instruction were being linked.
       
   352          * @param ctor the reflected constructor
   403          * @param ctor the reflected constructor
   353          * @return a method handle which can invoke the reflected constructor
   404          * @return a method handle which can invoke the reflected constructor
   354          * @exception NoAccessException if access checking fails
   405          * @exception NoAccessException if access checking fails
   355          */
   406          */
   356         public MethodHandle unreflectConstructor(Constructor ctor) throws NoAccessException {
   407         public MethodHandle unreflectConstructor(Constructor ctor) throws NoAccessException {
   357             MemberName m = new MemberName(ctor);
   408             MemberName m = new MemberName(ctor);
   358             return unreflectImpl(m, ctor.isAccessible(), false, lookupClass);
   409             return unreflectImpl(m, ctor.isAccessible(), false, false, this);
   359         }
   410         }
   360 
   411 
   361         /**
   412         /**
   362          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   413          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   363          * Produce a method handle giving read access to a reflected field.
   414          * Produce a method handle giving read access to a reflected field.
   364          * The type of the method handle will have a return type of the field's
   415          * The type of the method handle will have a return type of the field's
   365          * value type.  Its sole argument will be the field's containing class
   416          * value type.
   366          * (but only if it is non-static).
   417          * If the field is static, the method handle will take no arguments.
       
   418          * Otherwise, its single argument will be the instance containing
       
   419          * the field.
   367          * If the method's {@code accessible} flag is not set,
   420          * If the method's {@code accessible} flag is not set,
   368          * access checking is performed immediately on behalf of the lookup class.
   421          * access checking is performed immediately on behalf of the lookup class.
   369          * @param f the reflected field
   422          * @param f the reflected field
   370          * @return a method handle which can load values from the reflected field
   423          * @return a method handle which can load values from the reflected field
   371          * @exception NoAccessException if access checking fails
   424          * @exception NoAccessException if access checking fails
   372          */
   425          */
   373         public MethodHandle unreflectGetter(Field f) throws NoAccessException {
   426         public MethodHandle unreflectGetter(Field f) throws NoAccessException {
   374             return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), false, lookupClass);
   427             MemberName m = new MemberName(f);
       
   428             return unreflectImpl(m, f.isAccessible(), false, false, this);
   375         }
   429         }
   376 
   430 
   377         /**
   431         /**
   378          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   432          * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   379          * Produce a method handle giving write access to a reflected field.
   433          * Produce a method handle giving write access to a reflected field.
   380          * The type of the method handle will have a void return type.
   434          * The type of the method handle will have a void return type.
   381          * Its last argument will be the field's value type.
   435          * If the field is static, the method handle will take a single
   382          * Its other argument will be the field's containing class
   436          * argument, of the field's value type, the value to be stored.
   383          * (but only if it is non-static).
   437          * Otherwise, the two arguments will be the instance containing
       
   438          * the field, and the value to be stored.
   384          * If the method's {@code accessible} flag is not set,
   439          * If the method's {@code accessible} flag is not set,
   385          * access checking is performed immediately on behalf of the lookup class.
   440          * access checking is performed immediately on behalf of the lookup class.
   386          * @param f the reflected field
   441          * @param f the reflected field
   387          * @return a method handle which can store values into the reflected field
   442          * @return a method handle which can store values into the reflected field
   388          * @exception NoAccessException if access checking fails
   443          * @exception NoAccessException if access checking fails
   389          */
   444          */
   390         public MethodHandle unreflectSetter(Field f) throws NoAccessException {
   445         public MethodHandle unreflectSetter(Field f) throws NoAccessException {
   391             return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), true, lookupClass);
   446             MemberName m = new MemberName(f);
       
   447             return unreflectImpl(m, f.isAccessible(), false, true, this);
   392         }
   448         }
   393 
   449 
   394     }
   450     }
   395 
   451 
   396     static /*must not be public*/
   452     static /*must not be public*/
   397     MethodHandle findStaticFrom(Class<?> lookupClass,
   453     MethodHandle findStaticFrom(Lookup lookup,
   398                                 Class<?> defc, String name, MethodType type) throws NoAccessException {
   454                                 Class<?> defc, String name, MethodType type) throws NoAccessException {
   399         MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass);
   455         MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookup.lookupClass());
   400         checkStatic(true, method, lookupClass);
   456         VerifyAccess.checkName(method, lookup);
   401         return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass);
   457         checkStatic(true, method, lookup);
   402     }
   458         return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookup.lookupClass());
   403 
   459     }
   404     static void checkStatic(boolean wantStatic, MemberName m, Class<?> lookupClass) {
   460 
       
   461     static void checkStatic(boolean wantStatic, MemberName m, Lookup lookup) {
   405         if (wantStatic != m.isStatic()) {
   462         if (wantStatic != m.isStatic()) {
   406             String message = wantStatic ? "expected a static method" : "expected a non-static method";
   463             String message = wantStatic ? "expected a static method" : "expected a non-static method";
   407             throw newNoAccessException(message, m, lookupClass);
   464             throw newNoAccessException(message, m, lookup.lookupClass());
   408         }
   465         }
   409     }
   466     }
   410 
   467 
   411     static void checkSpecialCaller(Class<?> specialCaller, Class<?> lookupClass) {
   468     static void checkSpecialCaller(Class<?> specialCaller, Lookup lookup) {
   412         if (lookupClass == Lookup.IMPL_LOOKUP.lookupClass())
   469         if (lookup == Lookup.IMPL_LOOKUP)
   413             return;  // privileged action
   470             return;  // privileged action
   414         if (lookupClass == null ||  // public-only access
   471         assert(lookup.lookupClass() != null);
   415             !VerifyAccess.isSamePackageMember(specialCaller, lookupClass))
   472         if (!VerifyAccess.isSamePackageMember(specialCaller, lookup.lookupClass()))
   416             throw newNoAccessException("no private access", new MemberName(specialCaller), lookupClass);
   473             throw newNoAccessException("no private access", new MemberName(specialCaller), lookup.lookupClass());
   417     }
   474     }
   418 
   475 
   419     // Helper for creating handles on reflected methods and constructors.
   476     // Helper for creating handles on reflected methods and constructors.
   420     static MethodHandle unreflectImpl(MemberName m, boolean isAccessible,
   477     static MethodHandle unreflectImpl(MemberName m, boolean isAccessible,
   421                                       boolean doDispatch, Class<?> lookupClass) {
   478                                       boolean doDispatch, boolean isSetter, Lookup lookup) {
   422         MethodType mtype = m.getInvocationType();
   479         MethodType narrowMethodType = null;
   423         Class<?> defc = m.getDeclaringClass();
   480         Class<?> defc = m.getDeclaringClass();
       
   481         boolean isSpecialInvoke = m.isInvocable() && !doDispatch;
   424         int mods = m.getModifiers();
   482         int mods = m.getModifiers();
   425         if (m.isStatic()) {
   483         if (m.isStatic()) {
   426             if (!isAccessible &&
   484             if (!isAccessible &&
   427                     VerifyAccess.isAccessible(defc, mods, false, lookupClass) == null)
   485                     VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), false) == null)
   428                 throw newNoAccessException(m, lookupClass);
   486                 throw newNoAccessException(m, lookup);
   429         } else {
   487         } else {
   430             Class<?> constraint;
   488             Class<?> constraint;
   431             if (isAccessible) {
   489             if (isAccessible) {
   432                 // abbreviated access check for "unlocked" method
   490                 // abbreviated access check for "unlocked" method
   433                 constraint = doDispatch ? defc : lookupClass;
   491                 constraint = doDispatch ? defc : lookup.lookupClass();
   434             } else {
   492             } else {
   435                 constraint = VerifyAccess.isAccessible(defc, mods, doDispatch, lookupClass);
   493                 constraint = VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), isSpecialInvoke);
       
   494             }
       
   495             if (constraint == null) {
       
   496                 throw newNoAccessException(m, lookup);
   436             }
   497             }
   437             if (constraint != defc && !constraint.isAssignableFrom(defc)) {
   498             if (constraint != defc && !constraint.isAssignableFrom(defc)) {
   438                 if (!defc.isAssignableFrom(constraint))
   499                 if (!defc.isAssignableFrom(constraint))
   439                     throw newNoAccessException("receiver must be in caller class", m, lookupClass);
   500                     throw newNoAccessException("receiver must be in caller class", m, lookup.lookupClass());
   440                 mtype = mtype.changeParameterType(0, constraint);
   501                 if (m.isInvocable())
       
   502                     narrowMethodType = m.getInvocationType().changeParameterType(0, constraint);
       
   503                 else if (m.isField())
       
   504                     narrowMethodType = (!isSetter
       
   505                                         ? MethodType.methodType(m.getFieldType(), constraint)
       
   506                                         : MethodType.methodType(void.class, constraint, m.getFieldType()));
   441             }
   507             }
   442         }
   508         }
   443         return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookupClass);
   509         if (m.isInvocable())
       
   510             return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookup.lookupClass());
       
   511         else if (m.isField())
       
   512             return MethodHandleImpl.accessField(IMPL_TOKEN, m, isSetter, lookup.lookupClass());
       
   513         else
       
   514             throw new InternalError();
   444     }
   515     }
   445 
   516 
   446     /**
   517     /**
   447      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   518      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   448      * Produce a method handle giving read access to elements of an array.
   519      * Produce a method handle giving read access to elements of an array.
   470     public static
   541     public static
   471     MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
   542     MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
   472         return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
   543         return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
   473     }
   544     }
   474 
   545 
   475 
       
   476     /// method handle invocation (reflective style)
   546     /// method handle invocation (reflective style)
   477 
   547 
   478     /**
   548     /**
   479      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   549      * @deprecated Alias for MethodHandle.invokeVarargs.
   480      * Call the {@code invoke} method of a given method handle,
   550      */
   481      * with arguments that exactly match the parameter types of the method handle.
   551     @Deprecated
   482      * The length of the arguments array must equal the parameter count
   552     public static
   483      * of the target's type.
   553     Object invokeVarargs(MethodHandle target, Object... arguments) throws Throwable {
   484      * The arguments array is spread into separate arguments, and
   554         return target.invokeVarargs(arguments);
   485      * basic reference and unboxing conversions are applied.
   555     }
   486      * <p>
   556 
   487      * In order to match the type of the target, the following argument
   557     /**
   488      * conversions are applied as necessary:
   558      * @deprecated Alias for MethodHandle.invokeVarargs.
   489      * <ul>
   559      */
   490      * <li>reference casting
   560     @Deprecated
   491      * <li>unboxing
   561     public static
   492      * </ul>
   562     Object invoke(MethodHandle target, Object... arguments) throws Throwable {
   493      * The following conversions are not applied:
   563         return target.invokeVarargs(arguments);
   494      * <ul>
   564     }
   495      * <li>primitive conversions (e.g., {@code byte} to {@code int}
   565 
   496      * <li>varargs conversions other than the initial spread
   566     /**
   497      * <li>any application-specific conversions (e.g., string to number)
   567      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   498      * </ul>
   568      * Produce a method handle which will invoke any method handle of the
   499      * The result returned by the call is boxed if it is a primitive,
       
   500      * or forced to null if the return type is void.
       
   501      * <p>
       
   502      * This call is a convenience method for the following code:
       
   503      * <pre>
       
   504      *   MethodHandle invoker = MethodHandles.genericInvoker(target.type(), 0, true);
       
   505      *   Object result = invoker.invoke(arguments);
       
   506      * </pre>
       
   507      * @param target the method handle to invoke
       
   508      * @param arguments the arguments to pass to the target
       
   509      * @return the result returned by the target
       
   510      */
       
   511     public static
       
   512     Object invoke(MethodHandle target, Object... arguments) {
       
   513         int argc = arguments == null ? 0 : arguments.length;
       
   514         MethodType type = target.type();
       
   515         if (argc <= 4) {
       
   516             MethodHandle invoker = invokers(type).genericInvoker();
       
   517             switch (argc) {
       
   518                 case 0:  return invoker.<Object>invoke(target);
       
   519                 case 1:  return invoker.<Object>invoke(target,
       
   520                                     arguments[0]);
       
   521                 case 2:  return invoker.<Object>invoke(target,
       
   522                                     arguments[0], arguments[1]);
       
   523                 case 3:  return invoker.<Object>invoke(target,
       
   524                                     arguments[0], arguments[1], arguments[2]);
       
   525                 case 4:  return invoker.<Object>invoke(target,
       
   526                                     arguments[0], arguments[1], arguments[2], arguments[3]);
       
   527             }
       
   528         }
       
   529         MethodHandle invoker = invokers(type).varargsInvoker();
       
   530         return invoker.<Object>invoke(target, arguments);
       
   531     }
       
   532 
       
   533     public static
       
   534     Object invoke_0(MethodHandle target) {
       
   535         MethodHandle invoker = invokers(target.type()).genericInvoker();
       
   536         return invoker.<Object>invoke(target);
       
   537     }
       
   538     public static
       
   539     Object invoke_1(MethodHandle target, Object a0) {
       
   540         MethodHandle invoker = invokers(target.type()).genericInvoker();
       
   541         return invoker.<Object>invoke(target, a0);
       
   542     }
       
   543     public static
       
   544     Object invoke_2(MethodHandle target, Object a0, Object a1) {
       
   545         MethodHandle invoker = invokers(target.type()).genericInvoker();
       
   546         return invoker.<Object>invoke(target, a0, a1);
       
   547     }
       
   548     public static
       
   549     Object invoke_3(MethodHandle target, Object a0, Object a1, Object a2) {
       
   550         MethodHandle invoker = invokers(target.type()).genericInvoker();
       
   551         return invoker.<Object>invoke(target, a0, a1, a2);
       
   552     }
       
   553     public static
       
   554     Object invoke_4(MethodHandle target, Object a0, Object a1, Object a2, Object a3) {
       
   555         MethodHandle invoker = invokers(target.type()).genericInvoker();
       
   556         return invoker.<Object>invoke(target, a0, a1, a2, a3);
       
   557     }
       
   558 
       
   559     /**
       
   560      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
       
   561      * Give a method handle which will invoke any method handle of the
       
   562      * given type on a standard set of {@code Object} type arguments.
   569      * given type on a standard set of {@code Object} type arguments.
   563      * The the resulting invoker will be a method handle with the following
   570      * The resulting invoker will be a method handle with the following
   564      * arguments:
   571      * arguments:
   565      * <ul>
   572      * <ul>
   566      * <li>a single {@code MethodHandle} target
   573      * <li>a single {@code MethodHandle} target
   567      * <li>zero or more {@code Object} values
   574      * <li>zero or more {@code Object} values (one for each argument in {@code type})
   568      * <li>an optional {@code Object[]} array containing more arguments
       
   569      * </ul>
   575      * </ul>
   570      * The invoker will spread the varargs array (if present), apply
   576      * The invoker will apply reference casts as necessary and unbox primitive arguments,
       
   577      * as if by {@link #convertArguments}.
       
   578      * The return value of the invoker will be an {@code Object} reference,
       
   579      * boxing a primitive value if the original type returns a primitive,
       
   580      * and always null if the original type returns void.
       
   581      * <p>
       
   582      * This method is equivalent to the following code (though it may be more efficient):
       
   583      * <p><blockquote><pre>
       
   584      * MethodHandle invoker = exactInvoker(type);
       
   585      * MethodType genericType = type.generic();
       
   586      * genericType = genericType.insertParameterType(0, MethodHandle.class);
       
   587      * return convertArguments(invoker, genericType);
       
   588      * </pre></blockquote>
       
   589      * @param type the type of target methods which the invoker will apply to
       
   590      * @return a method handle suitable for invoking any method handle of the given type
       
   591      */
       
   592     static public
       
   593     MethodHandle genericInvoker(MethodType type) {
       
   594         return invokers(type).genericInvoker();
       
   595     }
       
   596 
       
   597     /**
       
   598      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
       
   599      * Produce a method handle which will invoke any method handle of the
       
   600      * given type on a standard set of {@code Object} type arguments
       
   601      * and a single trailing {@code Object[]} array.
       
   602      * The resulting invoker will be a method handle with the following
       
   603      * arguments:
       
   604      * <ul>
       
   605      * <li>a single {@code MethodHandle} target
       
   606      * <li>zero or more {@code Object} values (counted by {@code objectArgCount})
       
   607      * <li>an {@code Object[]} array containing more arguments
       
   608      * </ul>
       
   609      * The invoker will spread the varargs array, apply
   571      * reference casts as necessary, and unbox primitive arguments.
   610      * reference casts as necessary, and unbox primitive arguments.
   572      * The return value of the invoker will be an {@code Object} reference,
   611      * The return value of the invoker will be an {@code Object} reference,
   573      * boxing a primitive value if the original type returns a primitive,
   612      * boxing a primitive value if the original type returns a primitive,
   574      * and always null if the original type returns void.
   613      * and always null if the original type returns void.
   575      * <p>
   614      * <p>
   576      * This is a convenience method equivalent to the following code:
   615      * This method is equivalent to the following code (though it may be more efficient):
   577      * <pre>
   616      * <p><blockquote><pre>
   578      * MethodHandle invoker = exactInvoker(type);
   617      * MethodHandle invoker = exactInvoker(type);
   579      * MethodType genericType = MethodType.makeGeneric(objectArgCount, varargs);
   618      * MethodType vaType = MethodType.makeGeneric(objectArgCount, true);
   580      * genericType = genericType.insertParameterType(0, MethodHandle.class);
   619      * vaType = vaType.insertParameterType(0, MethodHandle.class);
   581      * if (!varargs)
   620      * return spreadArguments(invoker, vaType);
   582      *     return convertArguments(invoker, genericType);
   621      * </pre></blockquote>
   583      * else
       
   584      *     return spreadArguments(invoker, genericType);
       
   585      * </pre>
       
   586      * @param type the desired target type
   622      * @param type the desired target type
   587      * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
   623      * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
   588      * @param varargs if true, the invoker will accept a final {@code Object[]} argument
       
   589      * @return a method handle suitable for invoking any method handle of the given type
   624      * @return a method handle suitable for invoking any method handle of the given type
   590      */
   625      */
   591     static public
   626     static public
   592     MethodHandle genericInvoker(MethodType type, int objectArgCount, boolean varargs) {
   627     MethodHandle varargsInvoker(MethodType type, int objectArgCount) {
   593         return invokers(type).genericInvoker();
   628         if (objectArgCount < 0 || objectArgCount > type.parameterCount())
   594     }
   629             throw new IllegalArgumentException("bad argument count "+objectArgCount);
   595 
   630         return invokers(type).varargsInvoker(objectArgCount);
   596     /**
   631     }
   597      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   632 
   598      * Give a method handle which will take a invoke any method handle of the
   633     /**
       
   634      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
       
   635      * Produce a method handle which will take a invoke any method handle of the
   599      * given type.  The resulting invoker will have a type which is
   636      * given type.  The resulting invoker will have a type which is
   600      * exactly equal to the desired type, except that it will accept
   637      * exactly equal to the desired type, except that it will accept
   601      * an additional leading argument of type {@code MethodHandle}.
   638      * an additional leading argument of type {@code MethodHandle}.
   602      * <p>
   639      * <p>
   603      * This is a convenience method equivalent to the following code:
   640      * This method is equivalent to the following code (though it may be more efficient):
   604      * <pre>
   641      * <p><blockquote><pre>
   605      *     MethodHandles.lookup().findVirtual(MethodHandle.class, "invoke", type);
   642      * lookup().findVirtual(MethodHandle.class, "invoke", type);
   606      * </pre>
   643      * </pre></blockquote>
   607      * @param type the desired target type
   644      * @param type the desired target type
   608      * @return a method handle suitable for invoking any method handle of the given type
   645      * @return a method handle suitable for invoking any method handle of the given type
   609      */
   646      */
   610     static public
   647     static public
   611     MethodHandle exactInvoker(MethodType type) {
   648     MethodHandle exactInvoker(MethodType type) {
   612         return invokers(type).exactInvoker();
   649         return invokers(type).exactInvoker();
   613     }
   650     }
   614 
   651 
   615     static private Invokers invokers(MethodType type) {
   652     /**
       
   653      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
       
   654      * Produce a method handle equivalent to an invokedynamic instruction
       
   655      * which has been linked to the given call site.
       
   656      * Along with {@link Lookup#findVirtual}, {@link Lookup#findStatic},
       
   657      * and {@link Lookup#findSpecial}, this completes the emulation
       
   658      * of the JVM's {@code invoke} instructions.
       
   659      * <p>This method is equivalent to the following code:
       
   660      * <p><blockquote><pre>
       
   661      * MethodHandle getTarget, invoker, result;
       
   662      * getTarget = lookup().bind(site, "getTarget", methodType(MethodHandle.class));
       
   663      * invoker = exactInvoker(site.type());
       
   664      * result = foldArguments(invoker, getTarget)
       
   665      * </pre></blockquote>
       
   666      * @return a method handle which always invokes the call site's target
       
   667      */
       
   668     public static
       
   669     MethodHandle dynamicInvoker(CallSite site) {
       
   670         MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, CallSite.GET_TARGET, site);
       
   671         MethodHandle invoker = exactInvoker(site.type());
       
   672         return foldArguments(invoker, getTarget);
       
   673     }
       
   674 
       
   675     static Invokers invokers(MethodType type) {
   616         return MethodTypeImpl.invokers(IMPL_TOKEN, type);
   676         return MethodTypeImpl.invokers(IMPL_TOKEN, type);
   617     }
   677     }
   618 
   678 
   619     /**
   679     /**
   620      * <em>WORK IN PROGRESS:</em>
   680      * <em>WORK IN PROGRESS:</em>
   686     }
   746     }
   687 
   747 
   688     /// method handle modification (creation from other method handles)
   748     /// method handle modification (creation from other method handles)
   689 
   749 
   690     /**
   750     /**
   691      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
       
   692      * Produce a method handle which adapts the type of the
   751      * Produce a method handle which adapts the type of the
   693      * given method handle to a new type, by pairwise argument conversion,
   752      * given method handle to a new type by pairwise argument conversion.
   694      * and/or varargs conversion.
   753      * The original type and new type must have the same number of arguments.
   695      * The original type and new type must have the same number of
       
   696      * arguments, or else one or both them the must be varargs types.
       
   697      * The resulting method handle is guaranteed to confess a type
   754      * The resulting method handle is guaranteed to confess a type
   698      * which is equal to the desired new type, with any varargs property erased.
   755      * which is equal to the desired new type.
   699      * <p>
   756      * <p>
   700      * If the original type and new type are equal, returns target.
   757      * If the original type and new type are equal, returns target.
   701      * <p>
   758      * <p>
   702      * The following conversions are applied as needed both to
   759      * The following conversions are applied as needed both to
   703      * arguments and return types.  Let T0 and T1 be the differing
   760      * arguments and return types.  Let T0 and T1 be the differing
   704      * new and old parameter types (or old and new return types)
   761      * new and old parameter types (or old and new return types)
   705      * for corresponding values passed by the new and old method types.
   762      * for corresponding values passed by the new and old method types.
   706      * <p>
       
   707      * If an ordinary (non-varargs) parameter of the new type is
       
   708      * to be boxed in a varargs parameter of the old type of type T1[],
       
   709      * then T1 is the element type of the varargs array.
       
   710      * Otherwise, if a varargs parameter of the new type of type T0[]
       
   711      * is to be spread into one or more outgoing old type parameters,
       
   712      * then T0 is the element type of the
       
   713      * If the new type is varargs and the old type is not, the varargs
       
   714      * argument will be checked and must be a non-null array of exactly
       
   715      * the right length.  If there are no parameters in the old type
       
   716      * corresponding to the new varargs parameter, the varargs argument
       
   717      * is also allowed to be null.
       
   718      * <p>
       
   719      * Given those types T0, T1, one of the following conversions is applied
   763      * Given those types T0, T1, one of the following conversions is applied
   720      * if possible:
   764      * if possible:
   721      * <ul>
   765      * <ul>
   722      * <li>If T0 and T1 are references, then a cast to T2 is applied,
   766      * <li>If T0 and T1 are references, and T1 is not an interface type,
   723      *     where T2 is Object if T1 is an interface, else T1.
   767      *     then a cast to T1 is applied.
   724      *     (The types do not need to be related in any particular way.
   768      *     (The types do not need to be related in any particular way.)
   725      *     The treatment of interfaces follows the usage of the bytecode verifier.)
   769      * <li>If T0 and T1 are references, and T1 is an interface type,
       
   770      *     then the value of type T0 is passed as a T1 without a cast.
       
   771      *     (This treatment of interfaces follows the usage of the bytecode verifier.)
   726      * <li>If T0 and T1 are primitives, then a Java casting
   772      * <li>If T0 and T1 are primitives, then a Java casting
   727      *     conversion (JLS 5.5) is applied, if one exists.
   773      *     conversion (JLS 5.5) is applied, if one exists.
   728      * <li>If T0 and T1 are primitives and one is boolean,
   774      * <li>If T0 and T1 are primitives and one is boolean,
   729      *     the boolean is treated as a one-bit unsigned integer.
   775      *     the boolean is treated as a one-bit unsigned integer.
   730      *     (This treatment follows the usage of the bytecode verifier.)
   776      *     (This treatment follows the usage of the bytecode verifier.)
   743      *     T0 must be a wrapper class or a supertype of one.
   789      *     T0 must be a wrapper class or a supertype of one.
   744      *     If T0 is a wrapper class, its primitive value is converted
   790      *     If T0 is a wrapper class, its primitive value is converted
   745      *     if necessary to T1 by one of the preceding conversions.
   791      *     if necessary to T1 by one of the preceding conversions.
   746      *     Otherwise, T0 is converted directly to the wrapper type for T1,
   792      *     Otherwise, T0 is converted directly to the wrapper type for T1,
   747      *     which is then unboxed.
   793      *     which is then unboxed.
   748      * <li>If T1 is void, any returned value is discarded
   794      * <li>If the return type T1 is void, any returned value is discarded
   749      * <li>If T0 is void and T1 a reference, a null value is introduced.
   795      * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
   750      * <li>If T0 is void and T1 a primitive, a zero value is introduced.
   796      * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
   751      * </ul>
   797      * </ul>
   752      * @param target the method handle to invoke after arguments are retyped
   798      * @param target the method handle to invoke after arguments are retyped
   753      * @param newType the expected type of the new method handle
   799      * @param newType the expected type of the new method handle
   754      * @return a method handle which delegates to {@code target} after performing
   800      * @return a method handle which delegates to {@code target} after performing
   755      *           any necessary argument conversions, and arranges for any
   801      *           any necessary argument conversions, and arranges for any
   756      *           necessary return value conversions
   802      *           necessary return value conversions
   757      * @throws WrongMethodTypeException if the conversion cannot be made
   803      * @throws IllegalArgumentException if the conversion cannot be made
       
   804      * @see MethodHandle#asType
   758      */
   805      */
   759     public static
   806     public static
   760     MethodHandle convertArguments(MethodHandle target, MethodType newType) {
   807     MethodHandle convertArguments(MethodHandle target, MethodType newType) {
   761         MethodType oldType = target.type();
   808         MethodType oldType = target.type();
   762         if (oldType.equals(newType))
   809         if (oldType.equals(newType))
   870 
   917 
   871     /**
   918     /**
   872      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   919      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   873      * Produce a method handle which adapts the type of the
   920      * Produce a method handle which adapts the type of the
   874      * given method handle to a new type, by collecting a series of
   921      * given method handle to a new type, by collecting a series of
   875      * trailing arguments into an array.
   922      * trailing arguments as elements to a single argument array.
   876      * The resulting method handle is guaranteed to confess a type
   923      * <p>
   877      * which is equal to the desired new type.
   924      * This method may be used as an inverse to {@link #spreadArguments}.
   878      * <p>
       
   879      * This method is inverse to {@link #spreadArguments}.
       
   880      * The final parameter type of the old type must be an array type T[],
   925      * The final parameter type of the old type must be an array type T[],
   881      * which is the type of what is called the <i>spread</i> argument.
   926      * which is the type of what is called the <i>spread</i> argument.
   882      * The trailing arguments of the new type which correspond to
   927      * The trailing arguments of the new type which correspond to
   883      * the spread argument are all converted to type T and collected
   928      * the spread argument are all converted to type T and collected
   884      * into an array before the original method is called.
   929      * into an array before the original method is called.
   885      * <p>
       
   886      * ISSUE: Unify this with combineArguments.  CollectArguments
       
   887      * is combineArguments with (a) new Object[]{...} as a combiner,
       
   888      * and (b) the combined arguments dropped, in favor of the combined result.
       
   889      * @param target the method handle to invoke after the argument is prepended
   930      * @param target the method handle to invoke after the argument is prepended
   890      * @param newType the expected type of the new method handle
   931      * @param newType the expected type of the new method handle
   891      * @return a new method handle which collects some trailings argument
   932      * @return a new method handle which collects some trailing argument
   892      *         into an array, before calling the original method handle
   933      *         into an array, before calling the original method handle
   893      */
   934      */
   894     public static
   935     public static
   895     MethodHandle collectArguments(MethodHandle target, MethodType newType) {
   936     MethodHandle collectArguments(MethodHandle target, MethodType newType) {
   896         MethodType oldType = target.type();
   937         MethodType oldType = target.type();
   898         int outargs = oldType.parameterCount();
   939         int outargs = oldType.parameterCount();
   899         int collectPos = outargs - 1;
   940         int collectPos = outargs - 1;
   900         int numCollect = (inargs - collectPos);
   941         int numCollect = (inargs - collectPos);
   901         if (collectPos < 0 || numCollect < 0)
   942         if (collectPos < 0 || numCollect < 0)
   902             throw newIllegalArgumentException("wrong number of arguments");
   943             throw newIllegalArgumentException("wrong number of arguments");
   903         return MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos);
   944         MethodHandle res = MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos, null);
   904     }
   945         if (res == null) {
   905 
   946             throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
   906     /**
   947         }
   907      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   948         return res;
   908      * Produce a method handle which calls the original method handle,
   949     }
   909      * after inserting the given argument at the given position.
   950 
   910      * The type of the new method handle will drop the corresponding argument
   951     /**
   911      * type from the original handle's type.
   952      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   912      * <p>
   953      * Produce a method handle which calls the original method handle {@code target},
   913      * The given argument object must match the dropped argument type.
   954      * after inserting the given argument(s) at the given position.
   914      * If the dropped argument type is a primitive, the argument object
   955      * The formal parameters to {@code target} which will be supplied by those
   915      * must be a wrapper, and is unboxed to produce the primitive.
   956      * arguments are called <em>bound parameters</em>, because the new method
       
   957      * will contain bindings for those parameters take from {@code values}.
       
   958      * The type of the new method handle will drop the types for the bound
       
   959      * parameters from the original target type, since the new method handle
       
   960      * will no longer require those arguments to be supplied by its callers.
       
   961      * <p>
       
   962      * Each given argument object must match the corresponding bound parameter type.
       
   963      * If a bound parameter type is a primitive, the argument object
       
   964      * must be a wrapper, and will be unboxed to produce the primitive value.
   916      * <p>
   965      * <p>
   917      * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
   966      * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
   918      * where <i>N</i> is the number of argument types in <i>target</i>,
   967      * where <i>N</i> is the number of argument types in resulting method handle
   919      * meaning to insert the new argument as the first or last (respectively),
   968      * (after bound parameter types are dropped).
   920      * or somewhere in between.
       
   921      * @param target the method handle to invoke after the argument is inserted
   969      * @param target the method handle to invoke after the argument is inserted
   922      * @param pos where to insert the argument (zero for the first)
   970      * @param pos where to insert the argument (zero for the first)
   923      * @param value the argument to insert
   971      * @param values the series of arguments to insert
   924      * @return a new method handle which inserts an additional argument,
   972      * @return a new method handle which inserts an additional argument,
   925      *         before calling the original method handle
   973      *         before calling the original method handle
   926      */
   974      */
   927     public static
   975     public static
   928     MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
   976     MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
       
   977         int insCount = values.length;
   929         MethodType oldType = target.type();
   978         MethodType oldType = target.type();
   930         ArrayList<Class<?>> ptypes =
   979         ArrayList<Class<?>> ptypes =
   931                 new ArrayList<Class<?>>(oldType.parameterList());
   980                 new ArrayList<Class<?>>(oldType.parameterList());
   932         int outargs = oldType.parameterCount();
   981         int outargs = oldType.parameterCount();
   933         int inargs  = outargs - 1;
   982         int inargs  = outargs - insCount;
   934         if (pos < 0 || pos >= outargs)
   983         if (inargs < 0)
       
   984             throw newIllegalArgumentException("too many values to insert");
       
   985         if (pos < 0 || pos > inargs)
   935             throw newIllegalArgumentException("no argument type to append");
   986             throw newIllegalArgumentException("no argument type to append");
   936         Class<?> valueType = ptypes.remove(pos);
   987         MethodHandle result = target;
   937         value = checkValue(valueType, value);
   988         for (int i = 0; i < insCount; i++) {
   938         if (pos == 0 && !valueType.isPrimitive()) {
   989             Object value = values[i];
   939             // At least for now, make bound method handles a special case.
   990             Class<?> valueType = oldType.parameterType(pos+i);
   940             // This lets us get by with minimal JVM support, at the expense
   991             value = checkValue(valueType, value);
   941             // of generating signature-specific adapters as Java bytecodes.
   992             if (pos == 0 && !valueType.isPrimitive()) {
   942             MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, target, value);
   993                 // At least for now, make bound method handles a special case.
   943             if (bmh != null)  return bmh;
   994                 MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, result, value);
   944             // else fall through to general adapter machinery
   995                 if (bmh != null) {
   945         }
   996                     result = bmh;
   946         return MethodHandleImpl.bindArgument(IMPL_TOKEN, target, pos, value);
   997                     continue;
       
   998                 }
       
   999                 // else fall through to general adapter machinery
       
  1000             }
       
  1001             result = MethodHandleImpl.bindArgument(IMPL_TOKEN, result, pos, value);
       
  1002         }
       
  1003         return result;
       
  1004     }
       
  1005 
       
  1006     @Deprecated // "use MethodHandles.insertArguments instead"
       
  1007     public static
       
  1008     MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
       
  1009         return insertArguments(target, pos, value);
   947     }
  1010     }
   948 
  1011 
   949     /**
  1012     /**
   950      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  1013      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   951      * Produce a method handle which calls the original method handle,
  1014      * Produce a method handle which calls the original method handle,
   952      * after dropping the given argument(s) at the given position.
  1015      * after dropping the given argument(s) at the given position.
   953      * The type of the new method handle will insert the given argument
  1016      * The type of the new method handle will insert the given argument
   954      * type(s), at that position, into the original handle's type.
  1017      * type(s), at that position, into the original handle's type.
   955      * <p>
  1018      * <p>
   956      * The <i>pos</i> may range between zero and <i>N-1</i>,
  1019      * The <i>pos</i> may range between zero and <i>N</i>,
   957      * where <i>N</i> is the number of argument types in <i>target</i>,
  1020      * where <i>N</i> is the number of argument types in <i>target</i>,
   958      * meaning to drop the first or last argument (respectively),
  1021      * meaning to drop the first or last argument (respectively),
   959      * or an argument somewhere in between.
  1022      * or an argument somewhere in between.
       
  1023      * <p>
       
  1024      * <b>Example:</b>
       
  1025      * <p><blockquote><pre>
       
  1026      *   MethodHandle cat = MethodHandles.lookup().
       
  1027      *     findVirtual(String.class, "concat", String.class, String.class);
       
  1028      *   System.out.println(cat.&lt;String&gt;invoke("x", "y")); // xy
       
  1029      *   MethodHandle d0 = dropArguments(cat, 0, String.class);
       
  1030      *   System.out.println(d0.&lt;String&gt;invoke("x", "y", "z")); // xy
       
  1031      *   MethodHandle d1 = dropArguments(cat, 1, String.class);
       
  1032      *   System.out.println(d1.&lt;String&gt;invoke("x", "y", "z")); // xz
       
  1033      *   MethodHandle d2 = dropArguments(cat, 2, String.class);
       
  1034      *   System.out.println(d2.&lt;String&gt;invoke("x", "y", "z")); // yz
       
  1035      *   MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
       
  1036      *   System.out.println(d12.&lt;String&gt;invoke("w", "x", "y", "z")); // wz
       
  1037      * </pre></blockquote>
   960      * @param target the method handle to invoke after the argument is dropped
  1038      * @param target the method handle to invoke after the argument is dropped
   961      * @param valueTypes the type(s) of the argument to drop
  1039      * @param valueTypes the type(s) of the argument to drop
   962      * @param pos which argument to drop (zero for the first)
  1040      * @param pos which argument to drop (zero for the first)
   963      * @return a new method handle which drops an argument of the given type,
  1041      * @return a new method handle which drops an argument of the given type,
   964      *         before calling the original method handle
  1042      *         before calling the original method handle
   965      */
  1043      */
   966     public static
  1044     public static
   967     MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
  1045     MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
   968         if (valueTypes.length == 0)  return target;
  1046         if (valueTypes.size() == 0)  return target;
   969         MethodType oldType = target.type();
  1047         MethodType oldType = target.type();
   970         int outargs = oldType.parameterCount();
  1048         int outargs = oldType.parameterCount();
   971         int inargs  = outargs + valueTypes.length;
  1049         int inargs  = outargs + valueTypes.size();
   972         if (pos < 0 || pos >= inargs)
  1050         if (pos < 0 || pos >= inargs)
   973             throw newIllegalArgumentException("no argument type to remove");
  1051             throw newIllegalArgumentException("no argument type to remove");
   974         ArrayList<Class<?>> ptypes =
  1052         ArrayList<Class<?>> ptypes =
   975                 new ArrayList<Class<?>>(oldType.parameterList());
  1053                 new ArrayList<Class<?>>(oldType.parameterList());
   976         ptypes.addAll(pos, Arrays.asList(valueTypes));
  1054         ptypes.addAll(pos, valueTypes);
   977         MethodType newType = MethodType.make(oldType.returnType(), ptypes);
  1055         MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
   978         return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
  1056         return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
       
  1057     }
       
  1058 
       
  1059     public static
       
  1060     MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
       
  1061         return dropArguments(target, pos, Arrays.asList(valueTypes));
       
  1062     }
       
  1063 
       
  1064     /**
       
  1065      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
       
  1066      * Adapt a target method handle {@code target} by pre-processing
       
  1067      * one or more of its arguments, each with its own unary filter function,
       
  1068      * and then calling the target with each pre-processed argument
       
  1069      * replaced by the result of its corresponding filter function.
       
  1070      * <p>
       
  1071      * The pre-processing is performed by one or more method handles,
       
  1072      * specified in the non-null elements of the {@code filters} array.
       
  1073      * (If there are no such elements, the original target is returned.)
       
  1074      * Each filter (that is, each non-null element of {@code filters})
       
  1075      * is applied to the corresponding argument of the adapter.
       
  1076      * <p>
       
  1077      * If a filter {@code F} applies to the {@code N}th argument of
       
  1078      * the method handle, then {@code F} must be a method handle which
       
  1079      * takes exactly one argument.  The type of {@code F}'s sole argument
       
  1080      * replaces the corresponding argument type of the target
       
  1081      * in the resulting adapted method handle.
       
  1082      * The return type of {@code F} must be identical to the corresponding
       
  1083      * parameter type of the target.
       
  1084      * <p>
       
  1085      * It is an error if there are non-null elements of {@code filters}
       
  1086      * which do not correspond to argument positions in the target.
       
  1087      * The actual length of the target array may be any number, it need
       
  1088      * not be the same as the parameter count of the target type.
       
  1089      * (This provides an easy way to filter just the first argument or two
       
  1090      * of a target method handle.)
       
  1091      * <p> Here is pseudocode for the resulting adapter:
       
  1092      * <blockquote><pre>
       
  1093      * // there are N arguments in the A sequence
       
  1094      * T target(A[N]...);
       
  1095      * [i&lt;N] V[i] filter[i](B[i]) = filters[i] ?: identity;
       
  1096      * T adapter(B[N]... b) {
       
  1097      *   A[N] a...;
       
  1098      *   [i&lt;N] a[i] = filter[i](b[i]);
       
  1099      *   return target(a...);
       
  1100      * }
       
  1101      * </pre></blockquote>
       
  1102      * @param target the method handle to invoke after arguments are filtered
       
  1103      * @param filters method handles to call initially on filtered arguments
       
  1104      * @return method handle which incorporates the specified argument filtering logic
       
  1105      * @throws IllegalArgumentException if a non-null element of {@code filters}
       
  1106      *          does not match a corresponding argument type of {@code target}
       
  1107      */
       
  1108     public static
       
  1109     MethodHandle filterArguments(MethodHandle target, MethodHandle... filters) {
       
  1110         MethodType targetType = target.type();
       
  1111         MethodHandle adapter = target;
       
  1112         MethodType adapterType = targetType;
       
  1113         int pos = -1, maxPos = targetType.parameterCount();
       
  1114         for (MethodHandle filter : filters) {
       
  1115             pos += 1;
       
  1116             if (filter == null)  continue;
       
  1117             if (pos >= maxPos)
       
  1118                 throw newIllegalArgumentException("too many filters");
       
  1119             MethodType filterType = filter.type();
       
  1120             if (filterType.parameterCount() != 1
       
  1121                 || filterType.returnType() != targetType.parameterType(pos))
       
  1122                 throw newIllegalArgumentException("target and filter types do not match");
       
  1123             adapterType = adapterType.changeParameterType(pos, filterType.parameterType(0));
       
  1124             adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, pos, filter);
       
  1125         }
       
  1126         MethodType midType = adapter.type();
       
  1127         if (midType != adapterType)
       
  1128             adapter = MethodHandleImpl.convertArguments(IMPL_TOKEN, adapter, adapterType, midType, null);
       
  1129         return adapter;
       
  1130     }
       
  1131 
       
  1132     /**
       
  1133      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
       
  1134      * Adapt a target method handle {@code target} by pre-processing
       
  1135      * some of its arguments, and then calling the target with
       
  1136      * the result of the pre-processing, plus all original arguments.
       
  1137      * <p>
       
  1138      * The pre-processing is performed by a second method handle, the {@code combiner}.
       
  1139      * The first {@code N} arguments passed to the adapter,
       
  1140      * are copied to the combiner, which then produces a result.
       
  1141      * (Here, {@code N} is defined as the parameter count of the adapter.)
       
  1142      * After this, control passes to the {@code target}, with both the result
       
  1143      * of the combiner, and all the original incoming arguments.
       
  1144      * <p>
       
  1145      * The first argument type of the target must be identical with the
       
  1146      * return type of the combiner.
       
  1147      * The resulting adapter is the same type as the target, except that the
       
  1148      * initial argument type of the target is dropped.
       
  1149      * <p>
       
  1150      * (Note that {@link #dropArguments} can be used to remove any arguments
       
  1151      * that either the {@code combiner} or {@code target} does not wish to receive.
       
  1152      * If some of the incoming arguments are destined only for the combiner,
       
  1153      * consider using {@link #collectArguments} instead, since those
       
  1154      * arguments will not need to be live on the stack on entry to the
       
  1155      * target.)
       
  1156      * <p>
       
  1157      * The first argument of the target must be identical with the
       
  1158      * return value of the combiner.
       
  1159      * <p> Here is pseudocode for the resulting adapter:
       
  1160      * <blockquote><pre>
       
  1161      * // there are N arguments in the A sequence
       
  1162      * T target(V, A[N]..., B...);
       
  1163      * V combiner(A...);
       
  1164      * T adapter(A... a, B... b) {
       
  1165      *   V v = combiner(a...);
       
  1166      *   return target(v, a..., b...);
       
  1167      * }
       
  1168      * </pre></blockquote>
       
  1169      * @param target the method handle to invoke after arguments are combined
       
  1170      * @param combiner method handle to call initially on the incoming arguments
       
  1171      * @return method handle which incorporates the specified argument folding logic
       
  1172      * @throws IllegalArgumentException if the first argument type of
       
  1173      *          {@code target} is not the same as {@code combiner}'s return type,
       
  1174      *          or if the next {@code foldArgs} argument types of {@code target}
       
  1175      *          are not identical with the argument types of {@code combiner}
       
  1176      */
       
  1177     public static
       
  1178     MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
       
  1179         MethodType targetType = target.type();
       
  1180         MethodType combinerType = combiner.type();
       
  1181         int foldArgs = combinerType.parameterCount();
       
  1182         boolean ok = (targetType.parameterCount() >= 1 + foldArgs);
       
  1183         if (!ok)
       
  1184             throw misMatchedTypes("target and combiner types", targetType, combinerType);
       
  1185         MethodType newType = targetType.dropParameterTypes(0, 1);
       
  1186         return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner);
   979     }
  1187     }
   980 
  1188 
   981     /**
  1189     /**
   982      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  1190      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
   983      * Make a method handle which adapts a target method handle,
  1191      * Make a method handle which adapts a target method handle,
   984      * by guarding it with a test, a boolean-valued method handle.
  1192      * by guarding it with a test, a boolean-valued method handle.
   985      * If the guard fails, a fallback handle is called instead.
  1193      * If the guard fails, a fallback handle is called instead.
   986      * All three method handles must have the same corresponding
  1194      * All three method handles must have the same corresponding
   987      * argument and return types, except that the return type
  1195      * argument and return types, except that the return type
   988      * of the test must be boolean.
  1196      * of the test must be boolean, and the test is allowed
       
  1197      * to have fewer arguments than the other two method handles.
   989      * <p> Here is pseudocode for the resulting adapter:
  1198      * <p> Here is pseudocode for the resulting adapter:
   990      * <blockquote><pre>
  1199      * <blockquote><pre>
   991      * signature T(A...);
       
   992      * boolean test(A...);
  1200      * boolean test(A...);
   993      * T target(A...);
  1201      * T target(A...,B...);
   994      * T fallback(A...);
  1202      * T fallback(A...,B...);
   995      * T adapter(A... a) {
  1203      * T adapter(A... a,B... b) {
   996      *   if (test(a...))
  1204      *   if (test(a...))
   997      *     return target(a...);
  1205      *     return target(a..., b...);
   998      *   else
  1206      *   else
   999      *     return fallback(a...);
  1207      *     return fallback(a..., b...);
  1000      * }
  1208      * }
  1001      * </pre></blockquote>
  1209      * </pre></blockquote>
  1002      * @param test method handle used for test, must return boolean
  1210      * @param test method handle used for test, must return boolean
  1003      * @param target method handle to call if test passes
  1211      * @param target method handle to call if test passes
  1004      * @param fallback method handle to call if test fails
  1212      * @param fallback method handle to call if test fails
  1009      */
  1217      */
  1010     public static
  1218     public static
  1011     MethodHandle guardWithTest(MethodHandle test,
  1219     MethodHandle guardWithTest(MethodHandle test,
  1012                                MethodHandle target,
  1220                                MethodHandle target,
  1013                                MethodHandle fallback) {
  1221                                MethodHandle fallback) {
  1014         if (target.type() != fallback.type())
  1222         MethodType gtype = test.type();
  1015             throw newIllegalArgumentException("target and fallback types do not match");
  1223         MethodType ttype = target.type();
  1016         if (target.type().changeReturnType(boolean.class) != test.type())
  1224         MethodType ftype = fallback.type();
  1017             throw newIllegalArgumentException("target and test types do not match");
  1225         if (ttype != ftype)
       
  1226             throw misMatchedTypes("target and fallback types", ttype, ftype);
       
  1227         MethodType gtype2 = ttype.changeReturnType(boolean.class);
       
  1228         if (gtype2 != gtype) {
       
  1229             if (gtype.returnType() != boolean.class)
       
  1230                 throw newIllegalArgumentException("guard type is not a predicate "+gtype);
       
  1231             int gpc = gtype.parameterCount(), tpc = ttype.parameterCount();
       
  1232             if (gpc < tpc) {
       
  1233                 test = dropArguments(test, gpc, ttype.parameterList().subList(gpc, tpc));
       
  1234                 gtype = test.type();
       
  1235             }
       
  1236             if (gtype2 != gtype)
       
  1237                 throw misMatchedTypes("target and test types", ttype, gtype);
       
  1238         }
  1018         /* {
  1239         /* {
  1019             MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
  1240             MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
  1020             static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
  1241             static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
  1021                 return z ? t : f;
  1242                 return z ? t : f;
  1022             }
  1243             }
  1025                 f = dropArguments(f, 1, initargs);  // ignore 2nd copy of args
  1246                 f = dropArguments(f, 1, initargs);  // ignore 2nd copy of args
  1026                 return combineArguments(f, g);
  1247                 return combineArguments(f, g);
  1027             }
  1248             }
  1028             // choose = \z.(z ? target : fallback)
  1249             // choose = \z.(z ? target : fallback)
  1029             MethodHandle choose = findVirtual(MethodHandles.class, "choose",
  1250             MethodHandle choose = findVirtual(MethodHandles.class, "choose",
  1030                     MethodType.make(boolean.class, MethodHandle.class, MethodHandle.class));
  1251                     MethodType.methodType(boolean.class, MethodHandle.class, MethodHandle.class));
  1031             choose = appendArgument(choose, target);
  1252             choose = appendArgument(choose, target);
  1032             choose = appendArgument(choose, fallback);
  1253             choose = appendArgument(choose, fallback);
  1033             MethodHandle dispatch = compose(choose, test);
  1254             MethodHandle dispatch = compose(choose, test);
  1034             // dispatch = \(a...).(test(a...) ? target : fallback)
  1255             // dispatch = \(a...).(test(a...) ? target : fallback)
  1035             return combineArguments(invoke, dispatch, 0);
  1256             return combineArguments(invoke, dispatch, 0);
  1036             // return \(a...).((test(a...) ? target : fallback).invoke(a...))
  1257             // return \(a...).((test(a...) ? target : fallback).invoke(a...))
  1037         } */
  1258         } */
  1038         return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
  1259         return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
  1039     }
  1260     }
  1040 
  1261 
  1041     /**
  1262     static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
  1042      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  1263         return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
  1043      * Adapt a target method handle {@code target} by first processing
  1264     }
  1044      * its arguments, and then calling the target.
  1265 
  1045      * The initial processing is performed by a second method handle, the {@code combiner}.
  1266     /**
  1046      * After this, control passes to the {@code target}, with the same arguments.
  1267      * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
  1047      * <p>
  1268      * Make a method handle which adapts a target method handle,
  1048      * The return value of the {@code combiner} is inserted into the argument list
  1269      * by running it inside an exception handler.
  1049      * for the {@code target} at the indicated position {@code pos}, if it is non-negative.
  1270      * If the target returns normally, the adapter returns that value.
  1050      * Except for this inserted argument (if any), the argument types of
  1271      * If an exception matching the specified type is thrown, the fallback
  1051      * the target {@code target} and the {@code combiner} must be identical.
  1272      * handle is called instead on the exception, plus the original arguments.
  1052      * <p>
  1273      * <p>
  1053      * (Note that {@link #dropArguments} can be used to remove any arguments
  1274      * The handler must have leading parameter of {@code exType} or a supertype,
  1054      * that either the {@code combiner} or {@code target} does not wish to receive.)
  1275      * followed by arguments which correspond <em>(how? TBD)</em> to
  1055      * <p>
  1276      * all the parameters of the target.
  1056      * The combiner handle must have the same argument types as the
  1277      * The target and handler must return the same type.
  1057      * target handle, but must return {@link MethodHandle} instead of
       
  1058      * the ultimate return type.  The returned method handle, in turn,
       
  1059      * is required to have exactly the given final method type.
       
  1060      * <p> Here is pseudocode for the resulting adapter:
  1278      * <p> Here is pseudocode for the resulting adapter:
  1061      * <blockquote><pre>
  1279      * <blockquote><pre>
  1062      * signature V(A[pos]..., B...);
  1280      * T target(A...);
  1063      * signature T(A[pos]..., V, B...);
  1281      * T handler(ExType, A...);
  1064      * T target(A... a, V v, B... b);
  1282      * T adapter(A... a) {
  1065      * V combiner(A..., B...);
  1283      *   try {
  1066      * T adapter(A... a, B... b) {
  1284      *     return target(a...);
  1067      *   V v = combiner(a..., b...);
  1285      *   } catch (ExType ex) {
  1068      *   return target(a..., v, b...);
  1286      *     return handler(ex, a...);
       
  1287      *   }
  1069      * }
  1288      * }
  1070      * </pre></blockquote>
  1289      * </pre></blockquote>
  1071      * @param target the method handle to invoke after arguments are combined
  1290      * @param target method handle to call
  1072      * @param pos where the return value of {@code combiner} is to
  1291      * @param exType the type of exception which the handler will catch
  1073      *          be inserted as an argument to {@code target}
  1292      * @param handler method handle to call if a matching exception is thrown
  1074      * @param combiner method handle to call initially on the incoming arguments
  1293      * @return method handle which incorporates the specified try/catch logic
  1075      * @return method handle which incorporates the specified dispatch logic
  1294      * @throws IllegalArgumentException if {@code handler} does not accept
  1076      * @throws IllegalArgumentException if {@code combiner} does not itself
  1295      *          the given exception type, or if the method handle types do
  1077      *          return either void or the {@code pos}-th argument of {@code target},
  1296      *          not match in their return types and their
  1078      *          or does not have the same argument types as {@code target}
  1297      *          corresponding parameters
  1079      *          (minus the inserted argument)
  1298      */
  1080      */
  1299     public static
  1081     public static
  1300     MethodHandle catchException(MethodHandle target,
  1082     MethodHandle combineArguments(MethodHandle target, int pos, MethodHandle combiner) {
  1301                                 Class<? extends Throwable> exType,
  1083         MethodType mhType = target.type();
  1302                                 MethodHandle handler) {
  1084         Class<?> combineType = combiner.type().returnType();
  1303         MethodType targetType = target.type();
  1085         MethodType incomingArgs;
  1304         MethodType handlerType = handler.type();
  1086         if (pos < 0) {
  1305         boolean ok = (targetType.parameterCount() ==
  1087             // No inserted argument; target & combiner must have same argument types.
  1306                       handlerType.parameterCount() - 1);
  1088             incomingArgs = mhType;
  1307 //        for (int i = 0; ok && i < numExArgs; i++) {
  1089             if (!incomingArgs.changeReturnType(combineType).equals(combiner.type()))
  1308 //            if (targetType.parameterType(i) != handlerType.parameterType(1+i))
  1090                 throw newIllegalArgumentException("target and combiner types do not match");
  1309 //                ok = false;
  1091         } else {
  1310 //        }
  1092             // Inserted argument.
  1311         if (!ok)
  1093             if (pos >= mhType.parameterCount()
  1312             throw newIllegalArgumentException("target and handler types do not match");
  1094                 || mhType.parameterType(pos) != combineType)
  1313         return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
  1095                 throw newIllegalArgumentException("inserted combiner argument does not match target");
  1314     }
  1096             incomingArgs = mhType.dropParameterType(pos);
  1315 
  1097         }
  1316     /**
  1098         if (!incomingArgs.changeReturnType(combineType).equals(combiner.type())) {
  1317      * Produce a method handle which will throw exceptions of the given {@code exType}.
  1099             throw newIllegalArgumentException("target and combiner types do not match");
  1318      * The method handle will accept a single argument of {@code exType},
  1100         }
  1319      * and immediately throw it as an exception.
  1101         return MethodHandleImpl.combineArguments(IMPL_TOKEN, target, combiner, pos);
  1320      * The method type will nominally specify a return of {@code returnType}.
  1102     }
  1321      * The return type may be anything convenient:  It doesn't matter to the
  1103 
  1322      * method handle's behavior, since it will never return normally.
       
  1323      */
       
  1324     public static
       
  1325     MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
       
  1326         return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
       
  1327     }
       
  1328 
       
  1329     /** Alias for {@link MethodType#methodType}. */
       
  1330     @Deprecated // "use MethodType.methodType instead"
       
  1331     public static MethodType methodType(Class<?> rtype) {
       
  1332         return MethodType.methodType(rtype);
       
  1333     }
       
  1334 
       
  1335     /** Alias for {@link MethodType#methodType}. */
       
  1336     @Deprecated // "use MethodType.methodType instead"
       
  1337     public static MethodType methodType(Class<?> rtype, Class<?> ptype) {
       
  1338         return MethodType.methodType(rtype, ptype);
       
  1339     }
       
  1340 
       
  1341     /** Alias for {@link MethodType#methodType}. */
       
  1342     @Deprecated // "use MethodType.methodType instead"
       
  1343     public static MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
       
  1344         return MethodType.methodType(rtype, ptype0, ptypes);
       
  1345     }
  1104 }
  1346 }