jdk/src/share/classes/java/dyn/MethodHandles.java
author jrose
Mon, 11 May 2009 21:09:58 -0700
changeset 2763 172d44ffd1e5
parent 2707 5a17df307cbc
child 2764 2e45af54c0f9
permissions -rw-r--r--
6839802: java.dyn needs to be on the CORE_PKGS list Summary: fix makefile to expose the new APIs in the core list; edit some javadocs for correctness Reviewed-by: mr
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
     1
/*
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
     2
 * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
     4
 *
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    10
 *
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    15
 * accompanied this code).
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    16
 *
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    20
 *
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    23
 * have any questions.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    24
 */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    25
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    26
package java.dyn;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    27
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    28
import java.lang.reflect.Constructor;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    29
import sun.dyn.Access;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    30
import sun.dyn.MemberName;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    31
import sun.dyn.MethodHandleImpl;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    32
import sun.dyn.util.VerifyAccess;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    33
import sun.dyn.util.Wrapper;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    34
import java.lang.reflect.Field;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    35
import java.lang.reflect.Method;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    36
import java.lang.reflect.Modifier;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    37
import java.util.ArrayList;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    38
import java.util.Arrays;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    39
import sun.dyn.Invokers;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    40
import sun.dyn.MethodTypeImpl;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    41
import sun.reflect.Reflection;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    42
import static sun.dyn.MemberName.newIllegalArgumentException;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    43
import static sun.dyn.MemberName.newNoAccessException;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    44
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    45
/**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    46
 * Fundamental operations and utilities for MethodHandle.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    47
 * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    48
 * <em>API Note:</em>  The matching of method types in this API cannot
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    49
 * be completely checked by Java's generic type system for three reasons:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    50
 * <ol>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    51
 * <li>Method types range over all possible arities,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    52
 * from no arguments to an arbitrary number of arguments.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    53
 * Generics are not variadic, and so cannot represent this.</li>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    54
 * <li>Method types can specify arguments of primitive types,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    55
 * which Java generic types cannot range over.</li>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    56
 * <li>Method types can optionally specify varargs (ellipsis).</li>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    57
 * </ol>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    58
 * @author John Rose, JSR 292 EG
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    59
 */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    60
