MethodHandles.java 75.2 KB
Newer Older
1
/*
2
 * Copyright 2008-2010 Sun Microsystems, Inc.  All Rights Reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package java.dyn;

import java.lang.reflect.Constructor;
import sun.dyn.Access;
import sun.dyn.MemberName;
import sun.dyn.MethodHandleImpl;
import sun.dyn.util.VerifyAccess;
import sun.dyn.util.Wrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
37
import java.util.List;
38 39 40 41 42 43 44 45 46
import java.util.ArrayList;
import java.util.Arrays;
import sun.dyn.Invokers;
import sun.dyn.MethodTypeImpl;
import sun.reflect.Reflection;
import static sun.dyn.MemberName.newIllegalArgumentException;
import static sun.dyn.MemberName.newNoAccessException;

/**
47 48
 * This class consists exclusively of static methods that operate on or return
 * method handles. They fall into several categories:
49
 * <ul>
50 51 52 53
 * <li>Factory methods which create method handles for methods and fields.
 * <li>Invoker methods which can invoke method handles on dynamically typed arguments and/or varargs arrays.
 * <li>Combinator methods, which combine or transforming pre-existing method handles into new ones.
 * <li>Factory methods which create method handles that emulate other common JVM operations or control flow patterns.
54
 * </ul>
55 56 57 58 59 60 61 62 63 64 65 66 67 68
 * <p>
 * @author John Rose, JSR 292 EG
 */
public class MethodHandles {

    private MethodHandles() { }  // do not instantiate

    private static final Access IMPL_TOKEN = Access.getToken();
    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
    static { MethodHandleImpl.initStatics(); }
    // See IMPL_LOOKUP below.

    //// Method handle creation from ordinary methods.

69 70 71 72 73 74
    /**
     * Return a {@link Lookup lookup object} on the caller,
     * which has the capability to access any method handle that the caller has access to,
     * including direct method handles to private fields and methods.
     * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
     * Do not store it in place where untrusted code can access it.
75
     */
76 77 78 79
    public static Lookup lookup() {
        return new Lookup();
    }

80 81 82 83
    /**
     * Return a {@link Lookup lookup object} which is trusted minimally.
     * It can only be used to create method handles to
     * publicly accessible fields and methods.
84 85 86 87 88
     */
    public static Lookup publicLookup() {
        return Lookup.PUBLIC_LOOKUP;
    }

89
    /**
90 91 92
     * A <em>lookup object</em> is a factory for creating method handles,
     * when the creation requires access checking.
     * Method handles do not perform
93 94
     * access checks when they are called; this is a major difference
     * from reflective {@link Method}, which performs access checking
95 96 97
     * against every caller, on every call.
     * Therefore, method handle access
     * restrictions must be enforced when a method handle is created.
98
     * The caller class against which those restrictions are enforced
99 100
     * is known as the {@linkplain #lookupClass lookup class}.
     * A lookup object embodies an
101 102 103 104 105
     * authenticated lookup class, and can be used to create any number
     * of access-checked method handles, all checked against a single
     * lookup class.
     * <p>
     * A class which needs to create method handles will call
106
     * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
107 108 109 110 111 112 113 114
     * It may then use this factory to create method handles on
     * all of its methods, including private ones.
     * It may also delegate the lookup (e.g., to a metaobject protocol)
     * by passing the {@code Lookup} object to other code.
     * If this other code creates method handles, they will be access
     * checked against the original lookup class, and not with any higher
     * privileges.
     * <p>
115 116 117
     * Access checks only apply to named and reflected methods.
     * Other method handle creation methods, such as
     * {@link #convertArguments MethodHandles.convertArguments},
118 119
     * do not require any access checks, and can be done independently
     * of any lookup class.
120 121
     * <h3>How access errors are handled</h3>
     * A lookup can fail, because
122 123 124 125 126 127 128
     * the containing class is not accessible to the lookup class, or
     * because the desired class member is missing, or because the
     * desired class member is not accessible to the lookup class.
     * It can also fail if a security manager is installed and refuses
     * access.  In any of these cases, an exception will be
     * thrown from the attempted lookup.
     * In general, the conditions under which a method handle may be
129 130 131 132
     * created for a method {@code M} are exactly as restrictive as the conditions
     * under which the lookup class could have compiled a call to {@code M}.
     * At least some of these error conditions are likely to be
     * represented by checked exceptions in the final version of this API.
133 134 135
     */
    public static final
    class Lookup {
136
        /** The class on behalf of whom the lookup is being performed. */
137 138
        private final Class<?> lookupClass;

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
        /** The allowed sorts of members which may be looked up (public, etc.), with STRICT for package. */
        private final int allowedModes;

        private static final int
            PUBLIC    = Modifier.PUBLIC,
            PACKAGE   = Modifier.STRICT,
            PROTECTED = Modifier.PROTECTED,
            PRIVATE   = Modifier.PRIVATE,
            ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE),
            TRUSTED   = -1;

        private static int fixmods(int mods) {
            mods &= (ALL_MODES - PACKAGE);
            return (mods != 0) ? mods : PACKAGE;
        }

155 156 157
        /** Which class is performing the lookup?  It is this class against
         *  which checks are performed for visibility and access permissions.
         *  <p>
158 159
         *  This value is null if and only if this lookup was produced
         *  by {@link MethodHandles#publicLookup}.
160 161 162 163 164
         */
        public Class<?> lookupClass() {
            return lookupClass;
        }

165 166 167 168 169 170 171 172 173 174 175 176 177
        // This is just for calling out to MethodHandleImpl.
        private Class<?> lookupClassOrNull() {
            return (allowedModes == TRUSTED) ? null : lookupClass;
        }

        /** Which types of members can this lookup object produce?
         *  The result is a bit-mask of the modifier bits PUBLIC, PROTECTED, PRIVATE, and STRICT.
         *  The modifier bit STRICT stands in for the (non-existent) package protection mode.
         */
        int lookupModes() {
            return allowedModes & ALL_MODES;
        }

178 179 180 181
        /** Embody the current class (the lookupClass) as a lookup class
         * for method handle creation.
         * Must be called by from a method in this package,
         * which in turn is called by a method not in this package.
182
         * <p>
183 184 185 186
         * Also, don't make it private, lest javac interpose
         * an access$N method.
         */
        Lookup() {
187 188 189
            this(getCallerClassAtEntryPoint(), ALL_MODES);
            // make sure we haven't accidentally picked up a privileged class:
            checkUnprivilegedlookupClass(lookupClass);
190 191 192
        }

        Lookup(Access token, Class<?> lookupClass) {
193 194 195 196 197
            this(lookupClass, ALL_MODES);
            Access.check(token);
        }

        private Lookup(Class<?> lookupClass, int allowedModes) {
198
            this.lookupClass = lookupClass;
199
            this.allowedModes = allowedModes;
200 201 202
        }

