MethodHandles.java 98.8 KB
Newer Older
1
/*
J
Merge  
jrose 已提交
2
 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
3 4 5 6
 * 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
7
 * published by the Free Software Foundation.  Oracle designates this
8
 * particular file as subject to the "Classpath" exception as provided
9
 * by Oracle in the LICENSE file that accompanied this code.
10 11 12 13 14 15 16 17 18 19 20
 *
 * 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.
 *
21 22 23
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
24 25 26 27
 */

package java.dyn;

28
import java.lang.reflect.*;
29 30 31
import sun.dyn.Access;
import sun.dyn.MemberName;
import sun.dyn.MethodHandleImpl;
32
import sun.dyn.util.ValueConversions;
33 34
import sun.dyn.util.VerifyAccess;
import sun.dyn.util.Wrapper;
35
import java.util.List;
36 37 38 39 40 41 42 43 44
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;

/**
45 46
 * This class consists exclusively of static methods that operate on or return
 * method handles. They fall into several categories:
47
 * <ul>
48 49 50 51
 * <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.
52
 * </ul>
53 54 55 56 57 58 59 60 61 62 63 64 65 66
 * <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.

67 68 69 70 71 72
    /**
     * 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.
73
     */
74 75 76 77
    public static Lookup lookup() {
        return new Lookup();
    }

78 79 80 81
    /**
     * 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.
82 83 84 85 86 87 88 89
     * <p>
     * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
     * of this lookup object will be {@link java.lang.Object}.
     * <p>
     * The lookup class can be changed to any other class {@code C} using an expression of the form
     * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
     * Since all classes have equal access to public names,
     * such a change would confer no new access rights.
90 91 92 93 94
     */
    public static Lookup publicLookup() {
        return Lookup.PUBLIC_LOOKUP;
    }