public class MethodHandles {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    61
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    62
    private MethodHandles() { }  // do not instantiate
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    63
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    64
    private static final Access IMPL_TOKEN = Access.getToken();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    65
    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    66
    static { MethodHandleImpl.initStatics(); }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    67
    // See IMPL_LOOKUP below.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    68
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    69
    //// Method handle creation from ordinary methods.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    70
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    71
    public static Lookup lookup() {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    72
        return new Lookup();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    73
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    74
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    75
    /**
2763
172d44ffd1e5 6839802: java.dyn needs to be on the CORE_PKGS list
jrose
parents: 2707
diff changeset
    76
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    77
     * A factory object for creating method handles, when the creation
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    78
     * requires access checking.  Method handles do not perform
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    79
     * access checks when they are called; this is a major difference
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    80
     * from reflective {@link Method}, which performs access checking
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    81
     * against every caller, on every call.  Method handle access
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    82
     * restrictions are enforced when a method handle is created.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    83
     * The caller class against which those restrictions are enforced
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    84
     * is known as the "lookup class".  {@link Lookup} embodies an
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    85
     * authenticated lookup class, and can be used to create any number
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    86
     * of access-checked method handles, all checked against a single
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    87
     * lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    88
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    89
     * A class which needs to create method handles will call
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    90
     * {@code MethodHandles.lookup()} to create a factory for itself.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    91
     * It may then use this factory to create method handles on
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    92
     * all of its methods, including private ones.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    93
     * It may also delegate the lookup (e.g., to a metaobject protocol)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    94
     * by passing the {@code Lookup} object to other code.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    95
     * If this other code creates method handles, they will be access
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    96
     * checked against the original lookup class, and not with any higher
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    97
     * privileges.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    98
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    99
     * Note that access checks only apply to named and reflected methods.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   100
     * Other method handle creation methods, such as {@link #convertArguments},
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   101
     * do not require any access checks, and can be done independently
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   102
     * of any lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   103
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   104
     * <em>A note about error conditions:<em>  A lookup can fail, because
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   105
     * the containing class is not accessible to the lookup class, or
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   106
     * because the desired class member is missing, or because the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   107
     * desired class member is not accessible to the lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   108
     * It can also fail if a security manager is installed and refuses
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   109
     * access.  In any of these cases, an exception will be
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   110
     * thrown from the attempted lookup.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   111
     * In general, the conditions under which a method handle may be
2763
172d44ffd1e5 6839802: java.dyn needs to be on the CORE_PKGS list
jrose
parents: 2707
diff changeset
   112
     * created for a method {@code M} are exactly as restrictive as the conditions
172d44ffd1e5 6839802: java.dyn needs to be on the CORE_PKGS list
jrose
parents: 2707
diff changeset
   113
     * under which the lookup class could have compiled a call to {@code M}.
172d44ffd1e5 6839802: java.dyn needs to be on the CORE_PKGS list
jrose
parents: 2707
diff changeset
   114
     * At least some of these error conditions are likely to be
172d44ffd1e5 6839802: java.dyn needs to be on the CORE_PKGS list
jrose
parents: 2707
diff changeset
   115
     * represented by checked exceptions in the final version of this API.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   116
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   117
    public static final
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   118
    class Lookup {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   119
        private final Class<?> lookupClass;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   120
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   121
        /** Which class is performing the lookup?  It is this class against
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   122
         *  which checks are performed for visibility and access permissions.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   123
         *  <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   124
         *  This value is null if and only if this lookup is {@link #PUBLIC_LOOKUP}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   125
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   126
        public Class<?> lookupClass() {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   127
            return lookupClass;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   128
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   129
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   130
        /** Embody the current class (the lookupClass) as a lookup class
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   131
         * for method handle creation.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   132
         * Must be called by from a method in this package,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   133
         * which in turn is called by a method not in this package.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   134
         * Also, don't make it private, lest javac interpose
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   135
         * an access$N method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   136
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   137
        Lookup() {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   138
            Class caller = getCallerClassAtEntryPoint();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   139
            // make sure we haven't accidentally picked up this class:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   140
            checkUnprivilegedlookupClass(caller);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   141
            this.lookupClass = caller;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   142
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   143
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   144
        private Lookup(Class<?> lookupClass) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   145
            this.lookupClass = lookupClass;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   146
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   147
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   148
        /** Version of lookup which is trusted minimally.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   149
         *  It can only be used to create method handles to
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   150
         *  publicly accessible members.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   151
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   152
        public static final Lookup PUBLIC_LOOKUP = new Lookup(null);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   153
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   154
        /** Package-private version of lookup which is trusted. */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   155
        static final Lookup IMPL_LOOKUP = new Lookup(Access.class);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   156
        static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   157
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   158
        private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   159
            if (lookupClass == null ||
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   160
                lookupClass == Access.class ||
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   161
                lookupClass.getName().startsWith("java.dyn."))
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   162
                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   163
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   164
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   165
        @Override
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   166
        public String toString() {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   167
            if (lookupClass == null)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   168
                return "public";
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   169
            return lookupClass.getName();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   170
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   171
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   172
        // call this from an entry point method in Lookup with extraFrames=0.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   173
        private static Class<?> getCallerClassAtEntryPoint() {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   174
            final int CALLER_DEPTH = 4;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   175
            // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   176
            // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   177
            // Note:  This should be the only use of getCallerClass in this file.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   178
            return Reflection.getCallerClass(CALLER_DEPTH);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   179
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   180
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   181
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   182
         * Produce a method handle for a static method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   183
         * The type of the method handle will be that of the method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   184
         * The method and all its argument types must be accessible to the lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   185
         * If the method's class has not yet been initialized, that is done
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   186
         * immediately, before the method handle is returned.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   187
         * @param defc the class from which the method is accessed
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   188
         * @param name the name of the method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   189
         * @param type the type of the method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   190
         * @return the desired method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   191
         * @exception SecurityException <em>TBD</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   192
         * @exception NoAccessException if the method does not exist or access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   193
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   194
        public
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   195
        MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   196
            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   197
            checkStatic(true, method, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   198
            //throw NoSuchMethodException
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   199
            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   200
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   201
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   202
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   203
         * Produce a method handle for a virtual method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   204
         * The type of the method handle will be that of the method,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   205
         * with the receiver type ({@code defc}) prepended.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   206
         * The method and all its argument types must be accessible to the lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   207
         * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   208
         * When called, the handle will treat the first argument as a receiver
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   209
         * and dispatch on the receiver's type to determine which method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   210
         * implementation to enter.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   211
         * (The dispatching action is identical with that performed by an
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   212
         * {@code invokevirtual} or {@code invokeinterface} instruction.)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   213
         * @param defc the class or interface from which the method is accessed
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   214
         * @param name the name of the method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   215
         * @param type the type of the method, with the receiver argument omitted
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   216
         * @return the desired method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   217
         * @exception SecurityException <em>TBD</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   218
         * @exception NoAccessException if the method does not exist or access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   219
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   220
        public MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   221
            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   222
            checkStatic(false, method, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   223
            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   224
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   225
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   226
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   227
         * Produce an early-bound method handle for a virtual method,
2763
172d44ffd1e5 6839802: java.dyn needs to be on the CORE_PKGS list
jrose
parents: 2707
diff changeset
   228
         * as if called from an {@code invokespecial}
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   229
         * instruction from {@code caller}.
2763
172d44ffd1e5 6839802: java.dyn needs to be on the CORE_PKGS list
jrose
parents: 2707
diff changeset
   230
         * The type of the method handle will be that of the method,
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   231
         * with a suitably restricted receiver type (such as {@code caller}) prepended.
2763
172d44ffd1e5 6839802: java.dyn needs to be on the CORE_PKGS list
jrose
parents: 2707
diff changeset
   232
         * The method and all its argument types must be accessible
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   233
         * to the caller.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   234
         * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   235
         * When called, the handle will treat the first argument as a receiver,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   236
         * but will not dispatch on the receiver's type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   237
         * (This direct invocation action is identical with that performed by an
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   238
         * {@code invokespecial} instruction.)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   239
         * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   240
         * If the explicitly specified caller class is not identical with the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   241
         * lookup class, a security check TBD is performed.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   242
         * @param defc the class or interface from which the method is accessed
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   243
         * @param name the name of the method, or "<init>" for a constructor
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   244
         * @param type the type of the method, with the receiver argument omitted
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   245
         * @param specialCaller the proposed calling class to perform the {@code invokespecial}
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   246
         * @return the desired method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   247
         * @exception SecurityException <em>TBD</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   248
         * @exception NoAccessException if the method does not exist or access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   249
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   250
        public MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   251
                                        Class<?> specialCaller) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   252
            checkSpecialCaller(specialCaller, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   253
            MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   254
            checkStatic(false, method, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   255
            if (name.equals("<init>")) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   256
                if (defc != specialCaller)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   257
                    throw newNoAccessException("constructor must be local to lookup class", method, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   258
            } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   259
                throw newNoAccessException("method must be in a superclass of lookup class", method, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   260
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   261
            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   262
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   263
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   264
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   265
         * Produce an early-bound method handle for a non-static method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   266
         * The receiver must have a supertype {@code defc} in which a method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   267
         * of the given name and type is accessible to the lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   268
         * The method and all its argument types must be accessible to the lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   269
         * The type of the method handle will be that of the method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   270
         * The given receiver will be bound into the method handle.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   271
         * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   272
         * Equivalent to the following expression:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   273
         * <code>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   274
         * {@link #insertArgument}({@link #findVirtual}(defc, name, type), receiver)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   275
         * </code>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   276
         * @param receiver the object from which the method is accessed
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   277
         * @param name the name of the method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   278
         * @param type the type of the method, with the receiver argument omitted
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   279
         * @return the desired method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   280
         * @exception SecurityException <em>TBD</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   281
         * @exception NoAccessException if the method does not exist or access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   282
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   283
        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   284
            Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   285
            MemberName reference = new MemberName(rcvc, name, type);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   286
            MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   287
            checkStatic(false, method, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   288
            MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   289
            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   290
            if (bmh == null)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   291
                throw newNoAccessException(method, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   292
            return bmh;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   293
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   294
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   295
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   296
         * Make a direct method handle to <i>m</i>, if the lookup class has permission.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   297
         * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   298
         * If <i>m</i> is virtual, overriding is respected on every call.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   299
         * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   300
         * The type of the method handle will be that of the method,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   301
         * with the receiver type prepended (but only if it is non-static).
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   302
         * If the method's {@code accessible} flag is not set,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   303
         * access checking is performed immediately on behalf of the lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   304
         * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   305
         * @param m the reflected method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   306
         * @return a method handle which can invoke the reflected method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   307
         * @exception NoAccessException if access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   308
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   309
        public MethodHandle unreflect(Method m) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   310
            return unreflectImpl(new MemberName(m), m.isAccessible(), true, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   311
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   312
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   313
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   314
         * Produce a method handle for a reflected method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   315
         * It will bypass checks for overriding methods on the receiver,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   316
         * as if by the {@code invokespecial} instruction.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   317
         * The type of the method handle will be that of the method,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   318
         * with the receiver type prepended.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   319
         * If the method's {@code accessible} flag is not set,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   320
         * access checking is performed immediately on behalf of the lookup class,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   321
         * as if {@code invokespecial} instruction were being linked.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   322
         * @param m the reflected method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   323
         * @return a method handle which can invoke the reflected method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   324
         * @exception NoAccessException if access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   325
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   326
        public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   327
            checkSpecialCaller(specialCaller, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   328
            MemberName mname = new MemberName(m);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   329
            checkStatic(false, mname, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   330
            return unreflectImpl(mname, m.isAccessible(), false, specialCaller);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   331
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   332
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   333
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   334
         * Produce a method handle for a reflected constructor.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   335
         * The type of the method handle will be that of the constructor.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   336
         * The method handle will perform a {@code newInstance} operation,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   337
         * creating a new instance of the constructor's class on the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   338
         * arguments passed to the method handle.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   339
         * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   340
         * If the constructor's {@code accessible} flag is not set,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   341
         * access checking is performed immediately on behalf of the lookup class,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   342
         * as if {@code invokespecial} instruction were being linked.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   343
         * @param ctor the reflected constructor
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   344
         * @return a method handle which can invoke the reflected constructor
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   345
         * @exception NoAccessException if access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   346
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   347
        public MethodHandle unreflectConstructor(Constructor ctor) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   348
            MemberName m = new MemberName(ctor);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   349
            return unreflectImpl(m, ctor.isAccessible(), false, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   350
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   351
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   352
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   353
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   354
         * Produce a method handle giving read access to a reflected field.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   355
         * The type of the method handle will have a return type of the field's
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   356
         * value type.  Its sole argument will be the field's containing class
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   357
         * (but only if it is non-static).
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   358
         * If the method's {@code accessible} flag is not set,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   359
         * access checking is performed immediately on behalf of the lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   360
         * @param f the reflected field
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   361
         * @return a method handle which can load values from the reflected field
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   362
         * @exception NoAccessException if access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   363
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   364
        public MethodHandle unreflectGetter(Field f) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   365
            return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), false, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   366
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   367
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   368
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   369
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   370
         * Produce a method handle giving write access to a reflected field.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   371
         * The type of the method handle will have a void return type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   372
         * Its last argument will be the field's value type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   373
         * Its other argument will be the field's containing class
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   374
         * (but only if it is non-static).
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   375
         * If the method's {@code accessible} flag is not set,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   376
         * access checking is performed immediately on behalf of the lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   377
         * @param f the reflected field
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   378
         * @return a method handle which can store values into the reflected field
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   379
         * @exception NoAccessException if access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   380
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   381
        public MethodHandle unreflectSetter(Field f) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   382
            return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), true, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   383
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   384
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   385
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   386
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   387
    static /*must not be public*/
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   388
    MethodHandle findStaticFrom(Class<?> lookupClass,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   389
                                Class<?> defc, String name, MethodType type) throws NoAccessException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   390
        MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   391
        checkStatic(true, method, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   392
        return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   393
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   394
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   395
    static void checkStatic(boolean wantStatic, MemberName m, Class<?> lookupClass) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   396
        if (wantStatic != m.isStatic()) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   397
            String message = wantStatic ? "expected a static method" : "expected a non-static method";
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   398
            throw newNoAccessException(message, m, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   399
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   400
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   401
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   402
    static void checkSpecialCaller(Class<?> specialCaller, Class<?> lookupClass) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   403
        if (lookupClass == Lookup.IMPL_LOOKUP.lookupClass())
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   404
            return;  // privileged action
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   405
        if (lookupClass == null ||  // public-only access
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   406
            !VerifyAccess.isSamePackageMember(specialCaller, lookupClass))
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   407
            throw newNoAccessException("no private access", new MemberName(specialCaller), lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   408
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   409
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   410
    // Helper for creating handles on reflected methods and constructors.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   411
    static MethodHandle unreflectImpl(MemberName m, boolean isAccessible,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   412
                                      boolean doDispatch, Class<?> lookupClass) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   413
        MethodType mtype = m.getInvocationType();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   414
        Class<?> defc = m.getDeclaringClass();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   415
        int mods = m.getModifiers();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   416
        if (m.isStatic()) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   417
            if (!isAccessible &&
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   418
                    VerifyAccess.isAccessible(defc, mods, false, lookupClass) == null)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   419
                throw newNoAccessException(m, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   420
        } else {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   421
            Class<?> constraint;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   422
            if (isAccessible) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   423
                // abbreviated access check for "unlocked" method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   424
                constraint = doDispatch ? defc : lookupClass;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   425
            } else {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   426
                constraint = VerifyAccess.isAccessible(defc, mods, doDispatch, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   427
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   428
            if (constraint != defc && !constraint.isAssignableFrom(defc)) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   429
                if (!defc.isAssignableFrom(constraint))
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   430
                    throw newNoAccessException("receiver must be in caller class", m, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   431
                mtype = mtype.changeParameterType(0, constraint);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   432
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   433
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   434
        return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   435
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   436
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   437
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   438
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   439
     * Produce a method handle giving read access to elements of an array.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   440
     * The type of the method handle will have a return type of the array's
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   441
     * element type.  Its first argument will be the array type,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   442
     * and the second will be {@code int}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   443
     * @param arrayClass an array type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   444
     * @return a method handle which can load values from the given array type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   445
     * @throws  IllegalArgumentException if arrayClass is not an array type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   446
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   447
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   448
    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   449
        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, false);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   450
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   451
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   452
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   453
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   454
     * Produce a method handle giving write access to elements of an array.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   455
     * The type of the method handle will have a void return type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   456
     * Its last argument will be the array's element type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   457
     * The first and second arguments will be the array type and int.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   458
     * @return a method handle which can store values into the array type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   459
     * @throws IllegalArgumentException if arrayClass is not an array type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   460
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   461
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   462
    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   463
        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   464
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   465
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   466
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   467
    /// method handle invocation (reflective style)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   468
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   469
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   470
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   471
     * Call the {@code invoke} method of a given method handle,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   472
     * with arguments that exactly match the parameter types of the method handle.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   473
     * The length of the arguments array must equal the parameter count
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   474
     * of the target's type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   475
     * The arguments array is spread into separate arguments, and
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   476
     * basic reference and unboxing conversions are applied.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   477
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   478
     * In order to match the type of the target, the following argument
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   479
     * conversions are applied as necessary:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   480
     * <ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   481
     * <li>reference casting
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   482
     * <li>unboxing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   483
     * </ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   484
     * The following conversions are not applied:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   485
     * <ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   486
     * <li>primitive conversions (e.g., {@code byte} to {@code int}
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   487
     * <li>varargs conversions other than the initial spread
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   488
     * <li>any application-specific conversions (e.g., string to number)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   489
     * </ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   490
     * The result returned by the call is boxed if it is a primitive,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   491
     * or forced to null if the return type is void.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   492
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   493
     * This call is a convenience method for the following code:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   494
     * <pre>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   495
     *   MethodHandle invoker = MethodHandles.genericInvoker(target.type(), 0, true);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   496
     *   Object result = invoker.invoke(arguments);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   497
     * </pre>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   498
     * @param target the method handle to invoke
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   499
     * @param arguments the arguments to pass to the target
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   500
     * @return the result returned by the target
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   501
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   502
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   503
    Object invoke(MethodHandle target, Object... arguments) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   504
        int argc = arguments == null ? 0 : arguments.length;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   505
        MethodType type = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   506
        if (argc <= 4) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   507
            MethodHandle invoker = invokers(type).genericInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   508
            switch (argc) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   509
                case 0:  return invoker.<Object>invoke(target);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   510
                case 1:  return invoker.<Object>invoke(target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   511
                                    arguments[0]);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   512
                case 2:  return invoker.<Object>invoke(target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   513
                                    arguments[0], arguments[1]);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   514
                case 3:  return invoker.<Object>invoke(target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   515
                                    arguments[0], arguments[1], arguments[2]);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   516
                case 4:  return invoker.<Object>invoke(target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   517
                                    arguments[0], arguments[1], arguments[2], arguments[3]);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   518
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   519
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   520
        MethodHandle invoker = invokers(type).varargsInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   521
        return invoker.<Object>invoke(target, arguments);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   522
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   523
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   524
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   525
    Object invoke_0(MethodHandle target) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   526
        MethodHandle invoker = invokers(target.type()).genericInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   527
        return invoker.<Object>invoke(target);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   528
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   529
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   530
    Object invoke_1(MethodHandle target, Object a0) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   531
        MethodHandle invoker = invokers(target.type()).genericInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   532
        return invoker.<Object>invoke(target, a0);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   533
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   534
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   535
    Object invoke_2(MethodHandle target, Object a0, Object a1) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   536
        MethodHandle invoker = invokers(target.type()).genericInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   537
        return invoker.<Object>invoke(target, a0, a1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   538
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   539
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   540
    Object invoke_3(MethodHandle target, Object a0, Object a1, Object a2) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   541
        MethodHandle invoker = invokers(target.type()).genericInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   542
        return invoker.<Object>invoke(target, a0, a1, a2);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   543
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   544
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   545
    Object invoke_4(MethodHandle target, Object a0, Object a1, Object a2, Object a3) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   546
        MethodHandle invoker = invokers(target.type()).genericInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   547
        return invoker.<Object>invoke(target, a0, a1, a2, a3);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   548
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   549
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   550
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   551
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   552
     * Give a method handle which will invoke any method handle of the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   553
     * given type on a standard set of {@code Object} type arguments.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   554
     * The the resulting invoker will be a method handle with the following
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   555
     * arguments:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   556
     * <ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   557
     * <li>a single {@code MethodHandle} target
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   558
     * <li>zero or more {@code Object} values
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   559
     * <li>an optional {@code Object[]} array containing more arguments
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   560
     * </ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   561
     * The invoker will spread the varargs array (if present), apply
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   562
     * reference casts as necessary, and unbox primitive arguments.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   563
     * The return value of the invoker will be an {@code Object} reference,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   564
     * boxing a primitive value if the original type returns a primitive,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   565
     * and always null if the original type returns void.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   566
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   567
     * This is a convenience method equivalent to the following code:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   568
     * <pre>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   569
     * MethodHandle invoker = exactInvoker(type);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   570
     * MethodType genericType = MethodType.makeGeneric(objectArgCount, varargs);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   571
     * genericType = genericType.insertParameterType(0, MethodHandle.class);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   572
     * if (!varargs)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   573
     *     return convertArguments(invoker, genericType);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   574
     * else
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   575
     *     return spreadArguments(invoker, genericType);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   576
     * </pre>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   577
     * @param type the desired target type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   578
     * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   579
     * @param varargs if true, the invoker will accept a final {@code Object[]} argument
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   580
     * @return a method handle suitable for invoking any method handle of the given type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   581
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   582
    static public
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   583
    MethodHandle genericInvoker(MethodType type, int objectArgCount, boolean varargs) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   584
        return invokers(type).genericInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   585
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   586
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   587
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   588
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   589
     * Give a method handle which will take a invoke any method handle of the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   590
     * given type.  The resulting invoker will have a type which is
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   591
     * exactly equal to the desired type, except that it will accept
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   592
     * an additional leading argument of type {@code MethodHandle}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   593
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   594
     * This is a convenience method equivalent to the following code:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   595
     * <pre>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   596
     *     MethodHandles.lookup().findVirtual(MethodHandle.class, "invoke", type);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   597
     * </pre>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   598
     * @param type the desired target type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   599
     * @return a method handle suitable for invoking any method handle of the given type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   600
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   601
    static public
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   602
    MethodHandle exactInvoker(MethodType type) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   603
        return invokers(type).exactInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   604
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   605
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   606
    static private Invokers invokers(MethodType type) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   607
        return MethodTypeImpl.invokers(IMPL_TOKEN, type);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   608
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   609
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   610
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   611
     * <em>WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   612
     * Perform value checking, exactly as if for an adapted method handle.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   613
     * It is assumed that the given value is either null, of type T0,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   614
     * or (if T0 is primitive) of the wrapper type corresponding to T0.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   615
     * The following checks and conversions are made:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   616
     * <ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   617
     * <li>If T0 and T1 are references, then a cast to T1 is applied.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   618
     *     (The types do not need to be related in any particular way.)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   619
     * <li>If T0 and T1 are primitives, then a widening or narrowing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   620
     *     conversion is applied, if one exists.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   621
     * <li>If T0 is a primitive and T1 a reference, and
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   622
     *     T0 has a wrapper type TW, a boxing conversion to TW is applied,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   623
     *     possibly followed by a reference conversion.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   624
     *     T1 must be TW or a supertype.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   625
     * <li>If T0 is a reference and T1 a primitive, and
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   626
     *     T1 has a wrapper type TW, an unboxing conversion is applied,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   627
     *     possibly preceded by a reference conversion.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   628
     *     T0 must be TW or a supertype.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   629
     * <li>If T1 is void, the return value is discarded
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   630
     * <li>If T0 is void and T1 a reference, a null value is introduced.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   631
     * <li>If T0 is void and T1 a primitive, a zero value is introduced.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   632
     * </ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   633
     * If the value is discarded, null will be returned.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   634
     * @param valueType
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   635
     * @param value
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   636
     * @return the value, converted if necessary
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   637
     * @throws java.lang.ClassCastException if a cast fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   638
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   639
    static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   640
    <T0, T1> T1 checkValue(Class<T0> t0, Class<T1> t1, Object value)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   641
       throws ClassCastException
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   642
    {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   643
        if (t0 == t1) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   644
            // no conversion needed; just reassert the same type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   645
            if (t0.isPrimitive())
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   646
                return Wrapper.asPrimitiveType(t1).cast(value);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   647
            else
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   648
                return Wrapper.OBJECT.cast(value, t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   649
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   650
        boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   651
        if (!prim0) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   652
            // check contract with caller
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   653
            Wrapper.OBJECT.cast(value, t0);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   654
            if (!prim1) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   655
                return Wrapper.OBJECT.cast(value, t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   656
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   657
            // convert reference to primitive by unboxing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   658
            Wrapper w1 = Wrapper.forPrimitiveType(t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   659
            return w1.cast(value, t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   660
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   661
        // check contract with caller:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   662
        Wrapper.asWrapperType(t0).cast(value);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   663
        Wrapper w1 = Wrapper.forPrimitiveType(t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   664
        return w1.cast(value, t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   665
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   666
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   667
    static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   668
    Object checkValue(Class<?> T1, Object value)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   669
       throws ClassCastException
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   670
    {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   671
        Class<?> T0;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   672
        if (value == null)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   673
            T0 = Object.class;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   674
        else
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   675
            T0 = value.getClass();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   676
        return checkValue(T0, T1, value);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   677
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   678
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   679
    /// method handle modification (creation from other method handles)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   680
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   681
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   682
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   683
     * Produce a method handle which adapts the type of the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   684
     * given method handle to a new type, by pairwise argument conversion,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   685
     * and/or varargs conversion.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   686
     * The original type and new type must have the same number of
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   687
     * arguments, or else one or both them the must be varargs types.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   688
     * The resulting method handle is guaranteed to confess a type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   689
     * which is equal to the desired new type, with any varargs property erased.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   690
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   691
     * If the original type and new type are equal, returns target.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   692
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   693
     * The following conversions are applied as needed both to
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   694
     * arguments and return types.  Let T0 and T1 be the differing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   695
     * new and old parameter types (or old and new return types)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   696
     * for corresponding values passed by the new and old method types.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   697
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   698
     * If an ordinary (non-varargs) parameter of the new type is
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   699
     * to be boxed in a varargs parameter of the old type of type T1[],
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   700
     * then T1 is the element type of the varargs array.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   701
     * Otherwise, if a varargs parameter of the new type of type T0[]
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   702
     * is to be spread into one or more outgoing old type parameters,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   703
     * then T0 is the element type of the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   704
     * If the new type is varargs and the old type is not, the varargs
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   705
     * argument will be checked and must be a non-null array of exactly
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   706
     * the right length.  If there are no parameters in the old type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   707
     * corresponding to the new varargs parameter, the varargs argument
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   708
     * is also allowed to be null.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   709
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   710
     * Given those types T0, T1, one of the following conversions is applied
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   711
     * if possible:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   712
     * <ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   713
     * <li>If T0 and T1 are references, then a cast to T2 is applied,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   714
     *     where T2 is Object if T1 is an interface, else T1.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   715
     *     (The types do not need to be related in any particular way.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   716
     *     The treatment of interfaces follows the usage of the bytecode verifier.)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   717
     * <li>If T0 and T1 are primitives, then a Java casting
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   718
     *     conversion (JLS 5.5) is applied, if one exists.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   719
     * <li>If T0 and T1 are primitives and one is boolean,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   720
     *     the boolean is treated as a one-bit unsigned integer.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   721
     *     (This treatment follows the usage of the bytecode verifier.)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   722
     *     A conversion from another primitive type behaves as if
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   723
     *     it first converts to byte, and then masks all but the low bit.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   724
     * <li>If T0 is a primitive and T1 a reference, a boxing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   725
     *     conversion is applied if one exists, possibly followed by
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   726
     *     an reference conversion to a superclass.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   727
     *     T1 must be a wrapper class or a supertype of one.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   728
     *     If T1 is a wrapper class, T0 is converted if necessary
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   729
     *     to T1's primitive type by one of the preceding conversions.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   730
     *     Otherwise, T0 is boxed, and its wrapper converted to T1.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   731
     * <li>If T0 is a reference and T1 a primitive, an unboxing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   732
     *     conversion is applied if one exists, possibly preceded by
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   733
     *     a reference conversion to a wrapper class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   734
     *     T0 must be a wrapper class or a supertype of one.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   735
     *     If T0 is a wrapper class, its primitive value is converted
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   736
     *     if necessary to T1 by one of the preceding conversions.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   737
     *     Otherwise, T0 is converted directly to the wrapper type for T1,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   738
     *     which is then unboxed.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   739
     * <li>If T1 is void, any returned value is discarded
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   740
     * <li>If T0 is void and T1 a reference, a null value is introduced.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   741
     * <li>If T0 is void and T1 a primitive, a zero value is introduced.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   742
     * </ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   743
     * @param target the method handle to invoke after arguments are retyped
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   744
     * @param newType the expected type of the new method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   745
     * @return a method handle which delegates to {@code target} after performing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   746
     *           any necessary argument conversions, and arranges for any
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   747
     *           necessary return value conversions
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   748
     * @throws WrongMethodTypeException if the conversion cannot be made
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   749
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   750
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   751
    MethodHandle convertArguments(MethodHandle target, MethodType newType) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   752
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   753
        if (oldType.equals(newType))
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   754
            return target;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   755
        MethodHandle res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   756
                                                 newType, oldType, null);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   757
        if (res == null)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   758
            throw newIllegalArgumentException("cannot convert to "+newType+": "+target);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   759
        return res;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   760
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   761
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   762
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   763
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   764
     * Produce a method handle which adapts the calling sequence of the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   765
     * given method handle to a new type, by reordering the arguments.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   766
     * The resulting method handle is guaranteed to confess a type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   767
     * which is equal to the desired new type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   768
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   769
     * The given array controls the reordering.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   770
     * Call {@code #I} the number of incoming parameters (the value
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   771
     * {@code newType.parameterCount()}, and call {@code #O} the number
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   772
     * of outgoing parameters (the value {@code target.type().parameterCount()}).
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   773
     * Then the length of the reordering array must be {@code #O},
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   774
     * and each element must be a non-negative number less than {@code #I}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   775
     * For every {@code N} less than {@code #O}, the {@code N}-th
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   776
     * outgoing argument will be taken from the {@code I}-th incoming
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   777
     * argument, where {@code I} is {@code reorder[N]}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   778
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   779
     * The reordering array need not specify an actual permutation.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   780
     * An incoming argument will be duplicated if its index appears
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   781
     * more than once in the array, and an incoming argument will be dropped
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   782
     * if its index does not appear in the array.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   783
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   784
     * Pairwise conversions are applied as needed to arguments and return
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   785
     * values, as with {@link #convertArguments}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   786
     * @param target the method handle to invoke after arguments are reordered
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   787
     * @param newType the expected type of the new method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   788
     * @param reorder a string which controls the reordering
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   789
     * @return a method handle which delegates to {@code target} after performing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   790
     *           any necessary argument motion and conversions, and arranges for any
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   791
     *           necessary return value conversions
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   792
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   793
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   794
    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int[] reorder) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   795
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   796
        checkReorder(reorder, newType, oldType);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   797
        return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   798
                                                 newType, oldType,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   799
                                                 reorder);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   800
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   801
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   802
    private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   803
        if (reorder.length == oldType.parameterCount()) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   804
            int limit = newType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   805
            boolean bad = false;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   806
            for (int i : reorder) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   807
                if (i < 0 || i >= limit) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   808
                    bad = true; break;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   809
                }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   810
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   811
            if (!bad)  return;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   812
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   813
        throw newIllegalArgumentException("bad reorder array");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   814
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   815
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   816
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   817
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   818
     * Produce a method handle which adapts the type of the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   819
     * given method handle to a new type, by spreading the final argument.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   820
     * The resulting method handle is guaranteed to confess a type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   821
     * which is equal to the desired new type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   822
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   823
     * The final parameter type of the new type must be an array type T[].
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   824
     * This is the type of what is called the <i>spread</i> argument.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   825
     * All other arguments of the new type are called <i>ordinary</i> arguments.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   826
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   827
     * The ordinary arguments of the new type are pairwise converted
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   828
     * to the initial parameter types of the old type, according to the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   829
     * rules in {@link #convertArguments}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   830
     * Any additional arguments in the old type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   831
     * are converted from the array element type T,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   832
     * again according to the rules in {@link #convertArguments}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   833
     * The return value is converted according likewise.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   834
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   835
     * The call verifies that the spread argument is in fact an array
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   836
     * of exactly the type length, i.e., the excess number of
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   837
     * arguments in the old type over the ordinary arguments in the new type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   838
     * If there are no excess arguments, the spread argument is also
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   839
     * allowed to be null.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   840
     * @param target the method handle to invoke after the argument is prepended
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   841
     * @param newType the expected type of the new method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   842
     * @return a new method handle which spreads its final argument,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   843
     *         before calling the original method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   844
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   845
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   846
    MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   847
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   848
        int inargs  = newType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   849
        int outargs = oldType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   850
        int spreadPos = inargs - 1;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   851
        int numSpread = (outargs - spreadPos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   852
        MethodHandle res = null;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   853
        if (spreadPos >= 0 && numSpread >= 0) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   854
            res = MethodHandleImpl.spreadArguments(IMPL_TOKEN, target, newType, spreadPos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   855
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   856
        if (res == null) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   857
            throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   858
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   859
        return res;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   860
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   861
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   862
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   863
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   864
     * Produce a method handle which adapts the type of the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   865
     * given method handle to a new type, by collecting a series of
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   866
     * trailing arguments into an array.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   867
     * The resulting method handle is guaranteed to confess a type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   868
     * which is equal to the desired new type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   869
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   870
     * This method is inverse to {@link #spreadArguments}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   871
     * The final parameter type of the old type must be an array type T[],
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   872
     * which is the type of what is called the <i>spread</i> argument.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   873
     * The trailing arguments of the new type which correspond to
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   874
     * the spread argument are all converted to type T and collected
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   875
     * into an array before the original method is called.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   876
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   877
     * ISSUE: Unify this with combineArguments.  CollectArguments
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   878
     * is combineArguments with (a) new Object[]{...} as a combiner,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   879
     * and (b) the combined arguments dropped, in favor of the combined result.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   880
     * @param target the method handle to invoke after the argument is prepended
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   881
     * @param newType the expected type of the new method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   882
     * @return a new method handle which collects some trailings argument
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   883
     *         into an array, before calling the original method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   884
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   885
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   886
    MethodHandle collectArguments(MethodHandle target, MethodType newType) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   887
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   888
        int inargs  = newType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   889
        int outargs = oldType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   890
        int collectPos = outargs - 1;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   891
        int numCollect = (inargs - collectPos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   892
        if (collectPos < 0 || numCollect < 0)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   893
            throw newIllegalArgumentException("wrong number of arguments");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   894
        return MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   895
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   896
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   897
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   898
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   899
     * Produce a method handle which calls the original method handle,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   900
     * after inserting the given argument at the given position.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   901
     * The type of the new method handle will drop the corresponding argument
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   902
     * type from the original handle's type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   903
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   904
     * The given argument object must match the dropped argument type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   905
     * If the dropped argument type is a primitive, the argument object
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   906
     * must be a wrapper, and is unboxed to produce the primitive.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   907
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   908
     * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   909
     * where <i>N</i> is the number of argument types in <i>target</i>,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   910
     * meaning to insert the new argument as the first or last (respectively),
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   911
     * or somewhere in between.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   912
     * @param target the method handle to invoke after the argument is inserted
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   913
     * @param pos where to insert the argument (zero for the first)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   914
     * @param value the argument to insert
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   915
     * @return a new method handle which inserts an additional argument,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   916
     *         before calling the original method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   917
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   918
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   919
    MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   920
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   921
        ArrayList<Class<?>> ptypes =
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   922
                new ArrayList<Class<?>>(oldType.parameterList());
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   923
        int outargs = oldType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   924
        int inargs  = outargs - 1;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   925
        if (pos < 0 || pos >= outargs)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   926
            throw newIllegalArgumentException("no argument type to append");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   927
        Class<?> valueType = ptypes.remove(pos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   928
        value = checkValue(valueType, value);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   929
        if (pos == 0 && !valueType.isPrimitive()) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   930
            // At least for now, make bound method handles a special case.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   931
            // This lets us get by with minimal JVM support, at the expense
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   932
            // of generating signature-specific adapters as Java bytecodes.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   933
            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, target, value);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   934
            if (bmh != null)  return bmh;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   935
            // else fall through to general adapter machinery
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   936
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   937
        return MethodHandleImpl.bindArgument(IMPL_TOKEN, target, pos, value);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   938
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   939
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   940
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   941
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   942
     * Produce a method handle which calls the original method handle,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   943
     * after dropping the given argument(s) at the given position.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   944
     * The type of the new method handle will insert the given argument
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   945
     * type(s), at that position, into the original handle's type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   946
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   947
     * The <i>pos</i> may range between zero and <i>N-1</i>,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   948
     * where <i>N</i> is the number of argument types in <i>target</i>,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   949
     * meaning to drop the first or last argument (respectively),
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   950
     * or an argument somewhere in between.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   951
     * @param target the method handle to invoke after the argument is dropped
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   952
     * @param valueTypes the type(s) of the argument to drop
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   953
     * @param pos which argument to drop (zero for the first)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   954
     * @return a new method handle which drops an argument of the given type,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   955
     *         before calling the original method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   956
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   957
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   958
    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   959
        if (valueTypes.length == 0)  return target;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   960
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   961
        int outargs = oldType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   962
        int inargs  = outargs + valueTypes.length;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   963
        if (pos < 0 || pos >= inargs)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   964
            throw newIllegalArgumentException("no argument type to remove");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   965
        ArrayList<Class<?>> ptypes =
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   966
                new ArrayList<Class<?>>(oldType.parameterList());
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   967
        ptypes.addAll(pos, Arrays.asList(valueTypes));
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   968
        MethodType newType = MethodType.make(oldType.returnType(), ptypes);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   969
        return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   970
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   971
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   972
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   973
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   974
     * Make a method handle which adapts a target method handle,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   975
     * by guarding it with a test, a boolean-valued method handle.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   976
     * If the guard fails, a fallback handle is called instead.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   977
     * All three method handles must have the same corresponding
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   978
     * argument and return types, except that the return type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   979
     * of the test must be boolean.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   980
     * <p> Here is pseudocode for the resulting adapter:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   981
     * <blockquote><pre>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   982
     * signature T(A...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   983
     * boolean test(A...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   984
     * T target(A...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   985
     * T fallback(A...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   986
     * T adapter(A... a) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   987
     *   if (test(a...))
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   988
     *     return target(a...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   989
     *   else
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   990
     *     return fallback(a...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   991
     * }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   992
     * </pre></blockquote>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   993
     * @param test method handle used for test, must return boolean
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   994
     * @param target method handle to call if test passes
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   995
     * @param fallback method handle to call if test fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   996
     * @return method handle which incorporates the specified if/then/else logic
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   997
     * @throws IllegalArgumentException if {@code test} does not return boolean,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   998
     *          or if all three method types do not match (with the return
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   999
     *          type of {@code test} changed to match that of {@code target}).
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1000
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1001
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1002
    MethodHandle guardWithTest(MethodHandle test,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1003
                               MethodHandle target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1004
                               MethodHandle fallback) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1005
        if (target.type() != fallback.type())
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1006
            throw newIllegalArgumentException("target and fallback types do not match");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1007
        if (target.type().changeReturnType(boolean.class) != test.type())
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1008
            throw newIllegalArgumentException("target and test types do not match");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1009
        /* {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1010
            MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1011
            static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1012
                return z ? t : f;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1013
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1014
            static MethodHandle compose(MethodHandle f, MethodHandle g) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1015
                Class<?> initargs = g.type().parameterArray();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1016
                f = dropArguments(f, 1, initargs);  // ignore 2nd copy of args
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1017
                return combineArguments(f, g);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1018
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1019
            // choose = \z.(z ? target : fallback)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1020
            MethodHandle choose = findVirtual(MethodHandles.class, "choose",
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1021
                    MethodType.make(boolean.class, MethodHandle.class, MethodHandle.class));
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1022
            choose = appendArgument(choose, target);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1023
            choose = appendArgument(choose, fallback);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1024
            MethodHandle dispatch = compose(choose, test);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1025
            // dispatch = \(a...).(test(a...) ? target : fallback)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1026
            return combineArguments(invoke, dispatch, 0);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1027
            // return \(a...).((test(a...) ? target : fallback).invoke(a...))
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1028
        } */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1029
        return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1030
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1031
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1032
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1033
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1034
     * Adapt a target method handle {@code target} by first processing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1035
     * its arguments, and then calling the target.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1036
     * The initial processing is performed by a second method handle, the {@code combiner}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1037
     * After this, control passes to the {@code target}, with the same arguments.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1038
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1039
     * The return value of the {@code combiner} is inserted into the argument list
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1040
     * for the {@code target} at the indicated position {@code pos}, if it is non-negative.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1041
     * Except for this inserted argument (if any), the argument types of
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1042
     * the target {@code target} and the {@code combiner} must be identical.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1043
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1044
     * (Note that {@link #dropArguments} can be used to remove any arguments
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1045
     * that either the {@code combiner} or {@code target} does not wish to receive.)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1046
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1047
     * The combiner handle must have the same argument types as the
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1048
     * target handle, but must return {@link MethodHandle} instead of
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1049
     * the ultimate return type.  The returned method handle, in turn,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1050
     * is required to have exactly the given final method type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1051
     * <p> Here is pseudocode for the resulting adapter:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1052
     * <blockquote><pre>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1053
     * signature V(A[pos]..., B...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1054
     * signature T(A[pos]..., V, B...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1055
     * T target(A... a, V v, B... b);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1056
     * V combiner(A..., B...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1057
     * T adapter(A... a, B... b) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1058
     *   V v = combiner(a..., b...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1059
     *   return target(a..., v, b...);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1060
     * }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1061
     * </pre></blockquote>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1062
     * @param target the method handle to invoke after arguments are combined
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1063
     * @param pos where the return value of {@code combiner} is to
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1064
     *          be inserted as an argument to {@code target}
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1065
     * @param combiner method handle to call initially on the incoming arguments
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1066
     * @return method handle which incorporates the specified dispatch logic
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1067
     * @throws IllegalArgumentException if {@code combiner} does not itself
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1068
     *          return either void or the {@code pos}-th argument of {@code target},
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1069
     *          or does not have the same argument types as {@code target}
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1070
     *          (minus the inserted argument)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1071
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1072
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1073
    MethodHandle combineArguments(MethodHandle target, int pos, MethodHandle combiner) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1074
        MethodType mhType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1075
        Class<?> combineType = combiner.type().returnType();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1076
        MethodType incomingArgs;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1077
        if (pos < 0) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1078
            // No inserted argument; target & combiner must have same argument types.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1079
            incomingArgs = mhType;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1080
            if (!incomingArgs.changeReturnType(combineType).equals(combiner.type()))
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1081
                throw newIllegalArgumentException("target and combiner types do not match");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1082
        } else {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1083
            // Inserted argument.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1084
            if (pos >= mhType.parameterCount()
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1085
                || mhType.parameterType(pos) != combineType)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1086
                throw newIllegalArgumentException("inserted combiner argument does not match target");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1087
            incomingArgs = mhType.dropParameterType(pos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1088
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1089
        if (!incomingArgs.changeReturnType(combineType).equals(combiner.type())) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1090
            throw newIllegalArgumentException("target and combiner types do not match");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1091
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1092
        return MethodHandleImpl.combineArguments(IMPL_TOKEN, target, combiner, pos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1093
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1094
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1095
}