        /**
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
         * Create a lookup on the specified new lookup class.
         * The resulting object will report the specified
         * class as its own {@link #lookupClass}.
         * <p>
         * However, the resulting {@code Lookup} object is guaranteed
         * to have no more access capabilities than the original.
         * In particular:<ul>
         * <li>If the new lookup class differs from the old one,
         * protected members will not be accessible by virtue of inheritance.
         * <li>If the new lookup class is in a different package
         * than the old one, protected and default (package) members will not be accessible.
         * <li>If the new lookup class is not within the same package member
         * as the old one, private members will not be accessible.
         * <li>In all cases, public members will continue to be accessible.
         * </ul>
218
         */
219 220 221 222 223 224 225 226 227 228
        public Lookup in(Class<?> requestedLookupClass) {
            requestedLookupClass.getClass();  // null check
            if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
                return new Lookup(requestedLookupClass, ALL_MODES);
            if (requestedLookupClass == this.lookupClass)
                return this;  // keep same capabilities
            int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
            if ((newModes & PACKAGE) != 0
                && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
                newModes &= ~(PACKAGE|PRIVATE);
229
            }
230 231 232 233 234 235
            if ((newModes & PRIVATE) != 0
                && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
                newModes &= ~PRIVATE;
            }
            checkUnprivilegedlookupClass(requestedLookupClass);
            return new Lookup(requestedLookupClass, newModes);
236 237
        }

238 239 240
        // Make sure outer class is initialized first.
        static { IMPL_TOKEN.getClass(); }

241 242 243 244
        /** Version of lookup which is trusted minimally.
         *  It can only be used to create method handles to
         *  publicly accessible members.
         */
245
        static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
246 247

        /** Package-private version of lookup which is trusted. */
248
        static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
249 250 251
        static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }

        private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
252 253
            String name = lookupClass.getName();
            if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
254 255 256
                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
        }

257 258 259 260
        /** Display the name of the class.
         *  If there are restrictions on the access permitted to this lookup,
         *  display those also.
         */
261 262
        @Override
        public String toString() {
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
            String modestr;
            String cname = lookupClass.getName();
            switch (allowedModes) {
            case TRUSTED:
                return "/trusted";
            case PUBLIC:
                modestr = "/public";
                if (lookupClass == Object.class)
                    return modestr;
                break;
            case PUBLIC|PACKAGE:
                return cname + "/package";
            case 0:  // should not happen
                return cname + "/empty";
            case ALL_MODES:
                return cname;
            }
            StringBuilder buf = new StringBuilder(cname);
            if ((allowedModes & PUBLIC) != 0)     buf.append("/public");
            if ((allowedModes & PACKAGE) != 0)    buf.append("/package");
            if ((allowedModes & PROTECTED) != 0)  buf.append("/protected");
            if ((allowedModes & PRIVATE) != 0)    buf.append("/private");
            return buf.toString();
286 287 288 289 290 291 292 293
        }

        // call this from an entry point method in Lookup with extraFrames=0.
        private static Class<?> getCallerClassAtEntryPoint() {
            final int CALLER_DEPTH = 4;
            // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
            // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
            // Note:  This should be the only use of getCallerClass in this file.
294
            assert(Reflection.getCallerClass(CALLER_DEPTH-1) == MethodHandles.class);
295 296 297 298 299 300
            return Reflection.getCallerClass(CALLER_DEPTH);
        }

        /**
         * Produce a method handle for a static method.
         * The type of the method handle will be that of the method.
301 302
         * (Since static methods do not take receivers, there is no
         * additional receiver argument inserted into the method handle type,
303
         * as there would be with {@link #findVirtual} or {@link #findSpecial}.)
304 305 306
         * The method and all its argument types must be accessible to the lookup class.
         * If the method's class has not yet been initialized, that is done
         * immediately, before the method handle is returned.
307
         * @param refc the class from which the method is accessed
308 309 310 311 312 313 314
         * @param name the name of the method
         * @param type the type of the method
         * @return the desired method handle
         * @exception SecurityException <em>TBD</em>
         * @exception NoAccessException if the method does not exist or access checking fails
         */
        public
315 316 317 318
        MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoAccessException {
            MemberName method = resolveOrFail(refc, name, type, true);
            checkMethod(refc, method, true);
            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
319 320 321 322 323
        }

        /**
         * Produce a method handle for a virtual method.
         * The type of the method handle will be that of the method,
324
         * with the receiver type (usually {@code refc}) prepended.
325 326
         * The method and all its argument types must be accessible to the lookup class.
         * <p>
327 328 329 330 331 332 333
         * (<em>BUG NOTE:</em> The type {@code Object} may be prepended instead
         * of the receiver type, if the receiver type is not on the boot class path.
         * This is due to a temporary JVM limitation, in which MethodHandle
         * claims to be unable to access such classes.  To work around this
         * bug, use {@code convertArguments} to normalize the type of the leading
         * argument to a type on the boot class path, such as {@code Object}.)
         * <p>
334 335 336 337 338
         * When called, the handle will treat the first argument as a receiver
         * and dispatch on the receiver's type to determine which method
         * implementation to enter.
         * (The dispatching action is identical with that performed by an
         * {@code invokevirtual} or {@code invokeinterface} instruction.)
339
         * @param refc the class or interface from which the method is accessed
340 341 342 343 344 345
         * @param name the name of the method
         * @param type the type of the method, with the receiver argument omitted
         * @return the desired method handle
         * @exception SecurityException <em>TBD</em>
         * @exception NoAccessException if the method does not exist or access checking fails
         */
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
        public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoAccessException {
            MemberName method = resolveOrFail(refc, name, type, false);
            checkMethod(refc, method, false);
            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
            return restrictProtectedReceiver(method, mh);
        }

        /**
         * Produce a method handle which creates an object and initializes it, using
         * the constructor of the specified type.
         * The parameter types of the method handle will be those of the constructor,
         * while the return type will be a reference to the constructor's class.
         * The constructor and all its argument types must be accessible to the lookup class.
         * If the constructor's class has not yet been initialized, that is done
         * immediately, before the method handle is returned.
         * <p>
         * Note:  The requested type must have a return type of {@code void}.
         * This is consistent with the JVM's treatment of constructor signatures.
         * @param refc the class or interface from which the method is accessed
         * @param type the type of the method, with the receiver argument omitted, and a void return type
         * @return the desired method handle
         * @exception SecurityException <em>TBD</em>
         * @exception NoAccessException if the method does not exist or access checking fails
         */
        public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoAccessException {
            String name = "<init>";
            MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
            assert(ctor.isConstructor());
            checkAccess(refc, ctor);
            MethodHandle rawMH = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
            return MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawMH);
377 378 379 380
        }

        /**
         * Produce an early-bound method handle for a virtual method,
381
         * as if called from an {@code invokespecial}
382
         * instruction from {@code caller}.
383
         * The type of the method handle will be that of the method,
384
         * with a suitably restricted receiver type (such as {@code caller}) prepended.
385
         * The method and all its argument types must be accessible
386 387 388 389 390 391 392 393 394
         * to the caller.
         * <p>
         * When called, the handle will treat the first argument as a receiver,
         * but will not dispatch on the receiver's type.
         * (This direct invocation action is identical with that performed by an
         * {@code invokespecial} instruction.)
         * <p>
         * If the explicitly specified caller class is not identical with the
         * lookup class, a security check TBD is performed.
395 396
         * @param refc the class or interface from which the method is accessed
         * @param name the name of the method (which must not be "&lt;init&gt;")
397 398 399 400 401 402
         * @param type the type of the method, with the receiver argument omitted
         * @param specialCaller the proposed calling class to perform the {@code invokespecial}
         * @return the desired method handle
         * @exception SecurityException <em>TBD</em>
         * @exception NoAccessException if the method does not exist or access checking fails
         */