95
    /**
96 97 98
     * A <em>lookup object</em> is a factory for creating method handles,
     * when the creation requires access checking.
     * Method handles do not perform
99 100
     * access checks when they are called, but rather when they are created.
     * (This is a major difference
101
     * from reflective {@link Method}, which performs access checking
102
     * against every caller, on every call.)
103 104
     * Therefore, method handle access
     * restrictions must be enforced when a method handle is created.
105
     * The caller class against which those restrictions are enforced
106 107
     * is known as the {@linkplain #lookupClass lookup class}.
     * A lookup object embodies an
108 109 110 111 112
     * 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
113
     * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
114 115 116
     * 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)
117
     * by passing the lookup object to other code.
118 119 120 121
     * If this other code creates method handles, they will be access
     * checked against the original lookup class, and not with any higher
     * privileges.
     * <p>
122 123 124
     * Access checks only apply to named and reflected methods.
     * Other method handle creation methods, such as
     * {@link #convertArguments MethodHandles.convertArguments},
125 126
     * do not require any access checks, and can be done independently
     * of any lookup class.
127 128
     * <h3>How access errors are handled</h3>
     * A lookup can fail, because
129 130 131 132 133 134
     * 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.
135
     * <p>
136
     * In general, the conditions under which a method handle may be
137 138
     * 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}.
139 140
     * <p>
     * In some cases, this access is obtained by the Java compiler by creating
141 142
     * an wrapper method to access a private method of another class
     * in the same top-level declaration.
143
     * For example, a nested class {@code C.D}
144
     * can access private members within other related classes such as
145 146 147 148 149 150 151
     * {@code C}, {@code C.D.E}, or {@code C.B},
     * but the Java compiler may need to generate wrapper methods in
     * those related classes.  In such cases, a {@code Lookup} object on
     * {@code C.E} would be unable to those private members.
     * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
     * which can transform a lookup on {@code C.E} into one on any of those other
     * classes, without special elevation of privilege.
152 153 154
     */
    public static final
    class Lookup {
155
        /** The class on behalf of whom the lookup is being performed. */
156 157
        private final Class<?> lookupClass;

158
        /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
159 160
        private final int allowedModes;

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
        /** A single-bit mask representing {@code public} access,
         *  which may contribute to the result of {@link #lookupModes lookupModes}.
         *  The value, {@code 0x01}, happens to be the same as the value of the
         *  {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
         */
        public static final int PUBLIC = Modifier.PUBLIC;

        /** A single-bit mask representing {@code private} access,
         *  which may contribute to the result of {@link #lookupModes lookupModes}.
         *  The value, {@code 0x02}, happens to be the same as the value of the
         *  {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
         */
        public static final int PRIVATE = Modifier.PRIVATE;

        /** A single-bit mask representing {@code protected} access,
         *  which may contribute to the result of {@link #lookupModes lookupModes}.
         *  The value, {@code 0x04}, happens to be the same as the value of the
         *  {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
         */
        public static final int PROTECTED = Modifier.PROTECTED;

        /** A single-bit mask representing {@code package} access (default access),
         *  which may contribute to the result of {@link #lookupModes lookupModes}.
         *  The value is {@code 0x08}, which does not correspond meaningfully to
         *  any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
         */
        public static final int PACKAGE = Modifier.STATIC;

        private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
        private static final int TRUSTED   = -1;
191 192 193 194 195 196

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

197 198 199
        /** Which class is performing the lookup?  It is this class against
         *  which checks are performed for visibility and access permissions.
         *  <p>
200 201 202 203
         *  The class implies a maximum level of access permission,
         *  but the permissions may be additionally limited by the bitmask
         *  {@link #lookupModes}, which controls whether non-public members
         *  can be accessed.
204 205 206 207 208
         */
        public Class<?> lookupClass() {
            return lookupClass;
        }

209 210 211 212 213 214
        // 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?
215 216 217 218 219
         *  The result is a bit-mask of the bits
         *  {@linkplain #PUBLIC PUBLIC (0x01)},
         *  {@linkplain #PRIVATE PRIVATE (0x02)},
         *  {@linkplain #PROTECTED PROTECTED (0x04)},
         *  and {@linkplain #PACKAGE PACKAGE (0x08)}.
220 221 222 223 224 225 226 227 228 229
         *  <p>
         *  A freshly-created lookup object
         *  on the {@linkplain java.dyn.MethodHandles#lookup() caller's class}
         *  has all possible bits set, since the caller class can access all its own members.
         *  A lookup object on a new lookup class
         *  {@linkplain java.dyn.MethodHandles.Lookup#in created from a previous lookup object}
         *  may have some mode bits set to zero.
         *  The purpose of this is to restrict access via the new lookup object,
         *  so that it can access only names which can be reached by the original
         *  lookup object, and also by the new lookup class.
230
         */
231
        public int lookupModes() {
232 233 234
            return allowedModes & ALL_MODES;
        }

235 236 237 238
        /** 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.
239
         * <p>
240 241 242 243
         * Also, don't make it private, lest javac interpose
         * an access$N method.
         */
        Lookup() {
244 245 246
            this(getCallerClassAtEntryPoint(), ALL_MODES);
            // make sure we haven't accidentally picked up a privileged class:
            checkUnprivilegedlookupClass(lookupClass);
247 248 249
        }

        Lookup(Access token, Class<?> lookupClass) {
250 251 252 253 254
            this(lookupClass, ALL_MODES);
            Access.check(token);
        }

        private Lookup(Class<?> lookupClass, int allowedModes) {
255
            this.lookupClass = lookupClass;
256
            this.allowedModes = allowedModes;
257 258 259
        }

        /**
260 261
         * Create a lookup on the specified new lookup class.
         * The resulting object will report the specified
262
         * class as its own {@link #lookupClass lookupClass}.
263 264 265
         * <p>
         * However, the resulting {@code Lookup} object is guaranteed
         * to have no more access capabilities than the original.
266
         * In particular, access capabilities can be lost as follows:<ul>
267 268
         * <li>If the new lookup class differs from the old one,
         * protected members will not be accessible by virtue of inheritance.
269
         * (Protected members may continue to be accessible because of package sharing.)
270 271 272 273
         * <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.
274 275 276
         * <li>If the new lookup class is not accessible to the old lookup class,
         * then no members, not even public members, will be accessible.
         * (In all other cases, public members will continue to be accessible.)
277
         * </ul>
278
         */
279 280 281 282 283 284 285 286 287 288
        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);
289
            }
290
            // Allow nestmate lookups to be created without special privilege:
291 292 293 294
            if ((newModes & PRIVATE) != 0
                && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
                newModes &= ~PRIVATE;
            }
295 296 297 298 299 300
            if (newModes == PUBLIC
                && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass)) {
                // The requested class it not accessible from the lookup class.
                // No permissions.
                newModes = 0;
            }
301 302
            checkUnprivilegedlookupClass(requestedLookupClass);
            return new Lookup(requestedLookupClass, newModes);
303 304
        }

305 306 307
        // Make sure outer class is initialized first.
        static { IMPL_TOKEN.getClass(); }

308 309 310 311
        /** Version of lookup which is trusted minimally.
         *  It can only be used to create method handles to
         *  publicly accessible members.
         */
312
        static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
313 314

        /** Package-private version of lookup which is trusted. */
315
        static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
316 317 318
        static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }

        private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
319 320
            String name = lookupClass.getName();
            if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
321 322 323
                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
        }

324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
        /**
         * Display the name of the class from which lookups are to be made.
         * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
         * If there are restrictions on the access permitted to this lookup,
         * this is indicated by adding a suffix to the class name, consisting
         * of a slash and a keyword.  The keyword is chosen as follows:
         * <ul>
         * <li>If no access is allowed, the suffix is "/noaccess".
         * <li>If only public access is allowed, the suffix is "/public".
         * <li>If only public and package access are allowed, the suffix is "/package".
         * <li>If only public, package, and private access are allowed, the suffix is "/private".
         * </ul>
         * If none of the above cases apply, it is the case that full
         * access (public, package, private, and protected) is allowed.
         * In this case, no suffix is added.
         * This is true only of an object obtained originally from
         * {@link java.dyn.MethodHandles#lookup() MethodHandles.lookup}.
         * Objects created by {@link java.dyn.MethodHandles.Lookup#in() Lookup#in}
         * always have restricted access, and will display a suffix.
343
         */
344 345
        @Override
        public String toString() {
346 347 348
            String cname = lookupClass.getName();
            switch (allowedModes) {
            case TRUSTED:
349
                return "/trusted";  // internal only
350
            case PUBLIC:
351
                return cname + "/public";
352 353
            case PUBLIC|PACKAGE:
                return cname + "/package";
354 355
            case 0:  // no privileges
                return cname + "/noaccess";
356 357
            case ALL_MODES:
                return cname;
358 359
            default:
                return cname + "/private";
360
            }
361 362 363 364 365 366 367 368
        }

        // 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.
369
            assert(Reflection.getCallerClass(CALLER_DEPTH-1) == MethodHandles.class);
370 371 372 373 374 375
            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.
376 377
         * (Since static methods do not take receivers, there is no
         * additional receiver argument inserted into the method handle type,
378
         * as there would be with {@link #findVirtual} or {@link #findSpecial}.)
379 380 381
         * 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.
382
         * @param refc the class from which the method is accessed
383 384 385 386 387 388
         * @param name the name of the method
         * @param type the type of the method
         * @return the desired method handle
         * @exception NoAccessException if the method does not exist or access checking fails
         */
        public
389 390 391 392
        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());
393 394 395 396 397
        }

        /**
         * Produce a method handle for a virtual method.
         * The type of the method handle will be that of the method,
398
         * with the receiver type (usually {@code refc}) prepended.
399 400 401 402 403 404 405
         * The method and all its argument types must be accessible to the lookup class.
         * <p>
         * When called, the handle will treat the first argument as a receiver
         * and dispatch on the receiver's type to determine which method
         * implementation to enter.
         * (The dispatching action is identical with that performed by an
         * {@code invokevirtual} or {@code invokeinterface} instruction.)
406
         * @param refc the class or interface from which the method is accessed
407 408 409 410 411
         * @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 NoAccessException if the method does not exist or access checking fails
         */
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
        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 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);
442 443 444 445
        }

        /**
         * Produce an early-bound method handle for a virtual method,
446
         * as if called from an {@code invokespecial}
447
         * instruction from {@code caller}.
448
         * The type of the method handle will be that of the method,
449
         * with a suitably restricted receiver type (such as {@code caller}) prepended.
450
         * The method and all its argument types must be accessible
451 452 453 454 455 456 457 458
         * 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
459 460
         * lookup class, or if this lookup object does not have private access
         * privileges, the access fails.
461 462
         * @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;")
463 464 465 466 467
         * @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 NoAccessException if the method does not exist or access checking fails
         */
468
        public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
469
                                        Class<?> specialCaller) throws NoAccessException {
470 471 472 473 474 475 476 477
            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);
        }

        /**
478
         * Produce a method handle giving read access to a non-static field.
479 480
         * The type of the method handle will have a return type of the field's
         * value type.
481
         * The method handle's single argument will be the instance containing
482 483 484 485 486 487 488
         * 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
         * @return a method handle which can load values from the field
         * @exception NoAccessException if access checking fails
         */
489 490
        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
            return makeAccessor(refc, name, type, false, false);
