jdk/src/share/classes/java/dyn/MethodHandles.java
author jrose
Sat, 19 Jun 2010 01:14:40 -0700
changeset 5727 f825b9b605e4
parent 5725 16c1792b2ee6
parent 5726 72c9d793224b
child 7052 963a5baf2ba3
permissions -rw-r--r--
Merge
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
/*
5725
jrose
parents: 5506 5722
diff changeset
     2
 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
2707
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
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4537
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2707
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
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4537
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2707
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
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4537
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4537
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4537
diff changeset
    23
 * questions.
2707
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;
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
    37
import java.util.List;
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    38
import java.util.ArrayList;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    39
import java.util.Arrays;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    40
import sun.dyn.Invokers;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    41
import sun.dyn.MethodTypeImpl;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    42
import sun.reflect.Reflection;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    43
import static sun.dyn.MemberName.newIllegalArgumentException;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    44
import static sun.dyn.MemberName.newNoAccessException;
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
/**
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    47
 * This class consists exclusively of static methods that operate on or return
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    48
 * method handles. They fall into several categories:
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
    49
 * <ul>
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    50
 * <li>Factory methods which create method handles for methods and fields.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    51
 * <li>Invoker methods which can invoke method handles on dynamically typed arguments and/or varargs arrays.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    52
 * <li>Combinator methods, which combine or transforming pre-existing method handles into new ones.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    53
 * <li>Factory methods which create method handles that emulate other common JVM operations or control flow patterns.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
    54
 * </ul>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    55
 * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    56
 * @author John Rose, JSR 292 EG
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    57
 */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    58