403
        public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
404
                                        Class<?> specialCaller) throws NoAccessException {
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
            checkSpecialCaller(specialCaller);
            MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
            checkMethod(refc, method, false);
            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
            return restrictReceiver(method, mh, specialCaller);
        }

        /**
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
         * Produce a method handle giving read access to a field.
         * The type of the method handle will have a return type of the field's
         * value type.
         * If the field is static, the method handle will take no arguments.
         * Otherwise, its single argument will be the instance containing
         * the field.
         * Access checking is performed immediately on behalf of the lookup class.
         * @param name the field's name
         * @param type the field's type
         * @param isStatic true if and only if the field is static
         * @return a method handle which can load values from the field
         * @exception NoAccessException if access checking fails
         */
        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException {
            return makeAccessor(refc, name, type, isStatic, false);
        }

        /**
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
         * Produce a method handle giving write access to a reflected field.
         * The type of the method handle will have a void return type.
         * If the field is static, the method handle will take a single
         * argument, of the field's value type, the value to be stored.
         * Otherwise, the two arguments will be the instance containing
         * the field, and the value to be stored.
         * Access checking is performed immediately on behalf of the lookup class.
         * @param name the field's name
         * @param type the field's type
         * @param isStatic true if and only if the field is static
         * @return a method handle which can store values into the reflected field
         * @exception NoAccessException if access checking fails
         */
        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type,
                                       boolean isStatic) throws NoAccessException {
            return makeAccessor(refc, name, type, isStatic, true);
449 450 451 452 453 454 455
        }

        /**
         * Produce an early-bound method handle for a non-static method.
         * The receiver must have a supertype {@code defc} in which a method
         * of the given name and type is accessible to the lookup class.
         * The method and all its argument types must be accessible to the lookup class.
456 457 458 459 460
         * The type of the method handle will be that of the method,
         * without any insertion of an additional receiver parameter.
         * The given receiver will be bound into the method handle,
         * so that every call to the method handle will invoke the
         * requested method on the given receiver.
461
         * <p>
462
         * This is equivalent to the following expression:
463
         * <code>
464
         * {@link #insertArguments insertArguments}({@link #findVirtual findVirtual}(defc, name, type), receiver)
465
         * </code>
466 467 468
         * where {@code defc} is either {@code receiver.getClass()} or a super
         * type of that class, in which the requested method is accessible
         * to the lookup class.
469 470 471 472 473 474 475 476
         * @param receiver the object from which the method is accessed
         * @param name the name of the method
         * @param type the type of the method, with the receiver argument omitted
         * @return the desired method handle
         * @exception SecurityException <em>TBD</em>
         * @exception NoAccessException if the method does not exist or access checking fails
         */
        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
477 478 479 480
            Class<? extends Object> refc = receiver.getClass(); // may get NPE
            MemberName method = resolveOrFail(refc, name, type, false);
            checkMethod(refc, method, false);
            MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
481 482
            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
            if (bmh == null)
483
                throw newNoAccessException(method, lookupClass());
484 485 486 487
            return bmh;
        }

        /**
488
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
489 490 491 492 493 494 495 496 497 498 499 500 501 502
         * Make a direct method handle to <i>m</i>, if the lookup class has permission.
         * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
         * If <i>m</i> is virtual, overriding is respected on every call.
         * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
         * The type of the method handle will be that of the method,
         * with the receiver type prepended (but only if it is non-static).
         * If the method's {@code accessible} flag is not set,
         * access checking is performed immediately on behalf of the lookup class.
         * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
         * @param m the reflected method
         * @return a method handle which can invoke the reflected method
         * @exception NoAccessException if access checking fails
         */
        public MethodHandle unreflect(Method m) throws NoAccessException {
503 504 505 506 507 508
            MemberName method = new MemberName(m);
            assert(method.isMethod());
            if (!m.isAccessible())  checkMethod(method.getDeclaringClass(), method, method.isStatic());
            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
            if (!m.isAccessible())  mh = restrictProtectedReceiver(method, mh);
            return mh;
509 510 511
        }

        /**
512
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
513 514
         * Produce a method handle for a reflected method.
         * It will bypass checks for overriding methods on the receiver,
515
         * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
516
         * The type of the method handle will be that of the method,
517
         * with the special caller type prepended (and <em>not</em> the receiver of the method).
518 519 520 521
         * If the method's {@code accessible} flag is not set,
         * access checking is performed immediately on behalf of the lookup class,
         * as if {@code invokespecial} instruction were being linked.
         * @param m the reflected method
522
         * @param specialCaller the class nominally calling the method
523 524 525 526
         * @return a method handle which can invoke the reflected method
         * @exception NoAccessException if access checking fails
         */
        public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
527 528 529 530 531 532 533
            checkSpecialCaller(specialCaller);
            MemberName method = new MemberName(m);
            assert(method.isMethod());
            // ignore m.isAccessible:  this is a new kind of access
            checkMethod(m.getDeclaringClass(), method, false);
            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
            return restrictReceiver(method, mh, specialCaller);
534 535 536
        }

        /**
537
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
538
         * Produce a method handle for a reflected constructor.
539 540
         * The type of the method handle will be that of the constructor,
         * with the return type changed to the declaring class.
541 542 543 544 545
         * The method handle will perform a {@code newInstance} operation,
         * creating a new instance of the constructor's class on the
         * arguments passed to the method handle.
         * <p>
         * If the constructor's {@code accessible} flag is not set,
546
         * access checking is performed immediately on behalf of the lookup class.
547
         * @param c the reflected constructor
548 549 550
         * @return a method handle which can invoke the reflected constructor
         * @exception NoAccessException if access checking fails
         */
551 552 553 554 555 556
        public MethodHandle unreflectConstructor(Constructor c) throws NoAccessException {
            MemberName ctor = new MemberName(c);
            assert(ctor.isConstructor());
            if (!c.isAccessible())  checkAccess(c.getDeclaringClass(), ctor);
            MethodHandle rawCtor = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
            return MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawCtor);
557 558 559 560 561 562
        }

        /**
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
         * Produce a method handle giving read access to a reflected field.
         * The type of the method handle will have a return type of the field's
563 564 565 566
         * value type.
         * If the field is static, the method handle will take no arguments.
         * Otherwise, its single argument will be the instance containing
         * the field.
567 568 569 570 571 572 573
         * If the method's {@code accessible} flag is not set,
         * access checking is performed immediately on behalf of the lookup class.
         * @param f the reflected field
         * @return a method handle which can load values from the reflected field
         * @exception NoAccessException if access checking fails
         */
        public MethodHandle unreflectGetter(Field f) throws NoAccessException {
574
            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
575 576 577 578 579 580
        }

        /**
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
         * Produce a method handle giving write access to a reflected field.
         * The type of the method handle will have a void return type.
581 582 583 584
         * If the field is static, the method handle will take a single
         * argument, of the field's value type, the value to be stored.
         * Otherwise, the two arguments will be the instance containing
         * the field, and the value to be stored.
585 586 587 588 589 590 591
         * If the method's {@code accessible} flag is not set,
         * access checking is performed immediately on behalf of the lookup class.
         * @param f the reflected field
         * @return a method handle which can store values into the reflected field
         * @exception NoAccessException if access checking fails
         */
        public MethodHandle unreflectSetter(Field f) throws NoAccessException {
592
            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
593 594
        }