491 492 493
        }

        /**
494
         * Produce a method handle giving write access to a non-static field.
495
         * The type of the method handle will have a void return type.
496
         * The method handle will take two arguments, the instance containing
497
         * the field, and the value to be stored.
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
         * The second argument will be of the field's value type.
         * Access checking is performed immediately on behalf of the lookup class.
         * @param name the field's name
         * @param type the field's type
         * @return a method handle which can store values into the field
         * @exception NoAccessException if access checking fails
         */
        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
            return makeAccessor(refc, name, type, false, true);
        }

        /**
         * Produce a method handle giving read access to a static field.
         * The type of the method handle will have a return type of the field's
         * value type.
         * The method handle will take no arguments.
         * Access checking is performed immediately on behalf of the lookup class.
         * @param name the field's name
         * @param type the field's type
         * @return a method handle which can load values from the field
         * @exception NoAccessException if access checking fails
         */
        public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
            return makeAccessor(refc, name, type, true, false);
        }

        /**
         * Produce a method handle giving write access to a static field.
         * The type of the method handle will have a void return type.
         * The method handle will take a single
         * argument, of the field's value type, the value to be stored.
529 530 531
         * Access checking is performed immediately on behalf of the lookup class.
         * @param name the field's name
         * @param type the field's type
532
         * @return a method handle which can store values into the field
533 534
         * @exception NoAccessException if access checking fails
         */
535 536
        public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
            return makeAccessor(refc, name, type, true, true);
537 538 539 540 541 542 543
        }

        /**
         * 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.
544 545 546 547 548
         * 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.
549
         * <p>
550
         * This is equivalent to the following expression:
551
         * <code>
552
         * {@link #insertArguments insertArguments}({@link #findVirtual findVirtual}(defc, name, type), receiver)
553
         * </code>
554 555 556
         * 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.
557 558 559 560 561 562 563
         * @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 NoAccessException if the method does not exist or access checking fails
         */
        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
564 565 566 567
            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());
568 569
            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
            if (bmh == null)
570
                throw newNoAccessException(method, lookupClass());
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
            return bmh;
        }

        /**
         * 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 {
589 590 591 592 593 594
            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;
595 596 597 598 599
        }

        /**
         * Produce a method handle for a reflected method.
         * It will bypass checks for overriding methods on the receiver,
600
         * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
601
         * The type of the method handle will be that of the method,
602
         * with the special caller type prepended (and <em>not</em> the receiver of the method).
603 604 605 606
         * 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
607
         * @param specialCaller the class nominally calling the method
608 609 610 611
         * @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 {
612 613 614 615 616 617 618
            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);
619 620 621 622
        }

        /**
         * Produce a method handle for a reflected constructor.
623 624
         * The type of the method handle will be that of the constructor,
         * with the return type changed to the declaring class.
625 626 627 628 629
         * 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,
630
         * access checking is performed immediately on behalf of the lookup class.
631
         * @param c the reflected constructor
632 633 634
         * @return a method handle which can invoke the reflected constructor
         * @exception NoAccessException if access checking fails
         */
635 636 637 638 639 640
        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);