public class MethodHandles {
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
    private MethodHandles() { }  // do not instantiate
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 static final Access IMPL_TOKEN = Access.getToken();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    63
    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
    64
    static { MethodHandleImpl.initStatics(); }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    65
    // See IMPL_LOOKUP below.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    66
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    67
    //// Method handle creation from ordinary methods.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    68
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    69
    /**
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    70
     * Return a {@link Lookup lookup object} on the caller,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    71
     * which has the capability to access any method handle that the caller has access to,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    72
     * including direct method handles to private fields and methods.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    73
     * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    74
     * Do not store it in place where untrusted code can access it.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
    75
     */
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    76
    public static Lookup lookup() {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    77
        return new Lookup();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    78
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    79
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    80
    /**
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    81
     * Return a {@link Lookup lookup object} which is trusted minimally.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    82
     * It can only be used to create method handles to
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    83
     * publicly accessible fields and methods.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
    84
     */
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
    85
    public static Lookup publicLookup() {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
    86
        return Lookup.PUBLIC_LOOKUP;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
    87
    }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
    88
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    89
    /**
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    90
     * A <em>lookup object</em> is a factory for creating method handles,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    91
     * when the creation requires access checking.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    92
     * Method handles do not perform
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    93
     * 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
    94
     * from reflective {@link Method}, which performs access checking
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    95
     * against every caller, on every call.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    96
     * Therefore, method handle access
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    97
     * restrictions must be enforced when a method handle is created.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
    98
     * The caller class against which those restrictions are enforced
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
    99
     * is known as the {@linkplain #lookupClass lookup class}.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   100
     * A lookup object embodies an
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   101
     * 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
   102
     * 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
   103
     * lookup class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   104
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   105
     * A class which needs to create method handles will call
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   106
     * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   107
     * 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
   108
     * all of its methods, including private ones.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   109
     * 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
   110
     * by passing the {@code Lookup} object to other code.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   111
     * 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
   112
     * 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
   113
     * privileges.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   114
     * <p>
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   115
     * Access checks only apply to named and reflected methods.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   116
     * Other method handle creation methods, such as
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   117
     * {@link #convertArguments MethodHandles.convertArguments},
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   118
     * 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
   119
     * of any lookup class.
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   120
     * <h3>How access errors are handled</h3>
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   121
     * A lookup can fail, because
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   122
     * 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
   123
     * 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
   124
     * 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
   125
     * 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
   126
     * 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
   127
     * thrown from the attempted lookup.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   128
     * 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
   129
     * 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
   130
     * 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
   131
     * 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
   132
     * 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
   133
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   134
    public static final
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   135
    class Lookup {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   136
        /** The class on behalf of whom the lookup is being performed. */
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   137
        private final Class<?> lookupClass;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   138
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   139
        /** The allowed sorts of members which may be looked up (public, etc.), with STRICT for package. */
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   140
        private final int allowedModes;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   141
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   142
        private static final int
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   143
            PUBLIC    = Modifier.PUBLIC,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   144
            PACKAGE   = Modifier.STRICT,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   145
            PROTECTED = Modifier.PROTECTED,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   146
            PRIVATE   = Modifier.PRIVATE,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   147
            ALL_MODES = (PUBLIC | PACKAGE | PROTECTED | PRIVATE),
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   148
            TRUSTED   = -1;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   149
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   150
        private static int fixmods(int mods) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   151
            mods &= (ALL_MODES - PACKAGE);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   152
            return (mods != 0) ? mods : PACKAGE;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   153
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   154
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   155
        /** 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
   156
         *  which checks are performed for visibility and access permissions.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   157
         *  <p>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   158
         *  This value is null if and only if this lookup was produced
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   159
         *  by {@link MethodHandles#publicLookup}.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   160
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   161
        public Class<?> lookupClass() {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   162
            return 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
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   165
        // This is just for calling out to MethodHandleImpl.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   166
        private Class<?> lookupClassOrNull() {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   167
            return (allowedModes == TRUSTED) ? null : lookupClass;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   168
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   169
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   170
        /** Which types of members can this lookup object produce?
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   171
         *  The result is a bit-mask of the modifier bits PUBLIC, PROTECTED, PRIVATE, and STRICT.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   172
         *  The modifier bit STRICT stands in for the (non-existent) package protection mode.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   173
         */
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   174
        int lookupModes() {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   175
            return allowedModes & ALL_MODES;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   176
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   177
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   178
        /** 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
   179
         * for method handle creation.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   180
         * 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
   181
         * which in turn is called by a method not in this package.
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   182
         * <p>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   183
         * Also, don't make it private, lest javac interpose
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   184
         * an access$N method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   185
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   186
        Lookup() {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   187
            this(getCallerClassAtEntryPoint(), ALL_MODES);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   188
            // make sure we haven't accidentally picked up a privileged class:
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   189
            checkUnprivilegedlookupClass(lookupClass);
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   190
        }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   191
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   192
        Lookup(Access token, Class<?> lookupClass) {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   193
            this(lookupClass, ALL_MODES);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   194
            Access.check(token);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   195
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   196
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   197
        private Lookup(Class<?> lookupClass, int allowedModes) {
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   198
            this.lookupClass = lookupClass;
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   199
            this.allowedModes = allowedModes;
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   200
        }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   201
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   202
        /**
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   203
         * Create a lookup on the specified new lookup class.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   204
         * The resulting object will report the specified
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   205
         * class as its own {@link #lookupClass}.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   206
         * <p>
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   207
         * However, the resulting {@code Lookup} object is guaranteed
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   208
         * to have no more access capabilities than the original.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   209
         * In particular:<ul>
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   210
         * <li>If the new lookup class differs from the old one,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   211
         * protected members will not be accessible by virtue of inheritance.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   212
         * <li>If the new lookup class is in a different package
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   213
         * than the old one, protected and default (package) members will not be accessible.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   214
         * <li>If the new lookup class is not within the same package member
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   215
         * as the old one, private members will not be accessible.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   216
         * <li>In all cases, public members will continue to be accessible.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   217
         * </ul>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   218
         */
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   219
        public Lookup in(Class<?> requestedLookupClass) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   220
            requestedLookupClass.getClass();  // null check
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   221
            if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   222
                return new Lookup(requestedLookupClass, ALL_MODES);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   223
            if (requestedLookupClass == this.lookupClass)
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   224
                return this;  // keep same capabilities
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   225
            int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   226
            if ((newModes & PACKAGE) != 0
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   227
                && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   228
                newModes &= ~(PACKAGE|PRIVATE);
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   229
            }
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   230
            if ((newModes & PRIVATE) != 0
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   231
                && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   232
                newModes &= ~PRIVATE;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   233
            }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   234
            checkUnprivilegedlookupClass(requestedLookupClass);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   235
            return new Lookup(requestedLookupClass, newModes);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   236
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   237
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   238
        // Make sure outer class is initialized first.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   239
        static { IMPL_TOKEN.getClass(); }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   240
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   241
        /** Version of lookup which is trusted minimally.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   242
         *  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
   243
         *  publicly accessible members.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   244
         */
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   245
        static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   246
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   247
        /** Package-private version of lookup which is trusted. */
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   248
        static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   249
        static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   250
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   251
        private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
2764
2e45af54c0f9 6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents: 2763
diff changeset
   252
            String name = lookupClass.getName();
2e45af54c0f9 6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents: 2763
diff changeset
   253
            if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   254
                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   255
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   256
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   257
        /** Display the name of the class.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   258
         *  If there are restrictions on the access permitted to this lookup,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   259
         *  display those also.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   260
         */
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   261
        @Override
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   262
        public String toString() {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   263
            String modestr;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   264
            String cname = lookupClass.getName();
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   265
            switch (allowedModes) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   266
            case TRUSTED:
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   267
                return "/trusted";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   268
            case PUBLIC:
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   269
                modestr = "/public";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   270
                if (lookupClass == Object.class)
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   271
                    return modestr;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   272
                break;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   273
            case PUBLIC|PACKAGE:
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   274
                return cname + "/package";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   275
            case 0:  // should not happen
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   276
                return cname + "/empty";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   277
            case ALL_MODES:
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   278
                return cname;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   279
            }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   280
            StringBuilder buf = new StringBuilder(cname);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   281
            if ((allowedModes & PUBLIC) != 0)     buf.append("/public");
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   282
            if ((allowedModes & PACKAGE) != 0)    buf.append("/package");
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   283
            if ((allowedModes & PROTECTED) != 0)  buf.append("/protected");
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   284
            if ((allowedModes & PRIVATE) != 0)    buf.append("/private");
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   285
            return buf.toString();
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   286
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   287
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   288
        // 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
   289
        private static Class<?> getCallerClassAtEntryPoint() {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   290
            final int CALLER_DEPTH = 4;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   291
            // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   292
            // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   293
            // Note:  This should be the only use of getCallerClass in this file.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   294
            assert(Reflection.getCallerClass(CALLER_DEPTH-1) == MethodHandles.class);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   295
            return Reflection.getCallerClass(CALLER_DEPTH);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   296
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   297
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   298
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   299
         * Produce a method handle for a static method.
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.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   301
         * (Since static methods do not take receivers, there is no
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   302
         * additional receiver argument inserted into the method handle type,
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   303
         * as there would be with {@link #findVirtual} or {@link #findSpecial}.)
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   304
         * 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
   305
         * 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
   306
         * immediately, before the method handle is returned.
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   307
         * @param refc the class from which the method is accessed
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   308
         * @param name the name of the method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   309
         * @param type the type of the method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   310
         * @return the desired method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   311
         * @exception SecurityException <em>TBD</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   312
         * @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
   313
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   314
        public
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   315
        MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoAccessException {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   316
            MemberName method = resolveOrFail(refc, name, type, true);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   317
            checkMethod(refc, method, true);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   318
            return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   319
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   320
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   321
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   322
         * Produce a method handle for a virtual method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   323
         * The type of the method handle will be that of the method,
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   324
         * with the receiver type (usually {@code refc}) prepended.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   325
         * 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
   326
         * <p>
2764
2e45af54c0f9 6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents: 2763
diff changeset
   327
         * (<em>BUG NOTE:</em> The type {@code Object} may be prepended instead
2e45af54c0f9 6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents: 2763
diff changeset
   328
         * of the receiver type, if the receiver type is not on the boot class path.
2e45af54c0f9 6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents: 2763
diff changeset
   329
         * This is due to a temporary JVM limitation, in which MethodHandle
2e45af54c0f9 6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents: 2763
diff changeset
   330
         * claims to be unable to access such classes.  To work around this
2e45af54c0f9 6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents: 2763
diff changeset
   331
         * bug, use {@code convertArguments} to normalize the type of the leading
2e45af54c0f9 6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents: 2763
diff changeset
   332
         * argument to a type on the boot class path, such as {@code Object}.)
2e45af54c0f9 6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents: 2763
diff changeset
   333
         * <p>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   334
         * 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
   335
         * 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
   336
         * implementation to enter.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   337
         * (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
   338
         * {@code invokevirtual} or {@code invokeinterface} instruction.)
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   339
         * @param refc the class or interface from which the method is accessed
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   340
         * @param name the name of the method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   341
         * @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
   342
         * @return the desired method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   343
         * @exception SecurityException <em>TBD</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   344
         * @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
   345
         */
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   346
        public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoAccessException {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   347
            MemberName method = resolveOrFail(refc, name, type, false);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   348
            checkMethod(refc, method, false);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   349
            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   350
            return restrictProtectedReceiver(method, mh);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   351
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   352
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   353
        /**
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   354
         * Produce a method handle which creates an object and initializes it, using
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   355
         * the constructor of the specified type.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   356
         * The parameter types of the method handle will be those of the constructor,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   357
         * while the return type will be a reference to the constructor's class.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   358
         * The constructor and all its argument types must be accessible to the lookup class.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   359
         * If the constructor's class has not yet been initialized, that is done
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   360
         * immediately, before the method handle is returned.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   361
         * <p>
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   362
         * Note:  The requested type must have a return type of {@code void}.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   363
         * This is consistent with the JVM's treatment of constructor signatures.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   364
         * @param refc the class or interface from which the method is accessed
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   365
         * @param type the type of the method, with the receiver argument omitted, and a void return type
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   366
         * @return the desired method handle
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   367
         * @exception SecurityException <em>TBD</em>
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   368
         * @exception NoAccessException if the method does not exist or access checking fails
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   369
         */
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   370
        public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoAccessException {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   371
            String name = "<init>";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   372
            MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   373
            assert(ctor.isConstructor());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   374
            checkAccess(refc, ctor);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   375
            MethodHandle rawMH = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   376
            return MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawMH);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   377
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   378
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   379
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   380
         * 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
   381
         * as if called from an {@code invokespecial}
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   382
         * instruction from {@code caller}.
2763
172d44ffd1e5 6839802: java.dyn needs to be on the CORE_PKGS list
jrose
parents: 2707
diff changeset
   383
         * 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
   384
         * 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
   385
         * 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
   386
         * to the caller.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   387
         * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   388
         * 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
   389
         * but will not dispatch on the receiver's type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   390
         * (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
   391
         * {@code invokespecial} instruction.)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   392
         * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   393
         * 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
   394
         * lookup class, a security check TBD is performed.
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   395
         * @param refc the class or interface from which the method is accessed
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   396
         * @param name the name of the method (which must not be "&lt;init&gt;")
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   397
         * @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
   398
         * @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
   399
         * @return the desired method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   400
         * @exception SecurityException <em>TBD</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   401
         * @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
   402
         */
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   403
        public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   404
                                        Class<?> specialCaller) throws NoAccessException {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   405
            checkSpecialCaller(specialCaller);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   406
            MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   407
            checkMethod(refc, method, false);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   408
            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   409
            return restrictReceiver(method, mh, specialCaller);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   410
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   411
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   412
        /**
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   413
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5726
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   414
         * Produce a method handle giving read access to a non-static field.
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   415
         * The type of the method handle will have a return type of the field's
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   416
         * value type.
5726
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   417
         * The method handle's single argument will be the instance containing
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   418
         * the field.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   419
         * Access checking is performed immediately on behalf of the lookup class.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   420
         * @param name the field's name
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   421
         * @param type the field's type
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   422
         * @return a method handle which can load values from the field
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   423
         * @exception NoAccessException if access checking fails
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   424
         */
5726
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   425
        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   426
            return makeAccessor(refc, name, type, false, false);
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   427
        }
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   428
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   429
        /**
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   430
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   431
         * Produce a method handle giving write access to a non-static field.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   432
         * The type of the method handle will have a void return type.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   433
         * The method handle will take two arguments, the instance containing
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   434
         * the field, and the value to be stored.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   435
         * The second argument will be of the field's value type.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   436
         * Access checking is performed immediately on behalf of the lookup class.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   437
         * @param name the field's name
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   438
         * @param type the field's type
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   439
         * @return a method handle which can store values into the field
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   440
         * @exception NoAccessException if access checking fails
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   441
         */
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   442
        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   443
            return makeAccessor(refc, name, type, false, true);
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   444
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   445
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   446
        /**
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   447
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5726
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   448
         * Produce a method handle giving read access to a static field.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   449
         * The type of the method handle will have a return type of the field's
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   450
         * value type.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   451
         * The method handle will take no arguments.
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   452
         * Access checking is performed immediately on behalf of the lookup class.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   453
         * @param name the field's name
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   454
         * @param type the field's type
5726
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   455
         * @return a method handle which can load values from the field
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   456
         * @exception NoAccessException if access checking fails
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   457
         */
5726
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   458
        public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   459
            return makeAccessor(refc, name, type, true, false);
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   460
        }
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   461
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   462
        /**
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   463
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   464
         * Produce a method handle giving write access to a static field.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   465
         * The type of the method handle will have a void return type.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   466
         * The method handle will take a single
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   467
         * argument, of the field's value type, the value to be stored.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   468
         * Access checking is performed immediately on behalf of the lookup class.
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   469
         * @param name the field's name
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   470
         * @param type the field's type
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   471
         * @return a method handle which can store values into the field
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   472
         * @exception NoAccessException if access checking fails
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   473
         */
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   474
        public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
72c9d793224b 6939203: JSR 292 needs method handle constants
jrose
parents: 5722
diff changeset
   475
            return makeAccessor(refc, name, type, true, true);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   476
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   477
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   478
        /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   479
         * 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
   480
         * 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
   481
         * 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
   482
         * The method and all its argument types must be accessible to the lookup class.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   483
         * The type of the method handle will be that of the method,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   484
         * without any insertion of an additional receiver parameter.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   485
         * The given receiver will be bound into the method handle,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   486
         * so that every call to the method handle will invoke the
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   487
         * requested method on the given receiver.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   488
         * <p>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   489
         * This is equivalent to the following expression:
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   490
         * <code>
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   491
         * {@link #insertArguments insertArguments}({@link #findVirtual findVirtual}(defc, name, type), receiver)
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   492
         * </code>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   493
         * where {@code defc} is either {@code receiver.getClass()} or a super
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   494
         * type of that class, in which the requested method is accessible
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   495
         * to the lookup class.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   496
         * @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
   497
         * @param name the name of the method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   498
         * @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
   499
         * @return the desired method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   500
         * @exception SecurityException <em>TBD</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   501
         * @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
   502
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   503
        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   504
            Class<? extends Object> refc = receiver.getClass(); // may get NPE
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   505
            MemberName method = resolveOrFail(refc, name, type, false);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   506
            checkMethod(refc, method, false);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   507
            MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   508
            MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   509
            if (bmh == null)
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   510
                throw newNoAccessException(method, lookupClass());
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   511
            return bmh;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   512
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   513
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   514
        /**
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   515
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   516
         * 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
   517
         * 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
   518
         * 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
   519
         * 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
   520
         * 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
   521
         * 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
   522
         * 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
   523
         * 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
   524
         * 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
   525
         * @param m the reflected method
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   526
         * @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
   527
         * @exception NoAccessException if access checking fails
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 MethodHandle unreflect(Method m) throws NoAccessException {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   530
            MemberName method = new MemberName(m);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   531
            assert(method.isMethod());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   532
            if (!m.isAccessible())  checkMethod(method.getDeclaringClass(), method, method.isStatic());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   533
            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   534
            if (!m.isAccessible())  mh = restrictProtectedReceiver(method, mh);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   535
            return mh;
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   536
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   537
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   538
        /**
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   539
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   540
         * Produce a method handle for a reflected method.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   541
         * It will bypass checks for overriding methods on the receiver,
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   542
         * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   543
         * The type of the method handle will be that of the method,
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   544
         * with the special caller type prepended (and <em>not</em> the receiver of the method).
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   545
         * 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
   546
         * 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
   547
         * as if {@code invokespecial} instruction were being linked.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   548
         * @param m the reflected method
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   549
         * @param specialCaller the class nominally calling the method
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   550
         * @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
   551
         * @exception NoAccessException if access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   552
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   553
        public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   554
            checkSpecialCaller(specialCaller);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   555
            MemberName method = new MemberName(m);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   556
            assert(method.isMethod());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   557
            // ignore m.isAccessible:  this is a new kind of access
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   558
            checkMethod(m.getDeclaringClass(), method, false);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   559
            MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   560
            return restrictReceiver(method, mh, specialCaller);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   561
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   562
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   563
        /**
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   564
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   565
         * Produce a method handle for a reflected constructor.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   566
         * The type of the method handle will be that of the constructor,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   567
         * with the return type changed to the declaring class.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   568
         * The method handle will perform a {@code newInstance} operation,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   569
         * 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
   570
         * arguments passed to the method handle.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   571
         * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   572
         * If the constructor's {@code accessible} flag is not set,
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   573
         * access checking is performed immediately on behalf of the lookup class.
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   574
         * @param c the reflected constructor
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   575
         * @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
   576
         * @exception NoAccessException if access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   577
         */
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   578
        public MethodHandle unreflectConstructor(Constructor c) throws NoAccessException {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   579
            MemberName ctor = new MemberName(c);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   580
            assert(ctor.isConstructor());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   581
            if (!c.isAccessible())  checkAccess(c.getDeclaringClass(), ctor);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   582
            MethodHandle rawCtor = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   583
            return MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawCtor);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   584
        }
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
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   588
         * 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
   589
         * The type of the method handle will have a return type of the field's
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   590
         * value type.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   591
         * If the field is static, the method handle will take no arguments.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   592
         * Otherwise, its single argument will be the instance containing
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   593
         * the field.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   594
         * 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
   595
         * 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
   596
         * @param f the reflected field
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   597
         * @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
   598
         * @exception NoAccessException if access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   599
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   600
        public MethodHandle unreflectGetter(Field f) throws NoAccessException {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   601
            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   602
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   603
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
         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   606
         * 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
   607
         * The type of the method handle will have a void return type.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   608
         * If the field is static, the method handle will take a single
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   609
         * argument, of the field's value type, the value to be stored.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   610
         * Otherwise, the two arguments will be the instance containing
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   611
         * the field, and the value to be stored.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   612
         * 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
   613
         * 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
   614
         * @param f the reflected field
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   615
         * @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
   616
         * @exception NoAccessException if access checking fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   617
         */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   618
        public MethodHandle unreflectSetter(Field f) throws NoAccessException {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   619
            return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   620
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   621
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   622
        /// Helper methods, all package-private.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   623
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   624
        MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   625
            checkSymbolicClass(refc);  // do this before attempting to resolve
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   626
            int mods = (isStatic ? Modifier.STATIC : 0);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   627
            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   628
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   629
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   630
        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   631
            checkSymbolicClass(refc);  // do this before attempting to resolve
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   632
            int mods = (isStatic ? Modifier.STATIC : 0);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   633
            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   634
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   635
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   636
        MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   637
                                 boolean searchSupers, Class<?> specialCaller) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   638
            checkSymbolicClass(refc);  // do this before attempting to resolve
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   639
            int mods = (isStatic ? Modifier.STATIC : 0);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   640
            return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   641
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   642
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   643
        void checkSymbolicClass(Class<?> refc) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   644
            Class<?> caller = lookupClassOrNull();
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   645
            if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   646
                throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   647
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   648
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   649
        void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   650
            String message;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   651
            if (m.isConstructor())
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   652
                message = "expected a method, not a constructor";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   653
            else if (!m.isMethod())
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   654
                message = "expected a method";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   655
            else if (wantStatic != m.isStatic())
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   656
                message = wantStatic ? "expected a static method" : "expected a non-static method";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   657
            else
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   658
                { checkAccess(refc, m); return; }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   659
            throw newNoAccessException(message, m, lookupClass());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   660
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   661
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   662
        void checkAccess(Class<?> refc, MemberName m) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   663
            int allowedModes = this.allowedModes;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   664
            if (allowedModes == TRUSTED)  return;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   665
            int mods = m.getModifiers();
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   666
            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   667
                return;  // common case
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   668
            int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   669
            if ((requestedModes & allowedModes) != 0
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   670
                && VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   671
                                                   mods, lookupClass()))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   672
                return;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   673
            if (((requestedModes & ~allowedModes) & PROTECTED) != 0
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   674
                && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   675
                // Protected members can also be checked as if they were package-private.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   676
                return;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   677
            throw newNoAccessException(accessFailedMessage(refc, m), m, lookupClass());
2707
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
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   680
        String accessFailedMessage(Class<?> refc, MemberName m) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   681
            Class<?> defc = m.getDeclaringClass();
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   682
            int mods = m.getModifiers();
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   683
            if (!VerifyAccess.isClassAccessible(defc, lookupClass()))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   684
                return "class is not public";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   685
            if (refc != defc && !VerifyAccess.isClassAccessible(refc, lookupClass()))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   686
                return "symbolic reference "+refc.getName()+" is not public";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   687
            if (Modifier.isPublic(mods))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   688
                return "access to public member failed";  // (how?)
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   689
            else if (allowedModes == PUBLIC)
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   690
                return "member is not public";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   691
            if (Modifier.isPrivate(mods))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   692
                return "member is private";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   693
            if (Modifier.isProtected(mods))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   694
                return "member is protected";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   695
            return "member is private to package";
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   696
        }
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   697
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   698
        void checkSpecialCaller(Class<?> specialCaller) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   699
            if (allowedModes == TRUSTED)  return;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   700
            if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   701
                throw newNoAccessException("no private access for invokespecial",
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   702
                                           new MemberName(specialCaller), lookupClass());
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   703
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   704
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   705
        MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   706
            // The accessing class only has the right to use a protected member
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   707
            // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   708
            if (!method.isProtected() || method.isStatic()
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   709
                || allowedModes == TRUSTED
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   710
                || VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass()))
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   711
                return mh;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   712
            else
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   713
                return restrictReceiver(method, mh, lookupClass());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   714
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   715
        MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   716
            assert(!method.isStatic());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   717
            Class<?> defc = method.getDeclaringClass();  // receiver type of mh is too wide
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   718
            if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   719
                throw newNoAccessException("caller class must be a subclass below the method", method, caller);
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   720
            }
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   721
            MethodType rawType = mh.type();
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   722
            if (rawType.parameterType(0) == caller)  return mh;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   723
            MethodType narrowType = rawType.changeParameterType(0, caller);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   724
            return MethodHandleImpl.convertArguments(IMPL_TOKEN, mh, narrowType, rawType, null);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   725
        }
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   726
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   727
        MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   728
                                  boolean isStatic, boolean isSetter) throws NoAccessException {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   729
            MemberName field = resolveOrFail(refc, name, type, isStatic);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   730
            if (isStatic != field.isStatic())
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   731
                throw newNoAccessException(isStatic
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   732
                                           ? "expected a static field"
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   733
                                           : "expected a non-static field",
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   734
                                           field, lookupClass());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   735
            return makeAccessor(refc, field, false, isSetter);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   736
        }
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   737
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   738
        MethodHandle makeAccessor(Class<?> refc, MemberName field,
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   739
                                  boolean trusted, boolean isSetter) throws NoAccessException {
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   740
            assert(field.isField());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   741
            if (trusted)
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   742
                return MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   743
            checkAccess(refc, field);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   744
            MethodHandle mh = MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   745
            return restrictProtectedReceiver(field, mh);
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   746
        }
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   747
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   748
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
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   751
     * 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
   752
     * 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
   753
     * 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
   754
     * and the second will be {@code int}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   755
     * @param arrayClass an array type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   756
     * @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
   757
     * @throws  IllegalArgumentException if arrayClass is not an array type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   758
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   759
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   760
    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   761
        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, false);
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
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   764
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   765
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   766
     * 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
   767
     * 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
   768
     * 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
   769
     * 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
   770
     * @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
   771
     * @throws IllegalArgumentException if arrayClass is not an array type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   772
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   773
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   774
    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   775
        return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   776
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   777
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   778
    /// method handle invocation (reflective style)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   779
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   780
    /**
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   781
     * @deprecated Alias for MethodHandle.invokeVarargs.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   782
     */
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   783
    @Deprecated
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   784
    public static
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   785
    Object invokeVarargs(MethodHandle target, Object... arguments) throws Throwable {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   786
        return target.invokeVarargs(arguments);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   787
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   788
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   789
    /**
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   790
     * @deprecated Alias for MethodHandle.invokeVarargs.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   791
     */
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   792
    @Deprecated
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   793
    public static
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   794
    Object invoke(MethodHandle target, Object... arguments) throws Throwable {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   795
        return target.invokeVarargs(arguments);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   796
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   797
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   798
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   799
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   800
     * Produce a method handle which will invoke any method handle of the
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   801
     * given type on a standard set of {@code Object} type arguments.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   802
     * The resulting invoker will be a method handle with the following
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   803
     * arguments:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   804
     * <ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   805
     * <li>a single {@code MethodHandle} target
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   806
     * <li>zero or more {@code Object} values (one for each argument in {@code type})
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   807
     * </ul>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   808
     * The invoker will apply reference casts as necessary and unbox primitive arguments,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   809
     * as if by {@link #convertArguments}.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   810
     * The return value of the invoker will be an {@code Object} reference,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   811
     * boxing a primitive value if the original type returns a primitive,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   812
     * and always null if the original type returns void.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   813
     * <p>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   814
     * This method is equivalent to the following code (though it may be more efficient):
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   815
     * <p><blockquote><pre>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   816
     * MethodHandle invoker = exactInvoker(type);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   817
     * MethodType genericType = type.generic();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   818
     * genericType = genericType.insertParameterType(0, MethodHandle.class);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   819
     * return convertArguments(invoker, genericType);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   820
     * </pre></blockquote>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   821
     * @param type the type of target methods which the invoker will apply to
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   822
     * @return a method handle suitable for invoking any method handle of the given type
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   823
     */
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   824
    static public
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   825
    MethodHandle genericInvoker(MethodType type) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   826
        return invokers(type).genericInvoker();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   827
    }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   828
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   829
    /**
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   830
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   831
     * Produce a method handle which will invoke any method handle of the
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   832
     * given type on a standard set of {@code Object} type arguments
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   833
     * and a single trailing {@code Object[]} array.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   834
     * The resulting invoker will be a method handle with the following
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   835
     * arguments:
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   836
     * <ul>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   837
     * <li>a single {@code MethodHandle} target
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   838
     * <li>zero or more {@code Object} values (counted by {@code objectArgCount})
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   839
     * <li>an {@code Object[]} array containing more arguments
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   840
     * </ul>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   841
     * The invoker will spread the varargs array, apply
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   842
     * reference casts as necessary, and unbox primitive arguments.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   843
     * 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
   844
     * 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
   845
     * and always null if the original type returns void.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   846
     * <p>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   847
     * This method is equivalent to the following code (though it may be more efficient):
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   848
     * <p><blockquote><pre>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   849
     * MethodHandle invoker = exactInvoker(type);
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   850
     * MethodType vaType = MethodType.makeGeneric(objectArgCount, true);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   851
     * vaType = vaType.insertParameterType(0, MethodHandle.class);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   852
     * return spreadArguments(invoker, vaType);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   853
     * </pre></blockquote>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   854
     * @param type the desired target type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   855
     * @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
   856
     * @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
   857
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   858
    static public
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   859
    MethodHandle varargsInvoker(MethodType type, int objectArgCount) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   860
        if (objectArgCount < 0 || objectArgCount > type.parameterCount())
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   861
            throw new IllegalArgumentException("bad argument count "+objectArgCount);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   862
        return invokers(type).varargsInvoker(objectArgCount);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   863
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   864
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   865
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   866
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   867
     * Produce a method handle which will take a invoke any method handle of the
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   868
     * 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
   869
     * 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
   870
     * an additional leading argument of type {@code MethodHandle}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   871
     * <p>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   872
     * This method is equivalent to the following code (though it may be more efficient):
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   873
     * <p><blockquote><pre>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   874
     * lookup().findVirtual(MethodHandle.class, "invoke", type);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   875
     * </pre></blockquote>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   876
     * @param type the desired target type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   877
     * @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
   878
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   879
    static public
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   880
    MethodHandle exactInvoker(MethodType type) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   881
        return invokers(type).exactInvoker();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   882
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   883
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   884
    /**
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   885
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   886
     * Produce a method handle equivalent to an invokedynamic instruction
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   887
     * which has been linked to the given call site.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   888
     * Along with {@link Lookup#findVirtual}, {@link Lookup#findStatic},
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   889
     * and {@link Lookup#findSpecial}, this completes the emulation
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   890
     * of the JVM's {@code invoke} instructions.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   891
     * <p>This method is equivalent to the following code:
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   892
     * <p><blockquote><pre>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   893
     * MethodHandle getTarget, invoker, result;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   894
     * getTarget = lookup().bind(site, "getTarget", methodType(MethodHandle.class));
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   895
     * invoker = exactInvoker(site.type());
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   896
     * result = foldArguments(invoker, getTarget)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   897
     * </pre></blockquote>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   898
     * @return a method handle which always invokes the call site's target
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   899
     */
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   900
    public static
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   901
    MethodHandle dynamicInvoker(CallSite site) {
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   902
        MethodHandle getCSTarget = GET_TARGET;
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   903
        if (getCSTarget == null)
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   904
            GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   905
                findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   906
        MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site);
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   907
        MethodHandle invoker = exactInvoker(site.type());
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   908
        return foldArguments(invoker, getTarget);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   909
    }
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
   910
    private static MethodHandle GET_TARGET = null;  // link this lazily, not eagerly
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   911
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   912
    static Invokers invokers(MethodType type) {
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   913
        return MethodTypeImpl.invokers(IMPL_TOKEN, type);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   914
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   915
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   916
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   917
     * <em>WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   918
     * 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
   919
     * 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
   920
     * 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
   921
     * The following checks and conversions are made:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   922
     * <ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   923
     * <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
   924
     *     (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
   925
     * <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
   926
     *     conversion is applied, if one exists.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   927
     * <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
   928
     *     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
   929
     *     possibly followed by a reference conversion.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   930
     *     T1 must be TW or a supertype.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   931
     * <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
   932
     *     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
   933
     *     possibly preceded by a reference conversion.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   934
     *     T0 must be TW or a supertype.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   935
     * <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
   936
     * <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
   937
     * <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
   938
     * </ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   939
     * If the value is discarded, null will be returned.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   940
     * @param valueType
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   941
     * @param value
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   942
     * @return the value, converted if necessary
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   943
     * @throws java.lang.ClassCastException if a cast fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   944
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   945
    static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   946
    <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
   947
       throws ClassCastException
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   948
    {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   949
        if (t0 == t1) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   950
            // no conversion needed; just reassert the same type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   951
            if (t0.isPrimitive())
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   952
                return Wrapper.asPrimitiveType(t1).cast(value);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   953
            else
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   954
                return Wrapper.OBJECT.cast(value, t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   955
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   956
        boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   957
        if (!prim0) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   958
            // check contract with caller
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   959
            Wrapper.OBJECT.cast(value, t0);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   960
            if (!prim1) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   961
                return Wrapper.OBJECT.cast(value, t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   962
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   963
            // convert reference to primitive by unboxing
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   964
            Wrapper w1 = Wrapper.forPrimitiveType(t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   965
            return w1.cast(value, t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   966
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   967
        // check contract with caller:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   968
        Wrapper.asWrapperType(t0).cast(value);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   969
        Wrapper w1 = Wrapper.forPrimitiveType(t1);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   970
        return w1.cast(value, t1);
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
    static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   974
    Object checkValue(Class<?> T1, Object value)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   975
       throws ClassCastException
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   976
    {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   977
        Class<?> T0;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   978
        if (value == null)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   979
            T0 = Object.class;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   980
        else
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   981
            T0 = value.getClass();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   982
        return checkValue(T0, T1, value);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   983
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   984
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   985
    /// method handle modification (creation from other method handles)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   986
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   987
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   988
     * Produce a method handle which adapts the type of the
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   989
     * given method handle to a new type by pairwise argument conversion.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   990
     * The original type and new type must have the same number of arguments.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   991
     * The resulting method handle is guaranteed to confess a type
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
   992
     * which is equal to the desired new type.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   993
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   994
     * 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
   995
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   996
     * The following conversions are applied as needed both to
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
   997
     * 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
   998
     * 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
   999
     * 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
  1000
     * 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
  1001
     * if possible:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1002
     * <ul>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1003
     * <li>If T0 and T1 are references, and T1 is not an interface type,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1004
     *     then a cast to T1 is applied.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1005
     *     (The types do not need to be related in any particular way.)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1006
     * <li>If T0 and T1 are references, and T1 is an interface type,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1007
     *     then the value of type T0 is passed as a T1 without a cast.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1008
     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1009
     * <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
  1010
     *     conversion (JLS 5.5) is applied, if one exists.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1011
     * <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
  1012
     *     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
  1013
     *     (This treatment follows the usage of the bytecode verifier.)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1014
     *     A conversion from another primitive type behaves as if
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1015
     *     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
  1016
     * <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
  1017
     *     conversion is applied if one exists, possibly followed by
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1018
     *     an reference conversion to a superclass.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1019
     *     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
  1020
     *     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
  1021
     *     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
  1022
     *     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
  1023
     * <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
  1024
     *     conversion is applied if one exists, possibly preceded by
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1025
     *     a reference conversion to a wrapper class.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1026
     *     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
  1027
     *     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
  1028
     *     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
  1029
     *     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
  1030
     *     which is then unboxed.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1031
     * <li>If the return type T1 is void, any returned value is discarded
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1032
     * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1033
     * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1034
     * </ul>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1035
     * @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
  1036
     * @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
  1037
     * @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
  1038
     *           any necessary argument conversions, and arranges for any
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1039
     *           necessary return value conversions
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1040
     * @throws IllegalArgumentException if the conversion cannot be made
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1041
     * @see MethodHandle#asType
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1042
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1043
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1044
    MethodHandle convertArguments(MethodHandle target, MethodType newType) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1045
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1046
        if (oldType.equals(newType))
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1047
            return target;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1048
        MethodHandle res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1049
                                                 newType, oldType, null);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1050
        if (res == null)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1051
            throw newIllegalArgumentException("cannot convert to "+newType+": "+target);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1052
        return res;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1053
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1054
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1055
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1056
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1057
     * 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
  1058
     * 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
  1059
     * 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
  1060
     * which is equal to the desired new type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1061
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1062
     * The given array controls the reordering.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1063
     * 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
  1064
     * {@code newType.parameterCount()}, and call {@code #O} the number
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1065
     * of outgoing parameters (the value {@code target.type().parameterCount()}).
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1066
     * 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
  1067
     * 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
  1068
     * 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
  1069
     * 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
  1070
     * argument, where {@code I} is {@code reorder[N]}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1071
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1072
     * The reordering array need not specify an actual permutation.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1073
     * 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
  1074
     * 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
  1075
     * if its index does not appear in the array.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1076
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1077
     * 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
  1078
     * values, as with {@link #convertArguments}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1079
     * @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
  1080
     * @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
  1081
     * @param reorder a string which controls the reordering
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1082
     * @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
  1083
     *           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
  1084
     *           necessary return value conversions
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1085
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1086
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1087
    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int[] reorder) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1088
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1089
        checkReorder(reorder, newType, oldType);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1090
        return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1091
                                                 newType, oldType,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1092
                                                 reorder);
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
    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
  1096
        if (reorder.length == oldType.parameterCount()) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1097
            int limit = newType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1098
            boolean bad = false;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1099
            for (int i : reorder) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1100
                if (i < 0 || i >= limit) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1101
                    bad = true; break;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1102
                }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1103
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1104
            if (!bad)  return;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1105
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1106
        throw newIllegalArgumentException("bad reorder array");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1107
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1108
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1109
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1110
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1111
     * 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
  1112
     * 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
  1113
     * 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
  1114
     * which is equal to the desired new type.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1115
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1116
     * 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
  1117
     * 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
  1118
     * 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
  1119
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1120
     * 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
  1121
     * 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
  1122
     * rules in {@link #convertArguments}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1123
     * Any additional arguments in the old type
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1124
     * are converted from the array element type T,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1125
     * again according to the rules in {@link #convertArguments}.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1126
     * The return value is converted according likewise.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1127
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1128
     * 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
  1129
     * 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
  1130
     * 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
  1131
     * 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
  1132
     * allowed to be null.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1133
     * @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
  1134
     * @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
  1135
     * @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
  1136
     *         before calling the original method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1137
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1138
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1139
    MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1140
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1141
        int inargs  = newType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1142
        int outargs = oldType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1143
        int spreadPos = inargs - 1;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1144
        int numSpread = (outargs - spreadPos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1145
        MethodHandle res = null;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1146
        if (spreadPos >= 0 && numSpread >= 0) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1147
            res = MethodHandleImpl.spreadArguments(IMPL_TOKEN, target, newType, spreadPos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1148
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1149
        if (res == null) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1150
            throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1151
        }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1152
        return res;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1153
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1154
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1155
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1156
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1157
     * 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
  1158
     * given method handle to a new type, by collecting a series of
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1159
     * trailing arguments as elements to a single argument array.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1160
     * <p>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1161
     * This method may be used as an inverse to {@link #spreadArguments}.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1162
     * 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
  1163
     * 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
  1164
     * 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
  1165
     * 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
  1166
     * into an array before the original method is called.
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1167
     * @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
  1168
     * @param newType the expected type of the new method handle
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1169
     * @return a new method handle which collects some trailing argument
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1170
     *         into an array, before calling the original method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1171
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1172
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1173
    MethodHandle collectArguments(MethodHandle target, MethodType newType) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1174
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1175
        int inargs  = newType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1176
        int outargs = oldType.parameterCount();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1177
        int collectPos = outargs - 1;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1178
        int numCollect = (inargs - collectPos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1179
        if (collectPos < 0 || numCollect < 0)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1180
            throw newIllegalArgumentException("wrong number of arguments");
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1181
        MethodHandle res = MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos, null);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1182
        if (res == null) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1183
            throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1184
        }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1185
        return res;
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1186
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1187
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1188
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1189
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1190
     * Produce a method handle which calls the original method handle {@code target},
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1191
     * after inserting the given argument(s) at the given position.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1192
     * The formal parameters to {@code target} which will be supplied by those
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1193
     * arguments are called <em>bound parameters</em>, because the new method
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1194
     * will contain bindings for those parameters take from {@code values}.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1195
     * The type of the new method handle will drop the types for the bound
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1196
     * parameters from the original target type, since the new method handle
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1197
     * will no longer require those arguments to be supplied by its callers.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1198
     * <p>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1199
     * Each given argument object must match the corresponding bound parameter type.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1200
     * If a bound parameter type is a primitive, the argument object
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1201
     * must be a wrapper, and will be unboxed to produce the primitive value.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1202
     * <p>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1203
     * The  <i>pos</i> may range between zero and <i>N</i> (inclusively),
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1204
     * where <i>N</i> is the number of argument types in resulting method handle
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1205
     * (after bound parameter types are dropped).
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1206
     * @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
  1207
     * @param pos where to insert the argument (zero for the first)
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1208
     * @param values the series of arguments to insert
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1209
     * @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
  1210
     *         before calling the original method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1211
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1212
    public static
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1213
    MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1214
        int insCount = values.length;
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1215
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1216
        ArrayList<Class<?>> ptypes =
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1217
                new ArrayList<Class<?>>(oldType.parameterList());
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1218
        int outargs = oldType.parameterCount();
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1219
        int inargs  = outargs - insCount;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1220
        if (inargs < 0)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1221
            throw newIllegalArgumentException("too many values to insert");
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1222
        if (pos < 0 || pos > inargs)
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1223
            throw newIllegalArgumentException("no argument type to append");
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1224
        MethodHandle result = target;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1225
        for (int i = 0; i < insCount; i++) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1226
            Object value = values[i];
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1227
            Class<?> valueType = oldType.parameterType(pos+i);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1228
            value = checkValue(valueType, value);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1229
            if (pos == 0 && !valueType.isPrimitive()) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1230
                // At least for now, make bound method handles a special case.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1231
                MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, result, value);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1232
                if (bmh != null) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1233
                    result = bmh;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1234
                    continue;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1235
                }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1236
                // else fall through to general adapter machinery
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1237
            }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1238
            result = MethodHandleImpl.bindArgument(IMPL_TOKEN, result, pos, value);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1239
        }
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1240
        return result;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1241
    }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1242
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1243
    @Deprecated // "use MethodHandles.insertArguments instead"
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1244
    public static
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1245
    MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1246
        return insertArguments(target, pos, value);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1247
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1248
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1249
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1250
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1251
     * 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
  1252
     * 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
  1253
     * 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
  1254
     * 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
  1255
     * <p>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1256
     * The <i>pos</i> may range between zero and <i>N</i>,
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1257
     * 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
  1258
     * meaning to drop the first or last argument (respectively),
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1259
     * or an argument somewhere in between.
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1260
     * <p>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1261
     * <b>Example:</b>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1262
     * <p><blockquote><pre>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1263
     *   MethodHandle cat = MethodHandles.lookup().
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1264
     *     findVirtual(String.class, "concat", String.class, String.class);
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
  1265
     *   System.out.println(cat.&lt;String&gt;invokeExact("x", "y")); // xy
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1266
     *   MethodHandle d0 = dropArguments(cat, 0, String.class);
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
  1267
     *   System.out.println(d0.&lt;String&gt;invokeExact("x", "y", "z")); // xy
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1268
     *   MethodHandle d1 = dropArguments(cat, 1, String.class);
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
  1269
     *   System.out.println(d1.&lt;String&gt;invokeExact("x", "y", "z")); // xz
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1270
     *   MethodHandle d2 = dropArguments(cat, 2, String.class);
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
  1271
     *   System.out.println(d2.&lt;String&gt;invokeExact("x", "y", "z")); // yz
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1272
     *   MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
  1273
     *   System.out.println(d12.&lt;String&gt;invokeExact("w", "x", "y", "z")); // wz
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1274
     * </pre></blockquote>
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1275
     * @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
  1276
     * @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
  1277
     * @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
  1278
     * @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
  1279
     *         before calling the original method handle
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1280
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1281
    public static
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1282
    MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1283
        if (valueTypes.size() == 0)  return target;
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1284
        MethodType oldType = target.type();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1285
        int outargs = oldType.parameterCount();
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1286
        int inargs  = outargs + valueTypes.size();
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1287
        if (pos < 0 || pos >= inargs)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1288
            throw newIllegalArgumentException("no argument type to remove");
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1289
        ArrayList<Class<?>> ptypes =
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1290
                new ArrayList<Class<?>>(oldType.parameterList());
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1291
        ptypes.addAll(pos, valueTypes);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1292
        MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1293
        return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1294
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1295
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1296
    public static
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1297
    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1298
        return dropArguments(target, pos, Arrays.asList(valueTypes));
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1299
    }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1300
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1301
    /**
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1302
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1303
     * Adapt a target method handle {@code target} by pre-processing
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1304
     * one or more of its arguments, each with its own unary filter function,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1305
     * and then calling the target with each pre-processed argument
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1306
     * replaced by the result of its corresponding filter function.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1307
     * <p>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1308
     * The pre-processing is performed by one or more method handles,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1309
     * specified in the non-null elements of the {@code filters} array.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1310
     * (If there are no such elements, the original target is returned.)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1311
     * Each filter (that is, each non-null element of {@code filters})
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1312
     * is applied to the corresponding argument of the adapter.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1313
     * <p>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1314
     * If a filter {@code F} applies to the {@code N}th argument of
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1315
     * the method handle, then {@code F} must be a method handle which
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1316
     * takes exactly one argument.  The type of {@code F}'s sole argument
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1317
     * replaces the corresponding argument type of the target
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1318
     * in the resulting adapted method handle.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1319
     * The return type of {@code F} must be identical to the corresponding
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1320
     * parameter type of the target.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1321
     * <p>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1322
     * It is an error if there are non-null elements of {@code filters}
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1323
     * which do not correspond to argument positions in the target.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1324
     * The actual length of the target array may be any number, it need
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1325
     * not be the same as the parameter count of the target type.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1326
     * (This provides an easy way to filter just the first argument or two
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1327
     * of a target method handle.)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1328
     * <p> Here is pseudocode for the resulting adapter:
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1329
     * <blockquote><pre>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1330
     * // there are N arguments in the A sequence
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1331
     * T target(A[N]...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1332
     * [i&lt;N] V[i] filter[i](B[i]) = filters[i] ?: identity;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1333
     * T adapter(B[N]... b) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1334
     *   A[N] a...;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1335
     *   [i&lt;N] a[i] = filter[i](b[i]);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1336
     *   return target(a...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1337
     * }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1338
     * </pre></blockquote>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1339
     * @param target the method handle to invoke after arguments are filtered
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1340
     * @param filters method handles to call initially on filtered arguments
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1341
     * @return method handle which incorporates the specified argument filtering logic
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1342
     * @throws IllegalArgumentException if a non-null element of {@code filters}
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1343
     *          does not match a corresponding argument type of {@code target}
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1344
     */
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1345
    public static
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1346
    MethodHandle filterArguments(MethodHandle target, MethodHandle... filters) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1347
        MethodType targetType = target.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1348
        MethodHandle adapter = target;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1349
        MethodType adapterType = targetType;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1350
        int pos = -1, maxPos = targetType.parameterCount();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1351
        for (MethodHandle filter : filters) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1352
            pos += 1;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1353
            if (filter == null)  continue;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1354
            if (pos >= maxPos)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1355
                throw newIllegalArgumentException("too many filters");
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1356
            MethodType filterType = filter.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1357
            if (filterType.parameterCount() != 1
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1358
                || filterType.returnType() != targetType.parameterType(pos))
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1359
                throw newIllegalArgumentException("target and filter types do not match");
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1360
            adapterType = adapterType.changeParameterType(pos, filterType.parameterType(0));
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1361
            adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, pos, filter);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1362
        }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1363
        MethodType midType = adapter.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1364
        if (midType != adapterType)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1365
            adapter = MethodHandleImpl.convertArguments(IMPL_TOKEN, adapter, adapterType, midType, null);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1366
        return adapter;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1367
    }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1368
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1369
    /**
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1370
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1371
     * Adapt a target method handle {@code target} by pre-processing
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1372
     * some of its arguments, and then calling the target with
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1373
     * the result of the pre-processing, plus all original arguments.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1374
     * <p>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1375
     * The pre-processing is performed by a second method handle, the {@code combiner}.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1376
     * The first {@code N} arguments passed to the adapter,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1377
     * are copied to the combiner, which then produces a result.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1378
     * (Here, {@code N} is defined as the parameter count of the adapter.)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1379
     * After this, control passes to the {@code target}, with both the result
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1380
     * of the combiner, and all the original incoming arguments.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1381
     * <p>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1382
     * The first argument type of the target must be identical with the
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1383
     * return type of the combiner.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1384
     * The resulting adapter is the same type as the target, except that the
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1385
     * initial argument type of the target is dropped.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1386
     * <p>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1387
     * (Note that {@link #dropArguments} can be used to remove any arguments
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1388
     * that either the {@code combiner} or {@code target} does not wish to receive.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1389
     * If some of the incoming arguments are destined only for the combiner,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1390
     * consider using {@link #collectArguments} instead, since those
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1391
     * arguments will not need to be live on the stack on entry to the
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1392
     * target.)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1393
     * <p>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1394
     * The first argument of the target must be identical with the
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1395
     * return value of the combiner.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1396
     * <p> Here is pseudocode for the resulting adapter:
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1397
     * <blockquote><pre>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1398
     * // there are N arguments in the A sequence
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1399
     * T target(V, A[N]..., B...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1400
     * V combiner(A...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1401
     * T adapter(A... a, B... b) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1402
     *   V v = combiner(a...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1403
     *   return target(v, a..., b...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1404
     * }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1405
     * </pre></blockquote>
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1406
     * @param target the method handle to invoke after arguments are combined
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1407
     * @param combiner method handle to call initially on the incoming arguments
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1408
     * @return method handle which incorporates the specified argument folding logic
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1409
     * @throws IllegalArgumentException if the first argument type of
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1410
     *          {@code target} is not the same as {@code combiner}'s return type,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1411
     *          or if the next {@code foldArgs} argument types of {@code target}
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1412
     *          are not identical with the argument types of {@code combiner}
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1413
     */
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1414
    public static
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1415
    MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1416
        MethodType targetType = target.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1417
        MethodType combinerType = combiner.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1418
        int foldArgs = combinerType.parameterCount();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1419
        boolean ok = (targetType.parameterCount() >= 1 + foldArgs);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1420
        if (!ok)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1421
            throw misMatchedTypes("target and combiner types", targetType, combinerType);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1422
        MethodType newType = targetType.dropParameterTypes(0, 1);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1423
        return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1424
    }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1425
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1426
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1427
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1428
     * 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
  1429
     * 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
  1430
     * 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
  1431
     * All three method handles must have the same corresponding
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1432
     * argument and return types, except that the return type
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1433
     * of the test must be boolean, and the test is allowed
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1434
     * to have fewer arguments than the other two method handles.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1435
     * <p> Here is pseudocode for the resulting adapter:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1436
     * <blockquote><pre>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1437
     * boolean test(A...);
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1438
     * T target(A...,B...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1439
     * T fallback(A...,B...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1440
     * T adapter(A... a,B... b) {
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1441
     *   if (test(a...))
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1442
     *     return target(a..., b...);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1443
     *   else
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1444
     *     return fallback(a..., b...);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1445
     * }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1446
     * </pre></blockquote>
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1447
     * @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
  1448
     * @param target method handle to call if test passes
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1449
     * @param fallback method handle to call if test fails
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1450
     * @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
  1451
     * @throws IllegalArgumentException if {@code test} does not return boolean,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1452
     *          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
  1453
     *          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
  1454
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1455
    public static
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1456
    MethodHandle guardWithTest(MethodHandle test,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1457
                               MethodHandle target,
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1458
                               MethodHandle fallback) {
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1459
        MethodType gtype = test.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1460
        MethodType ttype = target.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1461
        MethodType ftype = fallback.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1462
        if (ttype != ftype)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1463
            throw misMatchedTypes("target and fallback types", ttype, ftype);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1464
        MethodType gtype2 = ttype.changeReturnType(boolean.class);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1465
        if (gtype2 != gtype) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1466
            if (gtype.returnType() != boolean.class)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1467
                throw newIllegalArgumentException("guard type is not a predicate "+gtype);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1468
            int gpc = gtype.parameterCount(), tpc = ttype.parameterCount();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1469
            if (gpc < tpc) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1470
                test = dropArguments(test, gpc, ttype.parameterList().subList(gpc, tpc));
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1471
                gtype = test.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1472
            }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1473
            if (gtype2 != gtype)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1474
                throw misMatchedTypes("target and test types", ttype, gtype);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1475
        }
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1476
        /* {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1477
            MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1478
            static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1479
                return z ? t : f;
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1480
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1481
            static MethodHandle compose(MethodHandle f, MethodHandle g) {
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1482
                Class<?> initargs = g.type().parameterArray();
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1483
                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
  1484
                return combineArguments(f, g);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1485
            }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1486
            // choose = \z.(z ? target : fallback)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1487
            MethodHandle choose = findVirtual(MethodHandles.class, "choose",
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1488
                    MethodType.methodType(boolean.class, MethodHandle.class, MethodHandle.class));
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1489
            choose = appendArgument(choose, target);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1490
            choose = appendArgument(choose, fallback);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1491
            MethodHandle dispatch = compose(choose, test);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1492
            // dispatch = \(a...).(test(a...) ? target : fallback)
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1493
            return combineArguments(invoke, dispatch, 0);
5722
4ada807383c8 6939134: JSR 292 adjustments to method handle invocation
jrose
parents: 4537
diff changeset
  1494
            // return \(a...).((test(a...) ? target : fallback).invokeExact(a...))
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1495
        } */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1496
        return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1497
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1498
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1499
    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1500
        return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1501
    }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1502
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1503
    /**
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1504
     * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1505
     * Make a method handle which adapts a target method handle,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1506
     * by running it inside an exception handler.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1507
     * If the target returns normally, the adapter returns that value.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1508
     * If an exception matching the specified type is thrown, the fallback
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1509
     * handle is called instead on the exception, plus the original arguments.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1510
     * <p>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1511
     * The handler must have leading parameter of {@code exType} or a supertype,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1512
     * followed by arguments which correspond <em>(how? TBD)</em> to
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1513
     * all the parameters of the target.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1514
     * The target and handler must return the same type.
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1515
     * <p> Here is pseudocode for the resulting adapter:
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1516
     * <blockquote><pre>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1517
     * T target(A...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1518
     * T handler(ExType, A...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1519
     * T adapter(A... a) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1520
     *   try {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1521
     *     return target(a...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1522
     *   } catch (ExType ex) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1523
     *     return handler(ex, a...);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1524
     *   }
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1525
     * }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1526
     * </pre></blockquote>
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1527
     * @param target method handle to call
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1528
     * @param exType the type of exception which the handler will catch
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1529
     * @param handler method handle to call if a matching exception is thrown
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1530
     * @return method handle which incorporates the specified try/catch logic
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1531
     * @throws IllegalArgumentException if {@code handler} does not accept
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1532
     *          the given exception type, or if the method handle types do
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1533
     *          not match in their return types and their
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1534
     *          corresponding parameters
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1535
     */
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1536
    public static
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1537
    MethodHandle catchException(MethodHandle target,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1538
                                Class<? extends Throwable> exType,
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1539
                                MethodHandle handler) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1540
        MethodType targetType = target.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1541
        MethodType handlerType = handler.type();
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1542
        boolean ok = (targetType.parameterCount() ==
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1543
                      handlerType.parameterCount() - 1);
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1544
//        for (int i = 0; ok && i < numExArgs; i++) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1545
//            if (targetType.parameterType(i) != handlerType.parameterType(1+i))
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1546
//                ok = false;
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1547
//        }
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1548
        if (!ok)
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1549
            throw newIllegalArgumentException("target and handler types do not match");
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1550
        return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1551
    }
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1552
4537
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1553
    /**
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1554
     * Produce a method handle which will throw exceptions of the given {@code exType}.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1555
     * The method handle will accept a single argument of {@code exType},
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1556
     * and immediately throw it as an exception.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1557
     * The method type will nominally specify a return of {@code returnType}.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1558
     * The return type may be anything convenient:  It doesn't matter to the
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1559
     * method handle's behavior, since it will never return normally.
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1560
     */
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1561
    public static
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1562
    MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1563
        return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
7c3c7f8d5195 6914665: update jdk code for JSR 292 (post 6858164)
jrose
parents: 2764
diff changeset
  1564
    }
2707
5a17df307cbc 6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff changeset
  1565
}