595
        /// Helper methods, all package-private.
596

597 598 599 600 601
        MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) {
            checkSymbolicClass(refc);  // do this before attempting to resolve
            int mods = (isStatic ? Modifier.STATIC : 0);
            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
        }
602

603 604 605 606
        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) {
            checkSymbolicClass(refc);  // do this before attempting to resolve
            int mods = (isStatic ? Modifier.STATIC : 0);
            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
607 608
        }

609 610 611 612 613 614
        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
                                 boolean searchSupers, Class<?> specialCaller) {
            checkSymbolicClass(refc);  // do this before attempting to resolve
            int mods = (isStatic ? Modifier.STATIC : 0);
            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller);
        }
615

616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
        void checkSymbolicClass(Class<?> refc) {
            Class<?> caller = lookupClassOrNull();
            if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
                throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller);
        }

        void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) {
            String message;
            if (m.isConstructor())
                message = "expected a method, not a constructor";
            else if (!m.isMethod())
                message = "expected a method";
            else if (wantStatic != m.isStatic())
                message = wantStatic ? "expected a static method" : "expected a non-static method";
            else
                { checkAccess(refc, m); return; }
            throw newNoAccessException(message, m, lookupClass());
        }

        void checkAccess(Class<?> refc, MemberName m) {
            int allowedModes = this.allowedModes;
            if (allowedModes == TRUSTED)  return;
            int mods = m.getModifiers();
            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()))
                return;  // common case
            int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
            if ((requestedModes & allowedModes) != 0
                && VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
                                                   mods, lookupClass()))
                return;
            if (((requestedModes & ~allowedModes) & PROTECTED) != 0
                && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
                // Protected members can also be checked as if they were package-private.
                return;
            throw newNoAccessException(accessFailedMessage(refc, m), m, lookupClass());
        }

        String accessFailedMessage(Class<?> refc, MemberName m) {
            Class<?> defc = m.getDeclaringClass();
            int mods = m.getModifiers();
            if (!VerifyAccess.isClassAccessible(defc, lookupClass()))
                return "class is not public";
            if (refc != defc && !VerifyAccess.isClassAccessible(refc, lookupClass()))
                return "symbolic reference "+refc.getName()+" is not public";
            if (Modifier.isPublic(mods))
                return "access to public member failed";  // (how?)
            else if (allowedModes == PUBLIC)
                return "member is not public";
            if (Modifier.isPrivate(mods))
                return "member is private";
            if (Modifier.isProtected(mods))
                return "member is protected";
            return "member is private to package";
        }

        void checkSpecialCaller(Class<?> specialCaller) {
            if (allowedModes == TRUSTED)  return;
            if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))
                throw newNoAccessException("no private access for invokespecial",
                                           new MemberName(specialCaller), lookupClass());
        }

        MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) {
            // The accessing class only has the right to use a protected member
            // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
            if (!method.isProtected() || method.isStatic()
                || allowedModes == TRUSTED
                || VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass()))
                return mh;
            else
                return restrictReceiver(method, mh, lookupClass());
        }
        MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) {
            assert(!method.isStatic());
            Class<?> defc = method.getDeclaringClass();  // receiver type of mh is too wide
            if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
                throw newNoAccessException("caller class must be a subclass below the method", method, caller);
693
            }
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
            MethodType rawType = mh.type();
            if (rawType.parameterType(0) == caller)  return mh;
            MethodType narrowType = rawType.changeParameterType(0, caller);
            return MethodHandleImpl.convertArguments(IMPL_TOKEN, mh, narrowType, rawType, null);
        }

        MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type,
                                  boolean isStatic, boolean isSetter) throws NoAccessException {
            MemberName field = resolveOrFail(refc, name, type, isStatic);
            if (isStatic != field.isStatic())
                throw newNoAccessException(isStatic
                                           ? "expected a static field"
                                           : "expected a non-static field",
                                           field, lookupClass());
            return makeAccessor(refc, field, false, isSetter);
        }

        MethodHandle makeAccessor(Class<?> refc, MemberName field,
                                  boolean trusted, boolean isSetter) throws NoAccessException {
            assert(field.isField());
            if (trusted)
                return MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
            checkAccess(refc, field);
            MethodHandle mh = MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
            return restrictProtectedReceiver(field, mh);
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
        }
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Produce a method handle giving read access to elements of an array.
     * The type of the method handle will have a return type of the array's
     * element type.  Its first argument will be the array type,
     * and the second will be {@code int}.
     * @param arrayClass an array type
     * @return a method handle which can load values from the given array type
     * @throws  IllegalArgumentException if arrayClass is not an array type
     */
    public static
    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, false);
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Produce a method handle giving write access to elements of an array.
     * The type of the method handle will have a void return type.
     * Its last argument will be the array's element type.
     * The first and second arguments will be the array type and int.
     * @return a method handle which can store values into the array type
     * @throws IllegalArgumentException if arrayClass is not an array type
     */
    public static
    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
    }

    /// method handle invocation (reflective style)

    /**
754
     * @deprecated Alias for MethodHandle.invokeVarargs.
755
     */
756
    @Deprecated
757
    public static
758 759
    Object invokeVarargs(MethodHandle target, Object... arguments) throws Throwable {
        return target.invokeVarargs(arguments);
760 761
    }

762 763 764 765
    /**
     * @deprecated Alias for MethodHandle.invokeVarargs.
     */
    @Deprecated
766
    public static