641 642 643 644 645
        }

        /**
         * 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
646 647 648 649
         * 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.
650 651 652 653 654 655 656
         * 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 {
657
            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
658 659 660 661 662
        }

        /**
         * Produce a method handle giving write access to a reflected field.
         * The type of the method handle will have a void return type.
663 664 665 666
         * 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.
667 668 669 670 671 672 673
         * 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 {
674
            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
675 676
        }

677
        /// Helper methods, all package-private.
678

679
        MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException {
680 681 682 683
            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());
        }
684

685
        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoAccessException {
686 687 688
            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());
689 690
        }

691
        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
692
                                 boolean searchSupers, Class<?> specialCaller) throws NoAccessException {
693 694 695 696
            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);
        }
697

698
        void checkSymbolicClass(Class<?> refc) throws NoAccessException {
699 700 701 702 703
            Class<?> caller = lookupClassOrNull();
            if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
                throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller);
        }

704
        void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws NoAccessException {
705 706 707 708 709 710 711 712 713 714 715 716
            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());
        }

717
        void checkAccess(Class<?> refc, MemberName m) throws NoAccessException {
718 719 720
            int allowedModes = this.allowedModes;
            if (allowedModes == TRUSTED)  return;
            int mods = m.getModifiers();
721
            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
                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";
746 747
            else if (allowedModes == 0)
                return "attempted member access through a non-public class";
748 749 750 751 752 753 754
            if (Modifier.isPrivate(mods))
                return "member is private";
            if (Modifier.isProtected(mods))
                return "member is protected";
            return "member is private to package";
        }

755 756
        private static final boolean ALLOW_NESTMATE_ACCESS = false;

757
        void checkSpecialCaller(Class<?> specialCaller) throws NoAccessException {
758
            if (allowedModes == TRUSTED)  return;
759 760 761 762
            if ((allowedModes & PRIVATE) == 0
                || (specialCaller != lookupClass()
                    && !(ALLOW_NESTMATE_ACCESS &&
                         VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
763 764 765 766
                throw newNoAccessException("no private access for invokespecial",
                                           new MemberName(specialCaller), lookupClass());
        }

767
        MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws NoAccessException {
768 769 770 771
            // 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
772 773 774
                || method.getDeclaringClass() == lookupClass()
                || (ALLOW_NESTMATE_ACCESS &&
                    VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
775 776 777 778
                return mh;
            else
                return restrictReceiver(method, mh, lookupClass());
        }
779
        MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws NoAccessException {
780 781 782 783
            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);
784
            }
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
            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);
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
        }
    }

    /**
     * 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);
    }

    /**
     * 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)

    /**
843
     * Produce a method handle which will invoke any method handle of the
844
     * given type on a standard set of {@code Object} type arguments.
845
     * The resulting invoker will be a method handle with the following
846 847 848
     * arguments:
     * <ul>
     * <li>a single {@code MethodHandle} target
849
     * <li>zero or more {@code Object} values (one for each argument in {@code type})
850
     * </ul>
851 852 853 854 855 856 857 858 859 860 861 862
     * <p>
     * The invoker will behave like a call to {@link MethodHandle.invokeGeneric} with
     * the indicated {@code type}.
     * That is, if the target is exactly of the given {@code type}, it will behave
     * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle.asType}
     * is used to convert the target to the required {@code type}.
     * <p>
     * The type of the returned invoker will not be the given {@code type}, but rather
     * will have all parameter and return types replaced by {@code Object}.
     * <p>
     * Before invoking its target, the invoker will apply reference casts as
     * necessary and unbox and widen primitive arguments, as if by {@link #convertArguments}.
863 864 865 866
     * 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>
867 868
     * This method is equivalent to the following code (though it may be more efficient):
     * <p><blockquote><pre>
869
     * MethodHandle invoker = lookup().findVirtual(MethodHandle.class, "invokeGeneric", type);
870
     * MethodType genericType = type.generic();
871
     * genericType = genericType.insertParameterType(0, MethodHandle.class);
872
     * return invoker.asType(genericType);
873 874 875 876 877 878 879 880 881 882 883
     * </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();
    }

    /**
     * Produce a method handle which will invoke any method handle of the
884
     * given {@code type} on a standard set of {@code Object} type arguments
885 886 887 888 889 890 891 892
     * 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>
893 894 895 896 897 898 899 900 901 902 903 904 905
     * <p>
     * The invoker will behave like a call to {@link MethodHandle.invokeGeneric} with
     * the indicated {@code type}.
     * That is, if the target is exactly of the given {@code type}, it will behave
     * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle.asType}
     * is used to convert the target to the required {@code type}.
     * <p>
     * The type of the returned invoker will not be the given {@code type}, but rather
     * will have all parameter and return types replaced by {@code Object}, except for
     * the last parameter type, which will be the array type {@code Object[]}.
     * <p>
     * Before invoking its target, the invoker will spread the varargs array, apply
     * reference casts as necessary, and unbox and widen primitive arguments.
906 907 908 909 910 911
     * 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>
912 913
     * MethodHandle invoker = lookup().findVirtual(MethodHandle.class, "invokeGeneric", type);
     * MethodType vaType = MethodType.genericMethodType(objectArgCount, true);
914
     * vaType = vaType.insertParameterType(0, MethodHandle.class);
915 916 917
     * int spreadArgCount = type.parameterCount - objectArgCount;
     * invoker = invoker.asSpreader(Object.class, spreadArgCount);
     * return invoker.asType(vaType);
918
     * </pre></blockquote>
919 920 921 922 923
     * @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
924 925 926 927
    MethodHandle varargsInvoker(MethodType type, int objectArgCount) {
        if (objectArgCount < 0 || objectArgCount > type.parameterCount())
            throw new IllegalArgumentException("bad argument count "+objectArgCount);
        return invokers(type).varargsInvoker(objectArgCount);
928 929 930
    }

    /**
931
     * Produce a method handle which will take a invoke any method handle of the
932 933 934 935
     * 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>
936 937
     * This method is equivalent to the following code (though it may be more efficient):
     * <p><blockquote><pre>
938
     * lookup().findVirtual(MethodHandle.class, "invokeExact", type);
939
     * </pre></blockquote>
940 941 942 943 944 945 946 947
     * @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();
    }

948
    static Invokers invokers(MethodType type) {
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
        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
990
                return Wrapper.OBJECT.convert(value, t1);
991 992 993 994
        }
        boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
        if (!prim0) {
            // check contract with caller
995
            Wrapper.OBJECT.convert(value, t0);
996
            if (!prim1) {
997
                return Wrapper.OBJECT.convert(value, t1);
998 999 1000
            }
            // convert reference to primitive by unboxing
            Wrapper w1 = Wrapper.forPrimitiveType(t1);
1001
            return w1.convert(value, t1);
1002 1003 1004 1005
        }
        // check contract with caller:
        Wrapper.asWrapperType(t0).cast(value);
        Wrapper w1 = Wrapper.forPrimitiveType(t1);
1006
        return w1.convert(value, t1);
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
    }

    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
1025 1026
     * given method handle to a new type by pairwise argument conversion.
     * The original type and new type must have the same number of arguments.
1027
     * The resulting method handle is guaranteed to report a type
1028
     * which is equal to the desired new type.
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
     * <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>
1039
     * <li>If T0 and T1 are references, then a cast to T1 is applied.
1040
     *     (The types do not need to be related in any particular way.)
1041 1042
     * <li>If T0 and T1 are primitives, then a Java method invocation
     *     conversion (JLS 5.3) is applied, if one exists.
1043 1044
     * <li>If T0 is a primitive and T1 a reference, a boxing
     *     conversion is applied if one exists, possibly followed by
1045
     *     a reference conversion to a superclass.
1046 1047
     *     T1 must be a wrapper class or a supertype of one.
     * <li>If T0 is a reference and T1 a primitive, an unboxing
1048 1049 1050
     *     conversion will be applied at runtime, possibly followed
     *     by a Java method invocation conversion (JLS 5.3)
     *     on the primitive value.  (These are the widening conversions.)
1051
     *     T0 must be a wrapper class or a supertype of one.
1052 1053
     *     (In the case where T0 is Object, these are the conversions
     *     allowed by java.lang.reflect.Method.invoke.)
1054 1055 1056
     * <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.
1057 1058 1059 1060 1061 1062
     * </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
1063
     * @throws WrongMethodTypeException if the conversion cannot be made
1064
     * @see MethodHandle#asType
1065
     * @see MethodHandles#explicitCastArguments
1066 1067 1068 1069 1070 1071
     */
    public static
    MethodHandle convertArguments(MethodHandle target, MethodType newType) {
        MethodType oldType = target.type();
        if (oldType.equals(newType))
            return target;
1072 1073 1074 1075 1076 1077
        MethodHandle res = null;
        try {
            res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
                                                    newType, oldType, null);
        } catch (IllegalArgumentException ex) {
        }
1078
        if (res == null)
1079
            throw new WrongMethodTypeException("cannot convert to "+newType+": "+target);
