author | jrose |
Sat, 30 Oct 2010 21:08:23 -0700 | |
changeset 7555 | a279ebc3b25c |
parent 7554 | 8a0ad9757002 |
child 7556 | 4a5711d43948 |
permissions | -rw-r--r-- |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1 |
/* |
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
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 | 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 | 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 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
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 sun.dyn.*; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
29 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
30 |
import sun.dyn.Access; |
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 |
|
4537 | 33 |
import static java.dyn.MethodHandles.invokers; // package-private API |
34 |
import static sun.dyn.MemberName.newIllegalArgumentException; // utility |
|
35 |
||
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
36 |
/** |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
37 |
* A method handle is a typed, directly executable reference to a method, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
38 |
* constructor, field, or similar low-level operation, with optional |
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
39 |
* transformations of arguments or return values. |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
40 |
* These transformations are quite general, and include such patterns as |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
41 |
* {@linkplain #asType conversion}, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
42 |
* {@linkplain #bindTo insertion}, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
43 |
* {@linkplain java.dyn.MethodHandles#dropArguments deletion}, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
44 |
* and {@linkplain java.dyn.MethodHandles#filterArguments substitution}. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
45 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
46 |
* <em>Note: The super-class of MethodHandle is Object. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
47 |
* Any other super-class visible in the Reference Implementation |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
48 |
* will be removed before the Proposed Final Draft. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
49 |
* Also, the final version will not include any public or |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
50 |
* protected constructors.</em> |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
51 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
52 |
* Method handles are strongly typed according to signature. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
53 |
* They are not distinguished by method name or enclosing class. |
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
54 |
* A method handle must be invoked under a signature which matches |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
55 |
* the method handle's own {@linkplain MethodType method type}. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
56 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
57 |
* Every method handle reports its type via the {@link #type type} accessor. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
58 |
* The structure of this type is a series of classes, one of which is |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
59 |
* the return type of the method (or {@code void.class} if none). |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
60 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
61 |
* Every method handle appears as an object containing a method named |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
62 |
* {@link #invokeExact invokeExact}, whose signature exactly matches |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
63 |
* the method handle's type. |
4537 | 64 |
* A Java method call expression, which compiles to an |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
65 |
* {@code invokevirtual} instruction, |
4537 | 66 |
* can invoke this method from Java source code. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
67 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
68 |
* Every call to a method handle specifies an intended method type, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
69 |
* which must exactly match the type of the method handle. |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
70 |
* (The type is specified in the {@code invokevirtual} instruction, |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
71 |
* via a {@code CONSTANT_NameAndType} constant pool entry.) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
72 |
* The call looks within the receiver object for a method |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
73 |
* named {@code invokeExact} of the intended method type. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
74 |
* The call fails with a {@link WrongMethodTypeException} |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
75 |
* if the method does not exist, even if there is an {@code invokeExact} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
76 |
* method of a closely similar signature. |
4537 | 77 |
* As with other kinds |
78 |
* of methods in the JVM, signature matching during method linkage |
|
79 |
* is exact, and does not allow for language-level implicit conversions |
|
80 |
* such as {@code String} to {@code Object} or {@code short} to {@code int}. |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
81 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
82 |
* Each individual method handle also contains a method named |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
83 |
* {@link #invokeGeneric invokeGeneric}, whose type is the same |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
84 |
* as {@code invokeExact}, and is therefore also reported by |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
85 |
* the {@link #type type} accessor. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
86 |
* A call to {@code invokeGeneric} works the same as a call to |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
87 |
* {@code invokeExact}, if the signature specified by the caller |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
88 |
* exactly matches the method handle's own type. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
89 |
* If there is a type mismatch, {@code invokeGeneric} attempts |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
90 |
* to adjust the type of the target method handle |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
91 |
* (as if by a call to {@link #asType asType}) |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
92 |
* to obtain an exactly invokable target. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
93 |
* This allows a more powerful negotiation of method type |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
94 |
* between caller and callee. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
95 |
* <p> |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
96 |
* A method handle is an unrestricted capability to call a method. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
97 |
* A method handle can be formed on a non-public method by a class |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
98 |
* that has access to that method; the resulting handle can be used |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
99 |
* in any place by any caller who receives a reference to it. Thus, access |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
100 |
* checking is performed when the method handle is created, not |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
101 |
* (as in reflection) every time it is called. Handles to non-public |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
102 |
* methods, or in non-public classes, should generally be kept secret. |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
103 |
* They should not be passed to untrusted code unless their use from |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
104 |
* the untrusted code would be harmless. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
105 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
106 |
* Bytecode in the JVM can directly call a method handle's |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
107 |
* {@code invokeExact} method from an {@code invokevirtual} instruction. |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
108 |
* The receiver class type must be {@code MethodHandle} and the method name |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
109 |
* must be {@code invokeExact}. The signature of the invocation |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
110 |
* (after resolving symbolic type names) must exactly match the method type |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
111 |
* of the target method. |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
112 |
* Similarly, bytecode can directly call a method handle's {@code invokeGeneric} |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
113 |
* method. The signature of the invocation (after resolving symbolic type names) |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
114 |
* must either exactly match the method type or be a valid argument to |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
115 |
* the target's {@link #asType asType} method. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
116 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
117 |
* Every {@code invokeExact} and {@code invokeGeneric} method always |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
118 |
* throws {@link java.lang.Throwable Throwable}, |
4537 | 119 |
* which is to say that there is no static restriction on what a method handle |
120 |
* can throw. Since the JVM does not distinguish between checked |
|
121 |
* and unchecked exceptions (other than by their class, of course), |
|
122 |
* there is no particular effect on bytecode shape from ascribing |
|
123 |
* checked exceptions to method handle invocations. But in Java source |
|
124 |
* code, methods which perform method handle calls must either explicitly |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
125 |
* throw {@code java.lang.Throwable Throwable}, or else must catch all |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
126 |
* throwables locally, rethrowing only those which are legal in the context, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
127 |
* and wrapping ones which are illegal. |
4537 | 128 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
129 |
* Bytecode in the JVM can directly obtain a method handle |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
130 |
* for any accessible method from a {@code ldc} instruction |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
131 |
* which refers to a {@code CONSTANT_Methodref} or |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
132 |
* {@code CONSTANT_InterfaceMethodref} constant pool entry. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
133 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
134 |
* Java code can also use a reflective API called |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
135 |
* {@link java.dyn.MethodHandles.Lookup MethodHandles.Lookup} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
136 |
* for creating and calling method handles. |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
137 |
* For example, a static method handle can be obtained |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
138 |
* from {@link java.dyn.MethodHandles.Lookup#findStatic Lookup.findStatic}. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
139 |
* There are also bridge methods from Core Reflection API objects, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
140 |
* such as {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.ureflect}. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
141 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
142 |
* A method reference may refer either to a static or non-static method. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
143 |
* In the non-static case, the method handle type includes an explicit |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
144 |
* receiver argument, prepended before any other arguments. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
145 |
* In the method handle's type, the initial receiver argument is typed |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
146 |
* according to the class under which the method was initially requested. |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
147 |
* (E.g., if a non-static method handle is obtained via {@code ldc}, |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
148 |
* the type of the receiver is the class named in the constant pool entry.) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
149 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
150 |
* When a method handle to a virtual method is invoked, the method is |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
151 |
* always looked up in the receiver (that is, the first argument). |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
152 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
153 |
* A non-virtual method handles to a specific virtual method implementation |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
154 |
* can also be created. These do not perform virtual lookup based on |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
155 |
* receiver type. Such a method handle simulates the effect of |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
156 |
* an {@code invokespecial} instruction to the same method. |
4537 | 157 |
* <p> |
158 |
* Here are some examples of usage: |
|
159 |
* <p><blockquote><pre> |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
160 |
Object x, y; String s; int i; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
161 |
MethodType mt; MethodHandle mh; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
162 |
MethodHandles.Lookup lookup = MethodHandles.lookup(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
163 |
// mt is {(char,char) => String} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
164 |
mt = MethodType.methodType(String.class, char.class, char.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
165 |
mh = lookup.findVirtual(String.class, "replace", mt); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
166 |
// (Ljava/lang/String;CC)Ljava/lang/String; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
167 |
s = mh.<String>invokeExact("daddy",'d','n'); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
168 |
assert(s.equals("nanny")); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
169 |
// weakly typed invocation (using MHs.invoke) |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
170 |
s = (String) mh.invokeWithArguments("sappy", 'p', 'v'); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
171 |
assert(s.equals("savvy")); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
172 |
// mt is {Object[] => List} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
173 |
mt = MethodType.methodType(java.util.List.class, Object[].class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
174 |
mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
175 |
// mt is {(Object,Object,Object) => Object} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
176 |
mt = MethodType.genericMethodType(3); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
177 |
mh = MethodHandles.collectArguments(mh, mt); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
178 |
// mt is {(Object,Object,Object) => Object} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
179 |
// (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
180 |
x = mh.invokeExact((Object)1, (Object)2, (Object)3); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
181 |
assert(x.equals(java.util.Arrays.asList(1,2,3))); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
182 |
// mt is { => int} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
183 |
mt = MethodType.methodType(int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
184 |
mh = lookup.findVirtual(java.util.List.class, "size", mt); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
185 |
// (Ljava/util/List;)I |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
186 |
i = mh.<int>invokeExact(java.util.Arrays.asList(1,2,3)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
187 |
assert(i == 3); |
4537 | 188 |
* </pre></blockquote> |
189 |
* Each of the above calls generates a single invokevirtual instruction |
|
190 |
* with the name {@code invoke} and the type descriptors indicated in the comments. |
|
191 |
* The argument types are taken directly from the actual arguments, |
|
192 |
* while the return type is taken from the type parameter. |
|
193 |
* (This type parameter may be a primitive, and it defaults to {@code Object}.) |
|
194 |
* <p> |
|
195 |
* <em>A note on generic typing:</em> Method handles do not represent |
|
196 |
* their function types in terms of Java parameterized (generic) types, |
|
197 |
* because there are three mismatches between function types and parameterized |
|
198 |
* Java types. |
|
199 |
* <ol> |
|
200 |
* <li>Method types range over all possible arities, |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
201 |
* from no arguments to up to 255 of arguments (a limit imposed by the JVM). |
4537 | 202 |
* Generics are not variadic, and so cannot represent this.</li> |
203 |
* <li>Method types can specify arguments of primitive types, |
|
204 |
* which Java generic types cannot range over.</li> |
|
205 |
* <li>Higher order functions over method handles (combinators) are |
|
206 |
* often generic across a wide range of function types, including |
|
207 |
* those of multiple arities. It is impossible to represent such |
|
208 |
* genericity with a Java type parameter.</li> |
|
209 |
* </ol> |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
210 |
* Signature polymorphic methods in this class appear to be documented |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
211 |
* as having type parameters for return types and a parameter, but that is |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
212 |
* merely a documentation convention. These type parameters do |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
213 |
* not play a role in type-checking method handle invocations. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
214 |
* <p> |
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
215 |
* Like classes and strings, method handles that correspond to accessible |
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
216 |
* fields, methods, and constructors can be represented directly |
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
217 |
* in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes. |
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
218 |
* Loading such a constant causes the component classes of its type to be loaded as necessary. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
219 |
* |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
220 |
* @see MethodType |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
221 |
* @see MethodHandles |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
222 |
* @author John Rose, JSR 292 EG |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
223 |
*/ |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
224 |
public abstract class MethodHandle |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
225 |
// Note: This is an implementation inheritance hack, and will be removed |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
226 |
// with a JVM change which moves the required hidden state onto this class. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
227 |
extends MethodHandleImpl |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
228 |
{ |
4537 | 229 |
private static Access IMPL_TOKEN = Access.getToken(); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
230 |
|
4537 | 231 |
// interface MethodHandle<R throws X extends Exception,A...> |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
232 |
// { MethodType<R throws X,A...> type(); public R invokeExact(A...) throws X; } |
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 |
/** |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
235 |
* Internal marker interface which distinguishes (to the Java compiler) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
236 |
* those methods which are signature polymorphic. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
237 |
*/ |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
238 |
@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.TYPE}) |
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
239 |
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
240 |
@interface PolymorphicSignature { } |
4537 | 241 |
|
242 |
private MethodType type; |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
243 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
244 |
/** |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
245 |
* Report the type of this method handle. |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
246 |
* Every invocation of this method handle via {@code invokeExact} must exactly match this type. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
247 |
* @return the method handle type |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
248 |
*/ |
4537 | 249 |
public final MethodType type() { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
250 |
return type; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
251 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
252 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
253 |
/** |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
254 |
* <em>CONSTRUCTOR WILL BE REMOVED FOR PFD:</em> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
255 |
* Temporary constructor in early versions of the Reference Implementation. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
256 |
* Method handle inheritance (if any) will be contained completely within |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
257 |
* the {@code java.dyn} package. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
258 |
*/ |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
259 |
// The constructor for MethodHandle may only be called by privileged code. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
260 |
// Subclasses may be in other packages, but must possess |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
261 |
// a token which they obtained from MH with a security check. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
262 |
// @param token non-null object which proves access permission |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
263 |
// @param type type (permanently assigned) of the new method handle |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
264 |
protected MethodHandle(Access token, MethodType type) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
265 |
super(token); |
4537 | 266 |
Access.check(token); |
267 |
this.type = type; |
|
268 |
} |
|
269 |
||
270 |
private void initType(MethodType type) { |
|
271 |
type.getClass(); // elicit NPE |
|
272 |
if (this.type != null) throw new InternalError(); |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
273 |
this.type = type; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
274 |
} |
4537 | 275 |
|
276 |
static { |
|
277 |
// This hack allows the implementation package special access to |
|
278 |
// the internals of MethodHandle. In particular, the MTImpl has all sorts |
|
279 |
// of cached information useful to the implementation code. |
|
280 |
MethodHandleImpl.setMethodHandleFriend(IMPL_TOKEN, new MethodHandleImpl.MethodHandleFriend() { |
|
281 |
public void initType(MethodHandle mh, MethodType type) { mh.initType(type); } |
|
282 |
}); |
|
283 |
} |
|
284 |
||
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
285 |
/** Produce a printed representation that displays information about this call site |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
286 |
* that may be useful to the human reader. |
4537 | 287 |
*/ |
288 |
@Override |
|
289 |
public String toString() { |
|
290 |
return MethodHandleImpl.getNameString(IMPL_TOKEN, this); |
|
291 |
} |
|
292 |
||
293 |
/** |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
294 |
* Invoke the method handle, allowing any caller signature, but requiring an exact signature match. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
295 |
* The signature at the call site of {@code invokeExact} must |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
296 |
* exactly match this method handle's {@link #type type}. |
4537 | 297 |
* No conversions are allowed on arguments or return values. |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
298 |
* @throws WrongMethodTypeException if the target's type is not identical with the caller's type signature |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
299 |
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call |
4537 | 300 |
*/ |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
301 |
public final native @PolymorphicSignature <R,A> R invokeExact(A... args) throws Throwable; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
302 |
|
4537 | 303 |
/** |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
304 |
* Invoke the method handle, allowing any caller signature, |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
305 |
* and optionally performing conversions for arguments and return types. |
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
306 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
307 |
* If the call site signature exactly matches this method handle's {@link #type type}, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
308 |
* the call proceeds as if by {@link #invokeExact invokeExact}. |
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
309 |
* <p> |
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
310 |
* Otherwise, the call proceeds as if this method handle were first |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
311 |
* adjusted by calling {@link #asType asType} to adjust this method handle |
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
312 |
* to the required type, and then the call proceeds as if by |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
313 |
* {@link #invokeExact invokeExact} on the adjusted method handle. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
314 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
315 |
* There is no guarantee that the {@code asType} call is actually made. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
316 |
* If the JVM can predict the results of making the call, it may perform |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
317 |
* adaptations directly on the caller's arguments, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
318 |
* and call the target method handle according to its own exact type. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
319 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
320 |
* If the method handle is equipped with a |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
321 |
* {@linkplain #withTypeHandler type handler}, the handler must produce |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
322 |
* an entry point of the call site's exact type. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
323 |
* Otherwise, the signature at the call site of {@code invokeGeneric} must |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
324 |
* be a valid argument to the standard {@code asType} method. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
325 |
* In particular, the caller must specify the same argument arity |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
326 |
* as the callee's type. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
327 |
* @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type signature |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
328 |
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call |
4537 | 329 |
*/ |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
330 |
public final native @PolymorphicSignature <R,A> R invokeGeneric(A... args) throws Throwable; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
331 |
|
4537 | 332 |
/** |
333 |
* Perform a varargs invocation, passing the arguments in the given array |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
334 |
* to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site |
4537 | 335 |
* which mentions only the type {@code Object}, and whose arity is the length |
336 |
* of the argument array. |
|
337 |
* <p> |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
338 |
* Specifically, execution proceeds as if by the following steps, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
339 |
* although the methods are not guaranteed to be called if the JVM |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
340 |
* can predict their effects. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
341 |
* <ul> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
342 |
* <li>Determine the length of the argument array as {@code N}. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
343 |
* For a null reference, {@code N=0}. </li> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
344 |
* <li>Determine the generic type {@code TN} of {@code N} arguments as |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
345 |
* as {@code TN=MethodType.genericMethodType(N)}.</li> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
346 |
* <li>Force the original target method handle {@code MH0} to the |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
347 |
* required type, as {@code MH1 = MH0.asType(TN)}. </li> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
348 |
* <li>Spread the array into {@code N} separate arguments {@code A0, ...}. </li> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
349 |
* <li>Invoke the type-adjusted method handle on the unpacked arguments: |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
350 |
* MH1.invokeExact(A0, ...). </li> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
351 |
* <li>Take the return value as an {@code Object} reference. </li> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
352 |
* </ul> |
4537 | 353 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
354 |
* Because of the action of the {@code asType} step, the following argument |
4537 | 355 |
* conversions are applied as necessary: |
356 |
* <ul> |
|
357 |
* <li>reference casting |
|
358 |
* <li>unboxing |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
359 |
* <li>widening primitive conversions |
4537 | 360 |
* </ul> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
361 |
* <p> |
4537 | 362 |
* The result returned by the call is boxed if it is a primitive, |
363 |
* or forced to null if the return type is void. |
|
364 |
* <p> |
|
365 |
* This call is equivalent to the following code: |
|
366 |
* <p><blockquote><pre> |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
367 |
* MethodHandle invoker = MethodHandles.varargsInvoker(this.type(), 0); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
368 |
* Object result = invoker.invokeExact(this, arguments); |
4537 | 369 |
* </pre></blockquote> |
370 |
* @param arguments the arguments to pass to the target |
|
371 |
* @return the result returned by the target |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
372 |
* @throws WrongMethodTypeException if the target's type cannot be adjusted to take the arguments |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
373 |
* @throws Throwable anything thrown by the target method invocation |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
374 |
* @see MethodHandles#varargsInvoker |
4537 | 375 |
*/ |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
376 |
public final Object invokeWithArguments(Object... arguments) throws Throwable { |
4537 | 377 |
int argc = arguments == null ? 0 : arguments.length; |
378 |
MethodType type = type(); |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
379 |
if (type.parameterCount() != argc) { |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
380 |
// simulate invokeGeneric |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
381 |
return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
382 |
} |
4537 | 383 |
if (argc <= 10) { |
384 |
MethodHandle invoker = MethodHandles.invokers(type).genericInvoker(); |
|
385 |
switch (argc) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
386 |
case 0: return invoker.invokeExact(this); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
387 |
case 1: return invoker.invokeExact(this, |
4537 | 388 |
arguments[0]); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
389 |
case 2: return invoker.invokeExact(this, |
4537 | 390 |
arguments[0], arguments[1]); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
391 |
case 3: return invoker.invokeExact(this, |
4537 | 392 |
arguments[0], arguments[1], arguments[2]); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
393 |
case 4: return invoker.invokeExact(this, |
4537 | 394 |
arguments[0], arguments[1], arguments[2], |
395 |
arguments[3]); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
396 |
case 5: return invoker.invokeExact(this, |
4537 | 397 |
arguments[0], arguments[1], arguments[2], |
398 |
arguments[3], arguments[4]); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
399 |
case 6: return invoker.invokeExact(this, |
4537 | 400 |
arguments[0], arguments[1], arguments[2], |
401 |
arguments[3], arguments[4], arguments[5]); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
402 |
case 7: return invoker.invokeExact(this, |
4537 | 403 |
arguments[0], arguments[1], arguments[2], |
404 |
arguments[3], arguments[4], arguments[5], |
|
405 |
arguments[6]); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
406 |
case 8: return invoker.invokeExact(this, |
4537 | 407 |
arguments[0], arguments[1], arguments[2], |
408 |
arguments[3], arguments[4], arguments[5], |
|
409 |
arguments[6], arguments[7]); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
410 |
case 9: return invoker.invokeExact(this, |
4537 | 411 |
arguments[0], arguments[1], arguments[2], |
412 |
arguments[3], arguments[4], arguments[5], |
|
413 |
arguments[6], arguments[7], arguments[8]); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
414 |
case 10: return invoker.invokeExact(this, |
4537 | 415 |
arguments[0], arguments[1], arguments[2], |
416 |
arguments[3], arguments[4], arguments[5], |
|
417 |
arguments[6], arguments[7], arguments[8], |
|
418 |
arguments[9]); |
|
419 |
} |
|
420 |
} |
|
421 |
||
422 |
// more than ten arguments get boxed in a varargs list: |
|
423 |
MethodHandle invoker = MethodHandles.invokers(type).varargsInvoker(0); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
424 |
return invoker.invokeExact(this, arguments); |
4537 | 425 |
} |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
426 |
/** Equivalent to {@code invokeWithArguments(arguments.toArray())}. */ |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
427 |
public final Object invokeWithArguments(java.util.List<?> arguments) throws Throwable { |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
428 |
return invokeWithArguments(arguments.toArray()); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
429 |
} |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
430 |
@Deprecated |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
431 |
public final Object invokeVarargs(Object... arguments) throws Throwable { |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
432 |
return invokeWithArguments(arguments); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
433 |
} |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
434 |
@Deprecated |
4537 | 435 |
public final Object invokeVarargs(java.util.List<?> arguments) throws Throwable { |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
436 |
return invokeWithArguments(arguments.toArray()); |
4537 | 437 |
} |
438 |
||
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
439 |
/** |
4537 | 440 |
* Produce an adapter method handle which adapts the type of the |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
441 |
* current method handle to a new type |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
442 |
* The resulting method handle is guaranteed to report a type |
4537 | 443 |
* which is equal to the desired new type. |
444 |
* <p> |
|
445 |
* If the original type and new type are equal, returns {@code this}. |
|
446 |
* <p> |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
447 |
* This method provides the crucial behavioral difference between |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
448 |
* {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}. The two methods |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
449 |
* perform the same steps when the caller's type descriptor is identical |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
450 |
* with the callee's, but when the types differ, {@link #invokeGeneric invokeGeneric} |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
451 |
* also calls {@code asType} (or some internal equivalent) in order |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
452 |
* to match up the caller's and callee's types. |
4537 | 453 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
454 |
* This method is equivalent to {@link MethodHandles#convertArguments convertArguments}, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
455 |
* except for method handles produced by {@link #withTypeHandler withTypeHandler}, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
456 |
* in which case the specified type handler is used for calls to {@code asType}. |
4537 | 457 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
458 |
* Note that the default behavior of {@code asType} only performs |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
459 |
* pairwise argument conversion and return value conversion. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
460 |
* Because of this, unless the method handle has a type handler, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
461 |
* the original type and new type must have the same number of arguments. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
462 |
* |
4537 | 463 |
* @param newType the expected type of the new method handle |
464 |
* @return a method handle which delegates to {@code this} after performing |
|
465 |
* any necessary argument conversions, and arranges for any |
|
466 |
* necessary return value conversions |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
467 |
* @throws WrongMethodTypeException if the conversion cannot be made |
4537 | 468 |
* @see MethodHandles#convertArguments |
469 |
*/ |
|
7554
8a0ad9757002
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
7051
diff
changeset
|
470 |
public MethodHandle asType(MethodType newType) { |
4537 | 471 |
return MethodHandles.convertArguments(this, newType); |
472 |
} |
|
473 |
||
474 |
/** |
|
475 |
* Produce a method handle which adapts, as its <i>target</i>, |
|
476 |
* the current method handle. The type of the adapter will be |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
477 |
* the same as the type of the target, except that the final |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
478 |
* {@code arrayLength} parameters of the target's type are replaced |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
479 |
* by a single array parameter of type {@code arrayType}. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
480 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
481 |
* If the array element type differs from any of the corresponding |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
482 |
* argument types on original target, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
483 |
* the original target is adapted to take the array elements directly, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
484 |
* as if by a call to {@link #asType asType}. |
4537 | 485 |
* <p> |
486 |
* When called, the adapter replaces a trailing array argument |
|
487 |
* by the array's elements, each as its own argument to the target. |
|
488 |
* (The order of the arguments is preserved.) |
|
489 |
* They are converted pairwise by casting and/or unboxing |
|
490 |
* to the types of the trailing parameters of the target. |
|
491 |
* Finally the target is called. |
|
492 |
* What the target eventually returns is returned unchanged by the adapter. |
|
493 |
* <p> |
|
494 |
* Before calling the target, the adapter verifies that the array |
|
495 |
* contains exactly enough elements to provide a correct argument count |
|
496 |
* to the target method handle. |
|
497 |
* (The array may also be null when zero elements are required.) |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
498 |
* @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
499 |
* @param arrayLength the number of arguments to spread from an incoming array argument |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
500 |
* @return a new method handle which spreads its final array argument, |
4537 | 501 |
* before calling the original method handle |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
502 |
* @throws IllegalArgumentException if {@code arrayType} is not an array type |
4537 | 503 |
* @throws IllegalArgumentException if target does not have at least |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
504 |
* {@code arrayLength} parameter types |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
505 |
* @throws WrongMethodTypeException if the implied {@code asType} call fails |
4537 | 506 |
*/ |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
507 |
public final MethodHandle asSpreader(Class<?> arrayType, int arrayLength) { |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
508 |
Class<?> arrayElement = arrayType.getComponentType(); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
509 |
if (arrayElement == null) throw newIllegalArgumentException("not an array type"); |
4537 | 510 |
MethodType oldType = type(); |
511 |
int nargs = oldType.parameterCount(); |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
512 |
if (nargs < arrayLength) throw newIllegalArgumentException("bad spread array length"); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
513 |
int keepPosArgs = nargs - arrayLength; |
4537 | 514 |
MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs); |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
515 |
newType = newType.insertParameterTypes(keepPosArgs, arrayElement); |
4537 | 516 |
return MethodHandles.spreadArguments(this, newType); |
517 |
} |
|
518 |
||
519 |
/** |
|
520 |
* Produce a method handle which adapts, as its <i>target</i>, |
|
521 |
* the current method handle. The type of the adapter will be |
|
522 |
* the same as the type of the target, except that a single trailing |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
523 |
* parameter (usually of type {@code arrayType}) is replaced by |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
524 |
* {@code arrayLength} parameters whose type is element type of {@code arrayType}. |
4537 | 525 |
* <p> |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
526 |
* If the array type differs from the final argument type on original target, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
527 |
* the original target is adapted to take the array type directly, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
528 |
* as if by a call to {@link #asType asType}. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
529 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
530 |
* When called, the adapter replaces its trailing {@code arrayLength} |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
531 |
* arguments by a single new array of type {@code arrayType}, whose elements |
4537 | 532 |
* comprise (in order) the replaced arguments. |
533 |
* Finally the target is called. |
|
534 |
* What the target eventually returns is returned unchanged by the adapter. |
|
535 |
* <p> |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
536 |
* (The array may also be a shared constant when {@code arrayLength} is zero.) |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
537 |
* @param arrayType usually {@code Object[]}, the type of the array argument which will collect the arguments |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
538 |
* @param arrayLength the number of arguments to collect into a new array argument |
4537 | 539 |
* @return a new method handle which collects some trailing argument |
540 |
* into an array, before calling the original method handle |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
541 |
* @throws IllegalArgumentException if {@code arrayType} is not an array type |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
542 |
or {@code arrayType} is not assignable to this method handle's trailing parameter type |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
543 |
* @throws IllegalArgumentException if {@code arrayLength} is not |
4537 | 544 |
* a legal array size |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
545 |
* @throws WrongMethodTypeException if the implied {@code asType} call fails |
4537 | 546 |
*/ |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
547 |
public final MethodHandle asCollector(Class<?> arrayType, int arrayLength) { |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
548 |
Class<?> arrayElement = arrayType.getComponentType(); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
549 |
if (arrayElement == null) throw newIllegalArgumentException("not an array type"); |
4537 | 550 |
MethodType oldType = type(); |
551 |
int nargs = oldType.parameterCount(); |
|
552 |
MethodType newType = oldType.dropParameterTypes(nargs-1, nargs); |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
553 |
newType = newType.insertParameterTypes(nargs-1, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
554 |
java.util.Collections.<Class<?>>nCopies(arrayLength, arrayElement)); |
4537 | 555 |
return MethodHandles.collectArguments(this, newType); |
556 |
} |
|
557 |
||
558 |
/** |
|
559 |
* Produce a method handle which binds the given argument |
|
560 |
* to the current method handle as <i>target</i>. |
|
561 |
* The type of the bound handle will be |
|
562 |
* the same as the type of the target, except that a single leading |
|
563 |
* reference parameter will be omitted. |
|
564 |
* <p> |
|
565 |
* When called, the bound handle inserts the given value {@code x} |
|
566 |
* as a new leading argument to the target. The other arguments are |
|
567 |
* also passed unchanged. |
|
568 |
* What the target eventually returns is returned unchanged by the bound handle. |
|
569 |
* <p> |
|
570 |
* The reference {@code x} must be convertible to the first parameter |
|
571 |
* type of the target. |
|
572 |
* @param x the value to bind to the first argument of the target |
|
573 |
* @return a new method handle which collects some trailing argument |
|
574 |
* into an array, before calling the original method handle |
|
575 |
* @throws IllegalArgumentException if the target does not have a |
|
576 |
* leading parameter type that is a reference type |
|
577 |
* @throws ClassCastException if {@code x} cannot be converted |
|
578 |
* to the leading parameter type of the target |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
579 |
* @see MethodHandles#insertArguments |
4537 | 580 |
*/ |
581 |
public final MethodHandle bindTo(Object x) { |
|
582 |
return MethodHandles.insertArguments(this, 0, x); |
|
583 |
} |
|
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
584 |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
585 |
/** |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
586 |
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
587 |
* Create a new method handle with the same type as this one, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
588 |
* but whose {@code asType} method invokes the given |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
589 |
* {@code typeHandler} on this method handle, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
590 |
* instead of the standard {@code MethodHandles.convertArguments}. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
591 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
592 |
* The new method handle will have the same behavior as the |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
593 |
* old one when invoked by {@code invokeExact}. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
594 |
* For {@code invokeGeneric} calls which exactly match |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
595 |
* the method type, the two method handles will also |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
596 |
* have the same behavior. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
597 |
* For other {@code invokeGeneric} calls, the {@code typeHandler} |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
598 |
* will control the behavior of the new method handle. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
599 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
600 |
* Thus, a method handle with an {@code asType} handler can |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
601 |
* be configured to accept more than one arity of {@code invokeGeneric} |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
602 |
* call, and potentially every possible arity. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
603 |
* It can also be configured to supply default values for |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
604 |
* optional arguments, when the caller does not specify them. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
605 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
606 |
* The given method handle must take two arguments and return |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
607 |
* one result. The result it returns must be a method handle |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
608 |
* of exactly the requested type. If the result returned by |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
609 |
* the target is null, a {@link NullPointerException} is thrown, |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
610 |
* else if the type of the target does not exactly match |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
611 |
* the requested type, a {@link WrongMethodTypeException} is thrown. |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
612 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
613 |
* Therefore, the type handler is invoked as if by this code: |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
614 |
* <blockquote><pre> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
615 |
* MethodHandle target = this; // original method handle |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
616 |
* MethodHandle adapter = ...; // adapted method handle |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
617 |
* MethodType requestedType = ...; // argument to asType() |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
618 |
* if (type().equals(requestedType)) |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
619 |
* return adapter; |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
620 |
* MethodHandle result = (MethodHandle) |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
621 |
* typeHandler.invokeGeneric(target, requestedType); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
622 |
* if (!result.type().equals(requestedType)) |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
623 |
* throw new WrongMethodTypeException(); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
624 |
* return result; |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
625 |
* </pre></blockquote> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
626 |
* <p> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
627 |
* For example, here is a list-making variable-arity method handle: |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
628 |
* <blockquote><pre> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
629 |
MethodHandle makeEmptyList = MethodHandles.constant(List.class, Arrays.asList()); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
630 |
MethodHandle asList = lookup() |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
631 |
.findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
632 |
static MethodHandle collectingTypeHandler(MethodHandle base, MethodType newType) { |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
633 |
return asList.asCollector(Object[].class, newType.parameterCount()).asType(newType); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
634 |
} |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
635 |
MethodHandle collectingTypeHandler = lookup() |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
636 |
.findStatic(lookup().lookupClass(), "collectingTypeHandler", |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
637 |
methodType(MethodHandle.class, MethodHandle.class, MethodType.class)); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
638 |
MethodHandle makeAnyList = makeEmptyList.withTypeHandler(collectingTypeHandler); |
7051
1c545d70a157
6964498: JSR 292 invokedynamic sites need local bootstrap methods
jrose
parents:
5725
diff
changeset
|
639 |
|
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
640 |
System.out.println(makeAnyList.invokeGeneric()); // prints [] |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
641 |
System.out.println(makeAnyList.invokeGeneric(1)); // prints [1] |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
642 |
System.out.println(makeAnyList.invokeGeneric("two", "too")); // prints [two, too] |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
643 |
* <pre><blockquote> |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
644 |
*/ |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
645 |
public MethodHandle withTypeHandler(MethodHandle typeHandler) { |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
646 |
return MethodHandles.withTypeHandler(this, typeHandler); |
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
647 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
648 |
} |