767 768
    Object invoke(MethodHandle target, Object... arguments) throws Throwable {
        return target.invokeVarargs(arguments);
769 770 771 772
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
773
     * Produce a method handle which will invoke any method handle of the
774
     * given type on a standard set of {@code Object} type arguments.
775
     * The resulting invoker will be a method handle with the following
776 777 778
     * arguments:
     * <ul>
     * <li>a single {@code MethodHandle} target
779
     * <li>zero or more {@code Object} values (one for each argument in {@code type})
780
     * </ul>
781 782
     * The invoker will apply reference casts as necessary and unbox primitive arguments,
     * as if by {@link #convertArguments}.
783 784 785 786
     * The return value of the invoker will be an {@code Object} reference,
     * boxing a primitive value if the original type returns a primitive,
     * and always null if the original type returns void.
     * <p>
787 788
     * This method is equivalent to the following code (though it may be more efficient):
     * <p><blockquote><pre>
789
     * MethodHandle invoker = exactInvoker(type);
790
     * MethodType genericType = type.generic();
791
     * genericType = genericType.insertParameterType(0, MethodHandle.class);
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
     * return convertArguments(invoker, genericType);
     * </pre></blockquote>
     * @param type the type of target methods which the invoker will apply to
     * @return a method handle suitable for invoking any method handle of the given type
     */
    static public
    MethodHandle genericInvoker(MethodType type) {
        return invokers(type).genericInvoker();
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Produce a method handle which will invoke any method handle of the
     * given type on a standard set of {@code Object} type arguments
     * and a single trailing {@code Object[]} array.
     * The resulting invoker will be a method handle with the following
     * arguments:
     * <ul>
     * <li>a single {@code MethodHandle} target
     * <li>zero or more {@code Object} values (counted by {@code objectArgCount})
     * <li>an {@code Object[]} array containing more arguments
     * </ul>
     * The invoker will spread the varargs array, apply
     * reference casts as necessary, and unbox primitive arguments.
     * The return value of the invoker will be an {@code Object} reference,
     * boxing a primitive value if the original type returns a primitive,
     * and always null if the original type returns void.
     * <p>
     * This method is equivalent to the following code (though it may be more efficient):
     * <p><blockquote><pre>
     * MethodHandle invoker = exactInvoker(type);
     * MethodType vaType = MethodType.makeGeneric(objectArgCount, true);
     * vaType = vaType.insertParameterType(0, MethodHandle.class);
     * return spreadArguments(invoker, vaType);
     * </pre></blockquote>
827 828 829 830 831
     * @param type the desired target type
     * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
     * @return a method handle suitable for invoking any method handle of the given type
     */
    static public
832 833 834 835
    MethodHandle varargsInvoker(MethodType type, int objectArgCount) {
        if (objectArgCount < 0 || objectArgCount > type.parameterCount())
            throw new IllegalArgumentException("bad argument count "+objectArgCount);
        return invokers(type).varargsInvoker(objectArgCount);
836 837 838 839
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
840
     * Produce a method handle which will take a invoke any method handle of the
841 842 843 844
     * given type.  The resulting invoker will have a type which is
     * exactly equal to the desired type, except that it will accept
     * an additional leading argument of type {@code MethodHandle}.
     * <p>
845 846 847 848
     * This method is equivalent to the following code (though it may be more efficient):
     * <p><blockquote><pre>
     * lookup().findVirtual(MethodHandle.class, "invoke", type);
     * </pre></blockquote>
849 850 851 852 853 854 855 856
     * @param type the desired target type
     * @return a method handle suitable for invoking any method handle of the given type
     */
    static public
    MethodHandle exactInvoker(MethodType type) {
        return invokers(type).exactInvoker();
    }

857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Produce a method handle equivalent to an invokedynamic instruction
     * which has been linked to the given call site.
     * Along with {@link Lookup#findVirtual}, {@link Lookup#findStatic},
     * and {@link Lookup#findSpecial}, this completes the emulation
     * of the JVM's {@code invoke} instructions.
     * <p>This method is equivalent to the following code:
     * <p><blockquote><pre>
     * MethodHandle getTarget, invoker, result;
     * getTarget = lookup().bind(site, "getTarget", methodType(MethodHandle.class));
     * invoker = exactInvoker(site.type());
     * result = foldArguments(invoker, getTarget)
     * </pre></blockquote>
     * @return a method handle which always invokes the call site's target
     */
    public static
    MethodHandle dynamicInvoker(CallSite site) {
875 876 877 878 879
        MethodHandle getCSTarget = GET_TARGET;
        if (getCSTarget == null)
            GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
                findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
        MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site);
880 881 882
        MethodHandle invoker = exactInvoker(site.type());
        return foldArguments(invoker, getTarget);
    }
883
    private static MethodHandle GET_TARGET = null;  // link this lazily, not eagerly
884 885

    static Invokers invokers(MethodType type) {
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
        return MethodTypeImpl.invokers(IMPL_TOKEN, type);
    }

    /**
     * <em>WORK IN PROGRESS:</em>
     * Perform value checking, exactly as if for an adapted method handle.
     * It is assumed that the given value is either null, of type T0,
     * or (if T0 is primitive) of the wrapper type corresponding to T0.
     * The following checks and conversions are made:
     * <ul>
     * <li>If T0 and T1 are references, then a cast to T1 is applied.
     *     (The types do not need to be related in any particular way.)
     * <li>If T0 and T1 are primitives, then a widening or narrowing
     *     conversion is applied, if one exists.
     * <li>If T0 is a primitive and T1 a reference, and
     *     T0 has a wrapper type TW, a boxing conversion to TW is applied,
     *     possibly followed by a reference conversion.
     *     T1 must be TW or a supertype.
     * <li>If T0 is a reference and T1 a primitive, and
     *     T1 has a wrapper type TW, an unboxing conversion is applied,
     *     possibly preceded by a reference conversion.
     *     T0 must be TW or a supertype.
     * <li>If T1 is void, the return value is discarded
     * <li>If T0 is void and T1 a reference, a null value is introduced.
     * <li>If T0 is void and T1 a primitive, a zero value is introduced.
     * </ul>
     * If the value is discarded, null will be returned.
     * @param valueType
     * @param value
     * @return the value, converted if necessary
     * @throws java.lang.ClassCastException if a cast fails
     */
    static
    <T0, T1> T1 checkValue(Class<T0> t0, Class<T1> t1, Object value)
       throws ClassCastException
    {
        if (t0 == t1) {
            // no conversion needed; just reassert the same type
            if (t0.isPrimitive())
                return Wrapper.asPrimitiveType(t1).cast(value);
            else
                return Wrapper.OBJECT.cast(value, t1);
        }
        boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
        if (!prim0) {
            // check contract with caller
            Wrapper.OBJECT.cast(value, t0);
            if (!prim1) {
                return Wrapper.OBJECT.cast(value, t1);
            }
            // convert reference to primitive by unboxing
            Wrapper w1 = Wrapper.forPrimitiveType(t1);
            return w1.cast(value, t1);
        }
        // check contract with caller:
        Wrapper.asWrapperType(t0).cast(value);
        Wrapper w1 = Wrapper.forPrimitiveType(t1);
        return w1.cast(value, t1);
    }

    static
    Object checkValue(Class<?> T1, Object value)
       throws ClassCastException
    {
        Class<?> T0;
        if (value == null)
            T0 = Object.class;
        else
            T0 = value.getClass();
        return checkValue(T0, T1, value);
    }

    /// method handle modification (creation from other method handles)

    /**
     * Produce a method handle which adapts the type of the
962 963
     * given method handle to a new type by pairwise argument conversion.
     * The original type and new type must have the same number of arguments.
964
     * The resulting method handle is guaranteed to confess a type
965
     * which is equal to the desired new type.
966 967 968 969 970 971 972 973 974 975
     * <p>
     * If the original type and new type are equal, returns target.
     * <p>
     * The following conversions are applied as needed both to
     * arguments and return types.  Let T0 and T1 be the differing
     * new and old parameter types (or old and new return types)
     * for corresponding values passed by the new and old method types.
     * Given those types T0, T1, one of the following conversions is applied
     * if possible:
     * <ul>
976 977 978 979 980 981
     * <li>If T0 and T1 are references, and T1 is not an interface type,
     *     then a cast to T1 is applied.
     *     (The types do not need to be related in any particular way.)
     * <li>If T0 and T1 are references, and T1 is an interface type,
     *     then the value of type T0 is passed as a T1 without a cast.
     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
     * <li>If T0 and T1 are primitives, then a Java casting
     *     conversion (JLS 5.5) is applied, if one exists.
     * <li>If T0 and T1 are primitives and one is boolean,
     *     the boolean is treated as a one-bit unsigned integer.
     *     (This treatment follows the usage of the bytecode verifier.)
     *     A conversion from another primitive type behaves as if
     *     it first converts to byte, and then masks all but the low bit.
     * <li>If T0 is a primitive and T1 a reference, a boxing
     *     conversion is applied if one exists, possibly followed by
     *     an reference conversion to a superclass.
     *     T1 must be a wrapper class or a supertype of one.
     *     If T1 is a wrapper class, T0 is converted if necessary
     *     to T1's primitive type by one of the preceding conversions.
     *     Otherwise, T0 is boxed, and its wrapper converted to T1.
     * <li>If T0 is a reference and T1 a primitive, an unboxing
     *     conversion is applied if one exists, possibly preceded by
     *     a reference conversion to a wrapper class.
     *     T0 must be a wrapper class or a supertype of one.
     *     If T0 is a wrapper class, its primitive value is converted
     *     if necessary to T1 by one of the preceding conversions.
     *     Otherwise, T0 is converted directly to the wrapper type for T1,
     *     which is then unboxed.
1004 1005 1006
     * <li>If the return type T1 is void, any returned value is discarded
     * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
     * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
1007 1008 1009 1010 1011 1012
     * </ul>
     * @param target the method handle to invoke after arguments are retyped
     * @param newType the expected type of the new method handle
     * @return a method handle which delegates to {@code target} after performing
     *           any necessary argument conversions, and arranges for any
     *           necessary return value conversions
1013 1014
     * @throws IllegalArgumentException if the conversion cannot be made
     * @see MethodHandle#asType
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
     */
    public static
    MethodHandle convertArguments(MethodHandle target, MethodType newType) {
        MethodType oldType = target.type();
        if (oldType.equals(newType))
            return target;
        MethodHandle res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
                                                 newType, oldType, null);
        if (res == null)
            throw newIllegalArgumentException("cannot convert to "+newType+": "+target);
        return res;
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Produce a method handle which adapts the calling sequence of the
     * given method handle to a new type, by reordering the arguments.
     * The resulting method handle is guaranteed to confess a type
     * which is equal to the desired new type.
     * <p>
     * The given array controls the reordering.
     * Call {@code #I} the number of incoming parameters (the value
     * {@code newType.parameterCount()}, and call {@code #O} the number
     * of outgoing parameters (the value {@code target.type().parameterCount()}).
     * Then the length of the reordering array must be {@code #O},
     * and each element must be a non-negative number less than {@code #I}.
     * For every {@code N} less than {@code #O}, the {@code N}-th
     * outgoing argument will be taken from the {@code I}-th incoming
     * argument, where {@code I} is {@code reorder[N]}.
     * <p>
     * The reordering array need not specify an actual permutation.
     * An incoming argument will be duplicated if its index appears
     * more than once in the array, and an incoming argument will be dropped
     * if its index does not appear in the array.
     * <p>
     * Pairwise conversions are applied as needed to arguments and return
     * values, as with {@link #convertArguments}.
     * @param target the method handle to invoke after arguments are reordered
     * @param newType the expected type of the new method handle
     * @param reorder a string which controls the reordering
     * @return a method handle which delegates to {@code target} after performing
     *           any necessary argument motion and conversions, and arranges for any
     *           necessary return value conversions
     */
    public static
    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int[] reorder) {
        MethodType oldType = target.type();
        checkReorder(reorder, newType, oldType);
        return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
                                                 newType, oldType,
                                                 reorder);
    }

    private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
        if (reorder.length == oldType.parameterCount()) {
            int limit = newType.parameterCount();
            boolean bad = false;
            for (int i : reorder) {
                if (i < 0 || i >= limit) {
                    bad = true; break;
                }
            }
            if (!bad)  return;
        }
        throw newIllegalArgumentException("bad reorder array");
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Produce a method handle which adapts the type of the
     * given method handle to a new type, by spreading the final argument.
     * The resulting method handle is guaranteed to confess a type
     * which is equal to the desired new type.
     * <p>
     * The final parameter type of the new type must be an array type T[].
     * This is the type of what is called the <i>spread</i> argument.
     * All other arguments of the new type are called <i>ordinary</i> arguments.
     * <p>
     * The ordinary arguments of the new type are pairwise converted
     * to the initial parameter types of the old type, according to the
     * rules in {@link #convertArguments}.
     * Any additional arguments in the old type
     * are converted from the array element type T,
     * again according to the rules in {@link #convertArguments}.
     * The return value is converted according likewise.
     * <p>
     * The call verifies that the spread argument is in fact an array
     * of exactly the type length, i.e., the excess number of
     * arguments in the old type over the ordinary arguments in the new type.
     * If there are no excess arguments, the spread argument is also
     * allowed to be null.
     * @param target the method handle to invoke after the argument is prepended
     * @param newType the expected type of the new method handle
     * @return a new method handle which spreads its final argument,
     *         before calling the original method handle
     */
    public static
    MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
        MethodType oldType = target.type();
        int inargs  = newType.parameterCount();
        int outargs = oldType.parameterCount();
        int spreadPos = inargs - 1;
        int numSpread = (outargs - spreadPos);
        MethodHandle res = null;
        if (spreadPos >= 0 && numSpread >= 0) {
            res = MethodHandleImpl.spreadArguments(IMPL_TOKEN, target, newType, spreadPos);
        }
        if (res == null) {
            throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
        }
        return res;
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Produce a method handle which adapts the type of the
     * given method handle to a new type, by collecting a series of
1132
     * trailing arguments as elements to a single argument array.
1133
     * <p>
1134
     * This method may be used as an inverse to {@link #spreadArguments}.
1135 1136 1137 1138 1139 1140 1141
     * The final parameter type of the old type must be an array type T[],
     * which is the type of what is called the <i>spread</i> argument.
     * The trailing arguments of the new type which correspond to
     * the spread argument are all converted to type T and collected
     * into an array before the original method is called.
     * @param target the method handle to invoke after the argument is prepended
     * @param newType the expected type of the new method handle
1142
     * @return a new method handle which collects some trailing argument
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
     *         into an array, before calling the original method handle
     */
    public static
    MethodHandle collectArguments(MethodHandle target, MethodType newType) {
        MethodType oldType = target.type();
        int inargs  = newType.parameterCount();
        int outargs = oldType.parameterCount();
        int collectPos = outargs - 1;
        int numCollect = (inargs - collectPos);
        if (collectPos < 0 || numCollect < 0)
            throw newIllegalArgumentException("wrong number of arguments");
1154 1155 1156 1157 1158
        MethodHandle res = MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos, null);
        if (res == null) {
            throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
        }
        return res;
1159 1160 1161 1162
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
1163 1164 1165 1166 1167 1168 1169 1170
     * Produce a method handle which calls the original method handle {@code target},
     * after inserting the given argument(s) at the given position.
     * The formal parameters to {@code target} which will be supplied by those
     * arguments are called <em>bound parameters</em>, because the new method
     * will contain bindings for those parameters take from {@code values}.
     * The type of the new method handle will drop the types for the bound
     * parameters from the original target type, since the new method handle
     * will no longer require those arguments to be supplied by its callers.
1171
     * <p>
1172 1173 1174
     * Each given argument object must match the corresponding bound parameter type.
     * If a bound parameter type is a primitive, the argument object
     * must be a wrapper, and will be unboxed to produce the primitive value.
1175 1176
     * <p>
     * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
1177 1178
     * where <i>N</i> is the number of argument types in resulting method handle
     * (after bound parameter types are dropped).
1179 1180
     * @param target the method handle to invoke after the argument is inserted
     * @param pos where to insert the argument (zero for the first)
1181
     * @param values the series of arguments to insert
1182 1183 1184 1185
     * @return a new method handle which inserts an additional argument,
     *         before calling the original method handle
     */
    public static
1186 1187
    MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
        int insCount = values.length;
1188 1189 1190 1191
        MethodType oldType = target.type();
        ArrayList<Class<?>> ptypes =
                new ArrayList<Class<?>>(oldType.parameterList());
        int outargs = oldType.parameterCount();
1192 1193 1194 1195
        int inargs  = outargs - insCount;
        if (inargs < 0)
            throw newIllegalArgumentException("too many values to insert");
        if (pos < 0 || pos > inargs)
1196
            throw newIllegalArgumentException("no argument type to append");
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211
        MethodHandle result = target;
        for (int i = 0; i < insCount; i++) {
            Object value = values[i];
            Class<?> valueType = oldType.parameterType(pos+i);
            value = checkValue(valueType, value);
            if (pos == 0 && !valueType.isPrimitive()) {
                // At least for now, make bound method handles a special case.
                MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, result, value);
                if (bmh != null) {
                    result = bmh;
                    continue;
                }
                // else fall through to general adapter machinery
            }
            result = MethodHandleImpl.bindArgument(IMPL_TOKEN, result, pos, value);
1212
        }
1213 1214 1215 1216 1217 1218 1219
        return result;
    }

    @Deprecated // "use MethodHandles.insertArguments instead"
    public static
    MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
        return insertArguments(target, pos, value);
1220 1221 1222 1223 1224 1225 1226 1227 1228
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Produce a method handle which calls the original method handle,
     * after dropping the given argument(s) at the given position.
     * The type of the new method handle will insert the given argument
     * type(s), at that position, into the original handle's type.
     * <p>
1229
     * The <i>pos</i> may range between zero and <i>N</i>,
1230 1231 1232
     * where <i>N</i> is the number of argument types in <i>target</i>,
     * meaning to drop the first or last argument (respectively),
     * or an argument somewhere in between.
1233 1234 1235 1236 1237
     * <p>
     * <b>Example:</b>
     * <p><blockquote><pre>
     *   MethodHandle cat = MethodHandles.lookup().
     *     findVirtual(String.class, "concat", String.class, String.class);
1238
     *   System.out.println(cat.&lt;String&gt;invokeExact("x", "y")); // xy
1239
     *   MethodHandle d0 = dropArguments(cat, 0, String.class);
1240
     *   System.out.println(d0.&lt;String&gt;invokeExact("x", "y", "z")); // xy
1241
     *   MethodHandle d1 = dropArguments(cat, 1, String.class);
1242
     *   System.out.println(d1.&lt;String&gt;invokeExact("x", "y", "z")); // xz
1243
     *   MethodHandle d2 = dropArguments(cat, 2, String.class);
1244
     *   System.out.println(d2.&lt;String&gt;invokeExact("x", "y", "z")); // yz
1245
     *   MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
1246
     *   System.out.println(d12.&lt;String&gt;invokeExact("w", "x", "y", "z")); // wz
1247
     * </pre></blockquote>
1248 1249 1250 1251 1252 1253 1254
     * @param target the method handle to invoke after the argument is dropped
     * @param valueTypes the type(s) of the argument to drop
     * @param pos which argument to drop (zero for the first)
     * @return a new method handle which drops an argument of the given type,
     *         before calling the original method handle
     */
    public static
1255 1256
    MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
        if (valueTypes.size() == 0)  return target;
1257 1258
        MethodType oldType = target.type();
        int outargs = oldType.parameterCount();
1259
        int inargs  = outargs + valueTypes.size();
1260 1261 1262 1263
        if (pos < 0 || pos >= inargs)
            throw newIllegalArgumentException("no argument type to remove");
        ArrayList<Class<?>> ptypes =
                new ArrayList<Class<?>>(oldType.parameterList());
1264 1265
        ptypes.addAll(pos, valueTypes);
        MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
1266 1267 1268
        return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
    }

1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398
    public static
    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
        return dropArguments(target, pos, Arrays.asList(valueTypes));
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Adapt a target method handle {@code target} by pre-processing
     * one or more of its arguments, each with its own unary filter function,
     * and then calling the target with each pre-processed argument
     * replaced by the result of its corresponding filter function.
     * <p>
     * The pre-processing is performed by one or more method handles,
     * specified in the non-null elements of the {@code filters} array.
     * (If there are no such elements, the original target is returned.)
     * Each filter (that is, each non-null element of {@code filters})
     * is applied to the corresponding argument of the adapter.
     * <p>
     * If a filter {@code F} applies to the {@code N}th argument of
     * the method handle, then {@code F} must be a method handle which
     * takes exactly one argument.  The type of {@code F}'s sole argument
     * replaces the corresponding argument type of the target
     * in the resulting adapted method handle.
     * The return type of {@code F} must be identical to the corresponding
     * parameter type of the target.
     * <p>
     * It is an error if there are non-null elements of {@code filters}
     * which do not correspond to argument positions in the target.
     * The actual length of the target array may be any number, it need
     * not be the same as the parameter count of the target type.
     * (This provides an easy way to filter just the first argument or two
     * of a target method handle.)
     * <p> Here is pseudocode for the resulting adapter:
     * <blockquote><pre>
     * // there are N arguments in the A sequence
     * T target(A[N]...);
     * [i&lt;N] V[i] filter[i](B[i]) = filters[i] ?: identity;
     * T adapter(B[N]... b) {
     *   A[N] a...;
     *   [i&lt;N] a[i] = filter[i](b[i]);
     *   return target(a...);
     * }
     * </pre></blockquote>
     * @param target the method handle to invoke after arguments are filtered
     * @param filters method handles to call initially on filtered arguments
     * @return method handle which incorporates the specified argument filtering logic
     * @throws IllegalArgumentException if a non-null element of {@code filters}
     *          does not match a corresponding argument type of {@code target}
     */
    public static
    MethodHandle filterArguments(MethodHandle target, MethodHandle... filters) {
        MethodType targetType = target.type();
        MethodHandle adapter = target;
        MethodType adapterType = targetType;
        int pos = -1, maxPos = targetType.parameterCount();
        for (MethodHandle filter : filters) {
            pos += 1;
            if (filter == null)  continue;
            if (pos >= maxPos)
                throw newIllegalArgumentException("too many filters");
            MethodType filterType = filter.type();
            if (filterType.parameterCount() != 1
                || filterType.returnType() != targetType.parameterType(pos))
                throw newIllegalArgumentException("target and filter types do not match");
            adapterType = adapterType.changeParameterType(pos, filterType.parameterType(0));
            adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, pos, filter);
        }
        MethodType midType = adapter.type();
        if (midType != adapterType)
            adapter = MethodHandleImpl.convertArguments(IMPL_TOKEN, adapter, adapterType, midType, null);
        return adapter;
    }

    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Adapt a target method handle {@code target} by pre-processing
     * some of its arguments, and then calling the target with
     * the result of the pre-processing, plus all original arguments.
     * <p>
     * The pre-processing is performed by a second method handle, the {@code combiner}.
     * The first {@code N} arguments passed to the adapter,
     * are copied to the combiner, which then produces a result.
     * (Here, {@code N} is defined as the parameter count of the adapter.)
     * After this, control passes to the {@code target}, with both the result
     * of the combiner, and all the original incoming arguments.
     * <p>
     * The first argument type of the target must be identical with the
     * return type of the combiner.
     * The resulting adapter is the same type as the target, except that the
     * initial argument type of the target is dropped.
     * <p>
     * (Note that {@link #dropArguments} can be used to remove any arguments
     * that either the {@code combiner} or {@code target} does not wish to receive.
     * If some of the incoming arguments are destined only for the combiner,
     * consider using {@link #collectArguments} instead, since those
     * arguments will not need to be live on the stack on entry to the
     * target.)
     * <p>
     * The first argument of the target must be identical with the
     * return value of the combiner.
     * <p> Here is pseudocode for the resulting adapter:
     * <blockquote><pre>
     * // there are N arguments in the A sequence
     * T target(V, A[N]..., B...);
     * V combiner(A...);
     * T adapter(A... a, B... b) {
     *   V v = combiner(a...);
     *   return target(v, a..., b...);
     * }
     * </pre></blockquote>
     * @param target the method handle to invoke after arguments are combined
     * @param combiner method handle to call initially on the incoming arguments
     * @return method handle which incorporates the specified argument folding logic
     * @throws IllegalArgumentException if the first argument type of
     *          {@code target} is not the same as {@code combiner}'s return type,
     *          or if the next {@code foldArgs} argument types of {@code target}
     *          are not identical with the argument types of {@code combiner}
     */
    public static
    MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
        MethodType targetType = target.type();
        MethodType combinerType = combiner.type();
        int foldArgs = combinerType.parameterCount();
        boolean ok = (targetType.parameterCount() >= 1 + foldArgs);
        if (!ok)
            throw misMatchedTypes("target and combiner types", targetType, combinerType);
        MethodType newType = targetType.dropParameterTypes(0, 1);
        return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner);
    }

1399 1400 1401 1402 1403 1404 1405
    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Make a method handle which adapts a target method handle,
     * by guarding it with a test, a boolean-valued method handle.
     * If the guard fails, a fallback handle is called instead.
     * All three method handles must have the same corresponding
     * argument and return types, except that the return type
1406 1407
     * of the test must be boolean, and the test is allowed
     * to have fewer arguments than the other two method handles.
1408 1409 1410
     * <p> Here is pseudocode for the resulting adapter:
     * <blockquote><pre>
     * boolean test(A...);
1411 1412 1413
     * T target(A...,B...);
     * T fallback(A...,B...);
     * T adapter(A... a,B... b) {
1414
     *   if (test(a...))
1415
     *     return target(a..., b...);
1416
     *   else
1417
     *     return fallback(a..., b...);
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
     * }
     * </pre></blockquote>
     * @param test method handle used for test, must return boolean
     * @param target method handle to call if test passes
     * @param fallback method handle to call if test fails
     * @return method handle which incorporates the specified if/then/else logic
     * @throws IllegalArgumentException if {@code test} does not return boolean,
     *          or if all three method types do not match (with the return
     *          type of {@code test} changed to match that of {@code target}).
     */
    public static
    MethodHandle guardWithTest(MethodHandle test,
                               MethodHandle target,
                               MethodHandle fallback) {
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
        MethodType gtype = test.type();
        MethodType ttype = target.type();
        MethodType ftype = fallback.type();
        if (ttype != ftype)
            throw misMatchedTypes("target and fallback types", ttype, ftype);
        MethodType gtype2 = ttype.changeReturnType(boolean.class);
        if (gtype2 != gtype) {
            if (gtype.returnType() != boolean.class)
                throw newIllegalArgumentException("guard type is not a predicate "+gtype);
            int gpc = gtype.parameterCount(), tpc = ttype.parameterCount();
            if (gpc < tpc) {
                test = dropArguments(test, gpc, ttype.parameterList().subList(gpc, tpc));
                gtype = test.type();
            }
            if (gtype2 != gtype)
                throw misMatchedTypes("target and test types", ttype, gtype);
        }
1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
        /* {
            MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
            static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
                return z ? t : f;
            }
            static MethodHandle compose(MethodHandle f, MethodHandle g) {
                Class<?> initargs = g.type().parameterArray();
                f = dropArguments(f, 1, initargs);  // ignore 2nd copy of args
                return combineArguments(f, g);
            }
            // choose = \z.(z ? target : fallback)
            MethodHandle choose = findVirtual(MethodHandles.class, "choose",
1461
                    MethodType.methodType(boolean.class, MethodHandle.class, MethodHandle.class));
1462 1463 1464 1465 1466
            choose = appendArgument(choose, target);
            choose = appendArgument(choose, fallback);
            MethodHandle dispatch = compose(choose, test);
            // dispatch = \(a...).(test(a...) ? target : fallback)
            return combineArguments(invoke, dispatch, 0);
1467
            // return \(a...).((test(a...) ? target : fallback).invokeExact(a...))
1468 1469 1470 1471
        } */
        return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
    }

1472 1473 1474 1475
    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
        return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
    }

1476 1477
    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
1478 1479 1480 1481 1482
     * Make a method handle which adapts a target method handle,
     * by running it inside an exception handler.
     * If the target returns normally, the adapter returns that value.
     * If an exception matching the specified type is thrown, the fallback
     * handle is called instead on the exception, plus the original arguments.
1483
     * <p>
1484 1485 1486 1487
     * The handler must have leading parameter of {@code exType} or a supertype,
     * followed by arguments which correspond <em>(how? TBD)</em> to
     * all the parameters of the target.
     * The target and handler must return the same type.
1488 1489
     * <p> Here is pseudocode for the resulting adapter:
     * <blockquote><pre>
1490 1491 1492 1493 1494 1495 1496 1497
     * T target(A...);
     * T handler(ExType, A...);
     * T adapter(A... a) {
     *   try {
     *     return target(a...);
     *   } catch (ExType ex) {
     *     return handler(ex, a...);
     *   }
1498 1499
     * }
     * </pre></blockquote>
1500 1501 1502 1503 1504 1505 1506 1507
     * @param target method handle to call
     * @param exType the type of exception which the handler will catch
     * @param handler method handle to call if a matching exception is thrown
     * @return method handle which incorporates the specified try/catch logic
     * @throws IllegalArgumentException if {@code handler} does not accept
     *          the given exception type, or if the method handle types do
     *          not match in their return types and their
     *          corresponding parameters
1508 1509
     */
    public static
1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
    MethodHandle catchException(MethodHandle target,
                                Class<? extends Throwable> exType,
                                MethodHandle handler) {
        MethodType targetType = target.type();
        MethodType handlerType = handler.type();
        boolean ok = (targetType.parameterCount() ==
                      handlerType.parameterCount() - 1);
//        for (int i = 0; ok && i < numExArgs; i++) {
//            if (targetType.parameterType(i) != handlerType.parameterType(1+i))
//                ok = false;
//        }
        if (!ok)
            throw newIllegalArgumentException("target and handler types do not match");
        return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
1524 1525
    }

1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537
    /**
     * Produce a method handle which will throw exceptions of the given {@code exType}.
     * The method handle will accept a single argument of {@code exType},
     * and immediately throw it as an exception.
     * The method type will nominally specify a return of {@code returnType}.
     * The return type may be anything convenient:  It doesn't matter to the
     * method handle's behavior, since it will never return normally.
     */
    public static
    MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
        return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
    }
1538
}