1080 1081 1082 1083
        return res;
    }

    /**
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 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
     * Produce a method handle which adapts the type of the
     * given method handle to a new type by pairwise argument conversion.
     * The original type and new type must have the same number of arguments.
     * The resulting method handle is guaranteed to report a type
     * which is equal to the desired new type.
     * <p>
     * If the original type and new type are equal, returns target.
     * <p>
     * The same conversions are allowed as for {@link #convertArguments convertArguments},
     * and some additional conversions are also applied if those conversions fail.
     * Given types T0, T1, one of the following conversions is applied
     * in addition, if the conversions specified for {@code convertArguments}
     * would be insufficient:
     * <ul>
     * <li>If T0 and T1 are references, and T1 is an interface type,
     *     then the value of type T0 is passed as a T1 without a cast.
     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
     * <li>If T0 and T1 are primitives and one is boolean,
     *     the boolean is treated as a one-bit unsigned integer.
     *     (This treatment follows the usage of the bytecode verifier.)
     *     A conversion from another primitive type behaves as if
     *     it first converts to byte, and then masks all but the low bit.
     * <li>If a primitive value would be converted by {@code convertArguments}
     *     using Java method invocation conversion (JLS 5.3),
     *     Java casting conversion (JLS 5.5) may be used also.
     *     This allows primitives to be narrowed as well as widened.
     * </ul>
     * @param target the method handle to invoke after arguments are retyped
     * @param newType the expected type of the new method handle
     * @return a method handle which delegates to {@code target} after performing
     *           any necessary argument conversions, and arranges for any
     *           necessary return value conversions
     * @throws WrongMethodTypeException if the conversion cannot be made
     * @see MethodHandle#asType
     * @see MethodHandles#convertArguments
     */
    public static
    MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
        return convertArguments(target, newType);  // FIXME!
    }

    /*
      FIXME: Reconcile javadoc with 10/22/2010 EG notes on conversion:

      Both converters arrange for their method handles to convert arguments
      and return values.  The conversion rules are the same for arguments
      and return values, and depend only on source and target types, S and
      T.  The conversions allowed by castConvertArguments are a strict
      superset of those performed by convertArguments.

      In all cases, if S and T are references, a simple checkcast is done.
      If neither S nor T is a primitive, no attempt is made to unbox and
      box.  A failed conversion throws ClassCastException.

      If T is void, the value is dropped.

      For compatibility with reflection, if S is void and T is a reference,
      a null value is produced.

      For compatibility with reflection, if S is a reference and T is a
      primitive, S is first unboxed and then undergoes primitive conversion.
      In the case of 'convertArguments', only assignment conversion is
      performed (no narrowing primitive conversion).

      If S is a primitive, S is boxed, and then the above rules are applied.
      If S and T are both primitives, the boxing will be undetectable; only
      the primitive conversions will be apparent to the user.  The key point
      is that if S is a primitive type, the implementation may box it and
      treat is as Object, without loss of information, or it may use a "fast
      path" which does not use boxing.

      Notwithstanding the rules above, for compatibility with the verifier,
      if T is an interface, it is treated as if it were Object.  [KEEP THIS?]

      Also, for compatibility with the verifier, a boolean may be undergo
      widening or narrowing conversion to any other primitive type.  [KEEP THIS?]
    */

    /**
1163 1164
     * Produce a method handle which adapts the calling sequence of the
     * given method handle to a new type, by reordering the arguments.
1165
     * The resulting method handle is guaranteed to report a type
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177
     * 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>
1178 1179 1180 1181 1182 1183 1184
     * No argument or return value conversions are applied.
     * The type of each incoming argument, as determined by {@code newType},
     * must be identical to the type of the corresponding outgoing argument
     * or arguments in the target method handle.
     * The return type of {@code newType} must be identical to the return
     * type of the original target.
     * <p>
1185 1186 1187 1188
     * 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.
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
     * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
     * incoming arguments which are not mentioned in the reordering array
     * are may be any type, as determined only by {@code newType}.
     * <blockquote><pre>
MethodType intfn1 = MethodType.methodType(int.class, int.class);
MethodType intfn2 = MethodType.methodType(int.class, int.class, int.class);
MethodHandle sub = ... {int x, int y => x-y} ...;
assert(sub.type().equals(intfn2));
MethodHandle sub1 = MethodHandles.permuteArguments(sub, intfn2, 0, 1);
MethodHandle rsub = MethodHandles.permuteArguments(sub, intfn2, 1, 0);
assert((int)rsub.invokeExact(1, 100) == 99);
MethodHandle add = ... {int x, int y => x+y} ...;
assert(add.type().equals(intfn2));
MethodHandle twice = MethodHandles.permuteArguments(add, intfn1, 0, 0);
assert(twice.type().equals(intfn1));
assert((int)twice.invokeExact(21) == 42);
     * </pre></blockquote>
1206 1207 1208
     * @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
1209 1210
     * @return a method handle which delegates to {@code target} after it
     *           drops unused arguments and moves and/or duplicates the other arguments
1211 1212
     */
    public static
1213
    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
        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");
    }

    /**
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246
     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
     * Equivalent to the following code:
     * <p><blockquote><pre>
     * int spreadPos = newType.parameterCount() - 1;
     * Class<?> spreadType = newType.parameterType(spreadPos);
     * int spreadCount = target.type().parameterCount() - spreadPos;
     * MethodHandle adapter = target.asSpreader(spreadType, spreadCount);
     * adapter = adapter.asType(newType);
     * return adapter;
     * </pre></blockquote>
     * @param target the method handle to invoke after argument spreading
1247
     * @param newType the expected type of the new method handle
1248
     * @return a method handle which spreads its final argument,
1249
     *         before calling the original method handle
1250
     * @deprecated Use {@link MethodHandle#asSpreader}
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
     */
    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;
    }

    /**
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
     * <em>METHOD WILL BE REMOVED FOR PFD:</em>
     * Equivalent to the following code:
     * <p><blockquote><pre>
     * int collectPos = target.type().parameterCount() - 1;
     * Class<?> collectType = target.type().parameterType(collectPos);
     * if (!collectType.isArray())  collectType = Object[].class;
     * int collectCount = newType.parameterCount() - collectPos;
     * MethodHandle adapter = target.asCollector(collectType, collectCount);
     * adapter = adapter.asType(newType);
     * return adapter;
     * </pre></blockquote>
     * @param target the method handle to invoke after argument collection
1282
     * @param newType the expected type of the new method handle
1283
     * @return a method handle which collects some trailing argument
1284
     *         into an array, before calling the original method handle
1285
     * @deprecated Use {@link MethodHandle#asCollector} instead.
1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
     */
    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");
1296 1297 1298 1299 1300
        MethodHandle res = MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos, null);
        if (res == null) {
            throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
        }
        return res;
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
     * Produce a method handle of the requested return type which returns the given
     * constant value every time it is invoked.
     * <p>
     * Before the method handle is returned, the passed-in value is converted to the requested type.
     * If the requested type is primitive, widening primitive conversions are attempted,
     * else reference conversions are attempted.
     * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)},
     * unless the type is {@code void}, in which case it is {@code identity(type)}.
     * @param type the return type of the desired method handle
     * @param value the value to return
     * @return a method handle of the given return type and no arguments, which always returns the given value
     * @throws WrongMethodTypeException if the value cannot be converted to the required return type
     */
    public static
    MethodHandle constant(Class<?> type, Object value) {
        if (type.isPrimitive()) {
            if (type == void.class)  return identity(type);
            Wrapper w = Wrapper.forPrimitiveType(type);
            return identity(type).bindTo(w.convert(value, type));
        } else {
            return identity(type).bindTo(type.cast(value));
        }
    }

    /**
     * Produce a method handle of the requested type which returns the given
     * constant value every time it is invoked.
     * <p>
     * Before the method handle is returned, the passed-in value is converted to the requested return type,
     * as if by {@link #explicitCastArguments #explicitCastArguments}.
     * That is, if the return type is primitive, the value is unboxed,
     * and the primitive value is widened and/or narrowed.
     * Otherwise, reference conversions are attempted.
     * @param type the type of the desired method handle
     * @param value the value to return
     * @return a method handle of the given return type and no arguments, which always returns the given value
     * @throws WrongMethodTypeException if the value cannot be converted to the required return type
     */
    public static
    MethodHandle constant(MethodType type, Object value) {
        MethodHandle target = constant(type.returnType(), value);
        int len = type.parameterCount();
        if (len == 0)
            return target.asType(type);
        target = target.asType(type.dropParameterTypes(0, len));
        return dropArguments(target, 0, type.parameterList().subList(0, len));
    }

     /**
      * Produce a method handle which returns its sole argument when invoked.
      * <p>The identity function for {@code void} takes no arguments and returns no values.
      * @param type the type of the sole parameter and return value of the desired method handle
      * @return a unary method handle which accepts and returns the given type
      */
    public static
    MethodHandle identity(Class<?> type) {
        return ValueConversions.identity(type);
    }

     /**
      * Produce a method handle of the requested type which returns its argument when invoked.
      * If the return type differs from the first argument type, the argument will be
      * converted as if by {@link #explicitCastArguments explicitCastArguments}.
1367
      * If there are additional arguments beyond the first, they are discarded.
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
      * <p>The identity function for {@code void} discards all its arguments.
      * @param type the type of the desired method handle
      * @return a method handle of the given type, which always returns its first argument
      * @throws WrongMethodTypeException if the first argument cannot be converted to the required return type
      */
    public static
    MethodHandle identity(MethodType type) {
        MethodHandle target = identity(type.returnType());
        int len = type.parameterCount();
        if (len == 1)
            return explicitCastArguments(target, type);
        if (len == 0)
            throw new IllegalArgumentException("not enough arguments");
        target = explicitCastArguments(target, type.dropParameterTypes(1, len));
        return dropArguments(target, 1, type.parameterList().subList(1, len));
    }

    /**
1386 1387 1388 1389 1390 1391 1392 1393
     * 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.
1394
     * <p>
1395 1396 1397
     * 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.
1398 1399
     * <p>
     * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
1400 1401
     * where <i>N</i> is the number of argument types in resulting method handle
     * (after bound parameter types are dropped).
1402 1403
     * @param target the method handle to invoke after the argument is inserted
     * @param pos where to insert the argument (zero for the first)
1404
     * @param values the series of arguments to insert
1405
     * @return a method handle which inserts an additional argument,
1406
     *         before calling the original method handle
1407
     * @see MethodHandle#bindTo
1408 1409
     */
    public static
1410 1411
    MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
        int insCount = values.length;
1412 1413 1414 1415
        MethodType oldType = target.type();
        ArrayList<Class<?>> ptypes =
                new ArrayList<Class<?>>(oldType.parameterList());
        int outargs = oldType.parameterCount();
1416 1417 1418 1419
        int inargs  = outargs - insCount;
        if (inargs < 0)
            throw newIllegalArgumentException("too many values to insert");
        if (pos < 0 || pos > inargs)
1420
            throw newIllegalArgumentException("no argument type to append");
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
        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);
1436
        }
1437 1438 1439
        return result;
    }

1440 1441 1442 1443 1444 1445
    /**
     * 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>
1446
     * The <i>pos</i> may range between zero and <i>N</i>,
1447 1448 1449
     * 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.
1450 1451 1452
     * <p>
     * <b>Example:</b>
     * <p><blockquote><pre>
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
import static java.dyn.MethodHandles.*;
import static java.dyn.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
MethodHandle d0 = dropArguments(cat, 0, String.class);
assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
MethodHandle d1 = dropArguments(cat, 1, String.class);
assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
MethodHandle d2 = dropArguments(cat, 2, String.class);
assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
1467
     * </pre></blockquote>
1468 1469 1470 1471
     * @param target the method handle to invoke after the arguments are dropped
     * @param valueTypes the type(s) of the argument(s) to drop
     * @param pos position of first argument to drop (zero for the leftmost)
     * @return a method handle which drops arguments of the given types,
1472 1473 1474
     *         before calling the original method handle
     */
    public static
1475 1476
    MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
        if (valueTypes.size() == 0)  return target;
1477 1478
        MethodType oldType = target.type();
        int outargs = oldType.parameterCount();
1479
        int inargs  = outargs + valueTypes.size();
1480 1481 1482 1483
        if (pos < 0 || pos >= inargs)
            throw newIllegalArgumentException("no argument type to remove");
        ArrayList<Class<?>> ptypes =
                new ArrayList<Class<?>>(oldType.parameterList());
1484 1485
        ptypes.addAll(pos, valueTypes);
        MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
1486 1487 1488
        return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
    }

1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503
    /**
     * 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.
     * This method is equivalent to the following code:
     * <code>
     * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
     * </code>
     * @param target the method handle to invoke after the arguments are dropped
     * @param valueTypes the type(s) of the argument(s) to drop
     * @param pos position of first argument to drop (zero for the leftmost)
     * @return a method handle which drops arguments of the given types,
     *         before calling the original method handle
     */
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
    public static
    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
        return dropArguments(target, pos, Arrays.asList(valueTypes));
    }

    /**
     * Adapt a target method handle {@code target} by pre-processing
     * one or more of its arguments, each with its own unary filter function,
     * and then calling the target with each pre-processed argument
     * replaced by the result of its corresponding filter function.
     * <p>
     * The pre-processing is performed by one or more method handles,
1516 1517 1518
     * specified in the elements of the {@code filters} array.
     * (If there are no elements in the array, the original target is returned.)
     * Each filter is applied to the corresponding argument of the adapter.
1519 1520 1521 1522 1523 1524 1525 1526 1527
     * <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>
1528
     * It is an error if there are elements of {@code filters}
1529
     * which do not correspond to argument positions in the target.
1530 1531 1532 1533 1534 1535 1536 1537 1538
     * <b>Example:</b>
     * <p><blockquote><pre>
import static java.dyn.MethodHandles.*;
import static java.dyn.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
MethodHandle upcase = lookup().findVirtual(String.class,
  "toUpperCase", methodType(String.class));
1539
assertEquals("xy", (String) cat.invokeExact("x", "y"));
1540
MethodHandle f0 = filterArguments(cat, 0, upcase);
1541
assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
1542
MethodHandle f1 = filterArguments(cat, 1, upcase);
1543
assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
1544
MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
1545
assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
1546 1547
     * </pre></blockquote>
     * @param target the method handle to invoke after arguments are filtered
1548
     * @param pos the position of the first argument to filter
1549 1550
     * @param filters method handles to call initially on filtered arguments
     * @return method handle which incorporates the specified argument filtering logic
1551 1552
     * @throws IllegalArgumentException if an element of {@code filters} is null or
     *          does not match a corresponding argument type of {@code target} as described above
1553 1554
     */
    public static
1555
    MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
1556 1557 1558
        MethodType targetType = target.type();
        MethodHandle adapter = target;
        MethodType adapterType = targetType;
1559 1560
        int maxPos = targetType.parameterCount();
        int curPos = pos;
1561
        for (MethodHandle filter : filters) {
1562
            if (curPos >= maxPos)
1563 1564 1565
                throw newIllegalArgumentException("too many filters");
            MethodType filterType = filter.type();
            if (filterType.parameterCount() != 1
1566
                || filterType.returnType() != targetType.parameterType(curPos))
1567
                throw newIllegalArgumentException("target and filter types do not match");
1568 1569 1570
            adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0));
            adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, curPos, filter);
            curPos += 1;
1571 1572 1573 1574 1575 1576 1577
        }
        MethodType midType = adapter.type();
        if (midType != adapterType)
            adapter = MethodHandleImpl.convertArguments(IMPL_TOKEN, adapter, adapterType, midType, null);
        return adapter;
    }

1578
    /**
1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606
     * Adapt a target method handle {@code target} by post-processing
     * its return value with a unary filter function.
     * <p>
     * If a filter {@code F} applies to the return value of
     * the target method handle, then {@code F} must be a method handle which
     * takes exactly one argument.  The return type of {@code F}
     * replaces the return type of the target
     * in the resulting adapted method handle.
     * The argument type of {@code F} must be identical to the
     * return type of the target.
     * <b>Example:</b>
     * <p><blockquote><pre>
import static java.dyn.MethodHandles.*;
import static java.dyn.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
MethodHandle length = lookup().findVirtual(String.class,
  "length", methodType(int.class));
System.out.println((String) cat.invokeExact("x", "y")); // xy
MethodHandle f0 = filterReturnValue(cat, length);
System.out.println((int) f0.invokeExact("x", "y")); // 2
     * </pre></blockquote>
     * @param target the method handle to invoke before filtering the return value
     * @param filter method handle to call on the return value
     * @return method handle which incorporates the specified return value filtering logic
     * @throws IllegalArgumentException if {@code filter} is null or
     *          does not match the return type of {@code target} as described above
1607
     */
1608
    public static
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
    MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
        MethodType targetType = target.type();
        MethodType filterType = filter.type();
        if (filterType.parameterCount() != 1
            || filterType.parameterType(0) != targetType.returnType())
            throw newIllegalArgumentException("target and filter types do not match");
        // FIXME: Too many nodes here.
        MethodHandle returner = dropArguments(filter, 0, targetType.parameterList());
        return foldArguments(returner, exactInvoker(target.type()).bindTo(target));
    }

1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
    /**
     * 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>
1637
     * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments
1638 1639
     * 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,
1640
     * consider using {@link MethodHandle#asCollector} instead, since those
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
     * 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,
1661
     *          or if the following argument types of {@code target}
1662 1663 1664 1665 1666 1667 1668 1669
     *          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);
1670 1671 1672 1673
        if (ok && !combinerType.parameterList().equals(targetType.parameterList().subList(1, foldArgs+1)))
            ok = false;
        if (ok && !combinerType.returnType().equals(targetType.parameterType(0)))
            ok = false;
1674 1675 1676 1677 1678 1679
        if (!ok)
            throw misMatchedTypes("target and combiner types", targetType, combinerType);
        MethodType newType = targetType.dropParameterTypes(0, 1);
        return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner);
    }

1680 1681 1682 1683 1684 1685
    /**
     * 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
1686 1687
     * of the test must be boolean, and the test is allowed
     * to have fewer arguments than the other two method handles.
1688 1689 1690
     * <p> Here is pseudocode for the resulting adapter:
     * <blockquote><pre>
     * boolean test(A...);
1691 1692 1693
     * T target(A...,B...);
     * T fallback(A...,B...);
     * T adapter(A... a,B... b) {
1694
     *   if (test(a...))
1695
     *     return target(a..., b...);
1696
     *   else
1697
     *     return fallback(a..., b...);
1698 1699
     * }
     * </pre></blockquote>
1700 1701 1702
     * Note that the test arguments ({@code a...} in the pseudocode) cannot
     * be modified by execution of the test, and so are passed unchanged
     * from the caller to the target or fallback as appropriate.
1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714
     * @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) {
1715 1716 1717
        MethodType gtype = test.type();
        MethodType ttype = target.type();
        MethodType ftype = fallback.type();
1718
        if (!ttype.equals(ftype))
1719
            throw misMatchedTypes("target and fallback types", ttype, ftype);
1720 1721 1722 1723 1724 1725 1726
        if (gtype.returnType() != boolean.class)
            throw newIllegalArgumentException("guard type is not a predicate "+gtype);
        List<Class<?>> targs = ttype.parameterList();
        List<Class<?>> gargs = gtype.parameterList();
        if (!targs.equals(gargs)) {
            int gpc = gargs.size(), tpc = targs.size();
            if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
1727
                throw misMatchedTypes("target and test types", ttype, gtype);
1728 1729
            test = dropArguments(test, gpc, targs.subList(gpc, tpc));
            gtype = test.type();
1730
        }
1731 1732 1733
        return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
    }

1734 1735 1736 1737
    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
        return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
    }

1738
    /**
1739 1740 1741 1742 1743
     * 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.
1744
     * <p>
1745 1746 1747 1748
     * The target and handler must have the same corresponding
     * argument and return types, except that handler may omit trailing arguments
     * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
     * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
1749 1750
     * <p> Here is pseudocode for the resulting adapter:
     * <blockquote><pre>
1751
     * T target(A..., B...);
1752
     * T handler(ExType, A...);
1753
     * T adapter(A... a, B... b) {
1754
     *   try {
1755
     *     return target(a..., b...);
1756 1757 1758
     *   } catch (ExType ex) {
     *     return handler(ex, a...);
     *   }
1759 1760
     * }
     * </pre></blockquote>
1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
     * Note that the saved arguments ({@code a...} in the pseudocode) cannot
     * be modified by execution of the target, and so are passed unchanged
     * from the caller to the handler, if the handler is invoked.
     * <p>
     * The target and handler must return the same type, even if the handler
     * always throws.  (This might happen, for instance, because the handler
     * is simulating a {@code finally} clause).
     * To create such a throwing handler, compose the handler creation logic
     * with {@link #throwException throwException},
     * in order to create a method handle of the correct return type.
1771 1772 1773 1774 1775 1776 1777 1778
     * @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
1779 1780
     */
    public static
1781 1782 1783
    MethodHandle catchException(MethodHandle target,
                                Class<? extends Throwable> exType,
                                MethodHandle handler) {
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
        MethodType ttype = target.type();
        MethodType htype = handler.type();
        if (htype.parameterCount() < 1 ||
            !htype.parameterType(0).isAssignableFrom(exType))
            throw newIllegalArgumentException("handler does not accept exception type "+exType);
        if (htype.returnType() != ttype.returnType())
            throw misMatchedTypes("target and handler return types", ttype, htype);
        List<Class<?>> targs = ttype.parameterList();
        List<Class<?>> hargs = htype.parameterList();
        hargs = hargs.subList(1, hargs.size());  // omit leading parameter from handler
        if (!targs.equals(hargs)) {
            int hpc = hargs.size(), tpc = targs.size();
            if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
                throw misMatchedTypes("target and handler types", ttype, htype);
            handler = dropArguments(handler, hpc, hargs.subList(hpc, tpc));
            htype = handler.type();
        }
1801
        return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
1802 1803
    }

1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815
    /**
     * 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));
    }
1816 1817

    /**
1818
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
1819 1820 1821 1822
     * Produce a wrapper instance of the given "SAM" interface which redirects
     * its calls to the given method handle.
     * A SAM interface is an interface which declares a single abstract method.
     * The type must be public.  (No additional access checks are performed.)
1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833
     * <p>
     * The resulting instance of the required SAM type will respond to
     * invocation of the SAM type's single abstract method by calling
     * the given {@code target} on the incoming arguments,
     * and returning or throwing whatever the {@code target}
     * returns or throws.  The invocation will be as if by
     * {@code target.invokeExact}.
     * <p>
     * The method handle may throw an <em>undeclared exception</em>,
     * which means any checked exception (or other checked throwable)
     * not declared by the SAM type's single abstract method.
1834 1835 1836
     * If this happens, the throwable will be wrapped in an instance of
     * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
     * and thrown in that wrapped form.
1837 1838 1839 1840 1841 1842 1843 1844 1845 1846
     * <p>
     * The wrapper instance is guaranteed to be of a non-public
     * implementation class C in a package containing no classes
     * or methods except system-defined classes and methods.
     * The implementation class C will have no public supertypes
     * or public methods beyond the following:
     * <ul>
     * <li>the SAM type itself and any methods in the SAM type
     * <li>the supertypes of the SAM type (if any) and their methods
     * <li>{@link Object} and its methods
1847
     * <li>{@link java.dyn.AsInstanceObject AsInstanceObject} and its methods</li>
1848 1849
     * </ul>
     * <p>
1850 1851 1852 1853 1854
     * (Note: When determining the unique abstract method of a SAM interface,
     * the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
     * are disregarded.  For example, {@link java.util.Comparator} is a SAM interface,
     * even though it re-declares the {@code Object.equals} method.)
     * <p>
1855 1856 1857 1858 1859
     * No stable mapping is promised between the SAM type and
     * the implementation class C.  Over time, several implementation
     * classes might be used for the same SAM type.
     * <p>
     * This method is not guaranteed to return a distinct
1860 1861 1862
     * wrapper object for each separate call.  If the implementation is able
     * to prove that a wrapper of the required SAM type
     * has already been created for a given
1863
     * method handle, or for another method handle with the
1864
     * same behavior, the implementation may return that wrapper in place of
1865
     * a new wrapper.
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876
     * <p>
     * This method is designed to apply to common use cases
     * where a single method handle must interoperate with
     * a type (class or interface) that implements a function-like
     * API.  Additional variations, such as SAM classes with
     * private constructors, or interfaces with multiple but related
     * entry points, must be covered by hand-written or automatically
     * generated adapter classes.  In those cases, consider implementing
     * {@link java.dyn.MethodHandles.AsInstanceObject AsInstanceObject}
     * in the adapters, so that generic code can extract the underlying
     * method handle without knowing where the SAM adapter came from.
1877 1878 1879 1880 1881 1882 1883 1884
     * @param target the method handle to invoke from the wrapper
     * @param samType the desired type of the wrapper, a SAM type
     * @return a correctly-typed wrapper for the given {@code target}
     * @throws IllegalArgumentException if the {@code target} throws
     *         an undeclared exception
     */
    // ISSUE: Should we delegate equals/hashCode to the targets?
    // Not useful unless there is a stable equals/hashCode behavior
1885
    // for MethodHandle, but there isn't.
1886
    public static
1887
    <T> T asInstance(final MethodHandle target, final Class<T> samType) {
1888 1889 1890 1891 1892 1893
        // POC implementation only; violates the above contract several ways
        final Method sam = getSamMethod(samType);
        if (sam == null)
            throw new IllegalArgumentException("not a SAM type: "+samType.getName());
        MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
        if (!samMT.equals(target.type()))
1894
            throw new IllegalArgumentException("wrong method type: "+target+" should match "+sam);
1895 1896
        return samType.cast(Proxy.newProxyInstance(
                samType.getClassLoader(),
1897
                new Class[]{ samType, AsInstanceObject.class },
1898
                new InvocationHandler() {
1899 1900 1901 1902 1903
                    private Object getArg(String name) {
                        if ((Object)name == "getAsInstanceTarget")  return target;
                        if ((Object)name == "getAsInstanceType")    return samType;
                        throw new AssertionError();
                    }
1904
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
1905 1906
                        if (method.getDeclaringClass() == AsInstanceObject.class)
                            return getArg(method.getName());
1907 1908 1909 1910 1911
                        if (method.equals(sam))
                            return target.invokeVarargs(args);
                        if (isObjectMethod(method))
                            return callObjectMethod(this, method, args);
                        throw new InternalError();
1912 1913 1914 1915
                    }
                }));
    }

1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933
    /**
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     * Interface implemented by every object which is produced by {@link #asInstance asInstance}.
     * The methods of this interface allow a caller to recover the parameters
     * to {@code asInstance}.
     * This allows applications to repeatedly convert between method handles
     * and SAM objects, without the risk of creating unbounded delegation chains.
     */
    public interface AsInstanceObject {
        /** Produce or recover a target method handle which is behaviorally
         *  equivalent to the SAM method of this object.
         */
        public MethodHandle getAsInstanceTarget();
        /** Recover the SAM type for which this object was created.
         */
        public Class<?> getAsInstanceType();
    }

1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964
    private static
    boolean isObjectMethod(Method m) {
        switch (m.getName()) {
        case "toString":
            return (m.getReturnType() == String.class
                    && m.getParameterTypes().length == 0);
        case "hashCode":
            return (m.getReturnType() == int.class
                    && m.getParameterTypes().length == 0);
        case "equals":
            return (m.getReturnType() == boolean.class
                    && m.getParameterTypes().length == 1
                    && m.getParameterTypes()[0] == Object.class);
        }
        return false;
    }

    private static
    Object callObjectMethod(Object self, Method m, Object[] args) {
        assert(isObjectMethod(m)) : m;
        switch (m.getName()) {
        case "toString":
            return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
        case "hashCode":
            return System.identityHashCode(self);
        case "equals":
            return (self == args[0]);
        }
        return null;
    }

1965 1966 1967 1968 1969 1970
    private static
    Method getSamMethod(Class<?> samType) {
        Method sam = null;
        for (Method m : samType.getMethods()) {
            int mod = m.getModifiers();
            if (Modifier.isAbstract(mod)) {
1971
                if (sam != null && !isObjectMethod(sam))
1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991
                    return null;  // too many abstract methods
                sam = m;
            }
        }
        if (!samType.isInterface() && getSamConstructor(samType) == null)
            return null;  // wrong kind of constructor
        return sam;
    }

    private static
    Constructor getSamConstructor(Class<?> samType) {
        for (Constructor c : samType.getDeclaredConstructors()) {
            if (c.getParameterTypes().length == 0) {
                int mod = c.getModifiers();
                if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
                    return c;
            }
        }
        return null;
    }
1992 1993 1994 1995 1996

    /*non-public*/
    static MethodHandle withTypeHandler(MethodHandle target, MethodHandle typeHandler) {
        return MethodHandleImpl.withTypeHandler(IMPL_TOKEN, target, typeHandler);
    }
1997
}