author | jrose |
Fri, 30 Apr 2010 23:48:23 -0700 | |
changeset 5722 | 4ada807383c8 |
parent 4537 | 7c3c7f8d5195 |
child 5723 | a58a0eed34b0 |
permissions | -rw-r--r-- |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1 |
/* |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
2 |
* Copyright 2008-2010 Sun Microsystems, Inc. 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 |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
7 |
* published by the Free Software Foundation. Sun designates this |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
8 |
* particular file as subject to the "Classpath" exception as provided |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
9 |
* by Sun in the LICENSE file that accompanied this code. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
10 |
* |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
15 |
* accompanied this code). |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
16 |
* |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
17 |
* You should have received a copy of the GNU General Public License version |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
20 |
* |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
23 |
* have any questions. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
24 |
*/ |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
25 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
26 |
package sun.dyn; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
27 |
|
4537 | 28 |
import java.dyn.JavaMethodHandle; |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
29 |
import java.dyn.MethodHandle; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
30 |
import java.dyn.MethodHandles; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
31 |
import java.dyn.MethodHandles.Lookup; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
32 |
import java.dyn.MethodType; |
4537 | 33 |
import java.util.logging.Level; |
34 |
import java.util.logging.Logger; |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
35 |
import sun.dyn.util.VerifyType; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
36 |
import java.dyn.NoAccessException; |
4537 | 37 |
import java.util.ArrayList; |
38 |
import java.util.Arrays; |
|
39 |
import java.util.Collections; |
|
40 |
import java.util.HashMap; |
|
41 |
import java.util.Iterator; |
|
42 |
import java.util.List; |
|
43 |
import sun.dyn.empty.Empty; |
|
44 |
import sun.dyn.util.ValueConversions; |
|
45 |
import sun.dyn.util.Wrapper; |
|
46 |
import sun.misc.Unsafe; |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
47 |
import static sun.dyn.MemberName.newIllegalArgumentException; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
48 |
import static sun.dyn.MemberName.newNoAccessException; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
49 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
50 |
/** |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
51 |
* Base class for method handles, containing JVM-specific fields and logic. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
52 |
* TO DO: It should not be a base class. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
53 |
* @author jrose |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
54 |
*/ |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
55 |
public abstract class MethodHandleImpl { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
56 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
57 |
// Fields which really belong in MethodHandle: |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
58 |
private byte vmentry; // adapter stub or method entry point |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
59 |
//private int vmslots; // optionally, hoist type.form.vmslots |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
60 |
protected Object vmtarget; // VM-specific, class-specific target value |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
61 |
//MethodType type; // defined in MethodHandle |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
62 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
63 |
// TO DO: vmtarget should be invisible to Java, since the JVM puts internal |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
64 |
// managed pointers into it. Making it visible exposes it to debuggers, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
65 |
// which can cause errors when they treat the pointer as an Object. |
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 |
// These two dummy fields are present to force 'I' and 'J' signatures |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
68 |
// into this class's constant pool, so they can be transferred |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
69 |
// to vmentry when this class is loaded. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
70 |
static final int INT_FIELD = 0; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
71 |
static final long LONG_FIELD = 0; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
72 |
|
4537 | 73 |
/** Access methods for the internals of MethodHandle, supplied to |
74 |
* MethodHandleImpl as a trusted agent. |
|
75 |
*/ |
|
76 |
static public interface MethodHandleFriend { |
|
77 |
void initType(MethodHandle mh, MethodType type); |
|
78 |
} |
|
79 |
public static void setMethodHandleFriend(Access token, MethodHandleFriend am) { |
|
80 |
Access.check(token); |
|
81 |
if (METHOD_HANDLE_FRIEND != null) |
|
82 |
throw new InternalError(); // just once |
|
83 |
METHOD_HANDLE_FRIEND = am; |
|
84 |
} |
|
85 |
static private MethodHandleFriend METHOD_HANDLE_FRIEND; |
|
86 |
||
87 |
// NOT public |
|
88 |
static void initType(MethodHandle mh, MethodType type) { |
|
89 |
METHOD_HANDLE_FRIEND.initType(mh, type); |
|
90 |
} |
|
91 |
||
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
92 |
// type is defined in java.dyn.MethodHandle, which is platform-independent |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
93 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
94 |
// vmentry (a void* field) is used *only* by by the JVM. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
95 |
// The JVM adjusts its type to int or long depending on system wordsize. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
96 |
// Since it is statically typed as neither int nor long, it is impossible |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
97 |
// to use this field from Java bytecode. (Please don't try to, either.) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
98 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
99 |
// The vmentry is an assembly-language stub which is jumped to |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
100 |
// immediately after the method type is verified. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
101 |
// For a direct MH, this stub loads the vmtarget's entry point |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
102 |
// and jumps to it. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
103 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
104 |
/** |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
105 |
* VM-based method handles must have a security token. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
106 |
* This security token can only be obtained by trusted code. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
107 |
* Do not create method handles directly; use factory methods. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
108 |
*/ |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
109 |
public MethodHandleImpl(Access token) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
110 |
Access.check(token); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
111 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
112 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
113 |
/** Initialize the method type form to participate in JVM calls. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
114 |
* This is done once for each erased type. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
115 |
*/ |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
116 |
public static void init(Access token, MethodType self) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
117 |
Access.check(token); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
118 |
if (MethodHandleNatives.JVM_SUPPORT) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
119 |
MethodHandleNatives.init(self); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
120 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
121 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
122 |
/// Factory methods to create method handles: |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
123 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
124 |
private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
125 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
126 |
static private Lookup IMPL_LOOKUP_INIT; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
127 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
128 |
public static void initLookup(Access token, Lookup lookup) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
129 |
Access.check(token); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
130 |
if (IMPL_LOOKUP_INIT != null) |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
131 |
throw new InternalError(); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
132 |
IMPL_LOOKUP_INIT = lookup; |
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 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
135 |
public static Lookup getLookup(Access token) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
136 |
Access.check(token); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
137 |
return IMPL_LOOKUP; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
138 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
139 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
140 |
static { |
4537 | 141 |
// Force initialization of Lookup, so it calls us back as initLookup: |
142 |
MethodHandles.publicLookup(); |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
143 |
if (IMPL_LOOKUP_INIT == null) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
144 |
throw new InternalError(); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
145 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
146 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
147 |
public static void initStatics() { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
148 |
// Trigger preceding sequence. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
149 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
150 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
151 |
/** Shared secret with MethodHandles.Lookup, a copy of Lookup.IMPL_LOOKUP. */ |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
152 |
static final Lookup IMPL_LOOKUP = IMPL_LOOKUP_INIT; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
153 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
154 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
155 |
/** Look up a given method. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
156 |
* Callable only from java.dyn and related packages. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
157 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
158 |
* The resulting method handle type will be of the given type, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
159 |
* with a receiver type {@code rcvc} prepended if the member is not static. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
160 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
161 |
* Access checks are made as of the given lookup class. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
162 |
* In particular, if the method is protected and {@code defc} is in a |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
163 |
* different package from the lookup class, then {@code rcvc} must be |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
164 |
* the lookup class or a subclass. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
165 |
* @param token Proof that the lookup class has access to this package. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
166 |
* @param member Resolved method or constructor to call. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
167 |
* @param name Name of the desired method. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
168 |
* @param rcvc Receiver type of desired non-static method (else null) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
169 |
* @param doDispatch whether the method handle will test the receiver type |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
170 |
* @param lookupClass access-check relative to this class |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
171 |
* @return a direct handle to the matching method |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
172 |
* @throws NoAccessException if the given method cannot be accessed by the lookup class |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
173 |
*/ |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
174 |
public static |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
175 |
MethodHandle findMethod(Access token, MemberName method, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
176 |
boolean doDispatch, Class<?> lookupClass) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
177 |
Access.check(token); // only trusted calls |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
178 |
MethodType mtype = method.getMethodType(); |
2764
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
179 |
MethodType rtype = mtype; |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
180 |
if (!method.isStatic()) { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
181 |
// adjust the advertised receiver type to be exactly the one requested |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
182 |
// (in the case of invokespecial, this will be the calling class) |
2764
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
183 |
Class<?> recvType = method.getDeclaringClass(); |
4537 | 184 |
mtype = mtype.insertParameterTypes(0, recvType); |
2764
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
185 |
// FIXME: JVM has trouble building MH.invoke sites for |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
186 |
// classes off the boot class path |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
187 |
rtype = mtype; |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
188 |
if (recvType.getClassLoader() != null) { |
2764
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
189 |
rtype = rtype.changeParameterType(0, Object.class); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
190 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
191 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
192 |
DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
193 |
if (!mh.isValid()) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
194 |
throw newNoAccessException(method, lookupClass); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
195 |
if (rtype != mtype) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
196 |
MethodHandle rmh = AdapterMethodHandle.makePairwiseConvert(token, rtype, mh); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
197 |
if (rmh == null) throw new InternalError(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
198 |
return rmh; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
199 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
200 |
assert(mh.type() == rtype); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
201 |
return mh; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
202 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
203 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
204 |
public static |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
205 |
MethodHandle makeAllocator(Access token, MethodHandle rawConstructor) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
206 |
Access.check(token); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
207 |
MethodType rawConType = rawConstructor.type(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
208 |
// Wrap the raw (unsafe) constructor with the allocation of a suitable object. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
209 |
MethodHandle allocator |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
210 |
= AllocateObject.make(token, rawConType.parameterType(0), rawConstructor); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
211 |
assert(allocator.type() |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
212 |
.equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0)))); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
213 |
return allocator; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
214 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
215 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
216 |
static final class AllocateObject<C> extends JavaMethodHandle { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
217 |
private static final Unsafe unsafe = Unsafe.getUnsafe(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
218 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
219 |
private final Class<C> allocateClass; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
220 |
private final MethodHandle rawConstructor; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
221 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
222 |
private AllocateObject(MethodHandle invoker, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
223 |
Class<C> allocateClass, MethodHandle rawConstructor) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
224 |
super(invoker); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
225 |
this.allocateClass = allocateClass; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
226 |
this.rawConstructor = rawConstructor; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
227 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
228 |
static MethodHandle make(Access token, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
229 |
Class<?> allocateClass, MethodHandle rawConstructor) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
230 |
Access.check(token); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
231 |
MethodType rawConType = rawConstructor.type(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
232 |
assert(rawConType.parameterType(0) == allocateClass); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
233 |
MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
234 |
int nargs = rawConType.parameterCount() - 1; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
235 |
if (nargs < INVOKES.length) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
236 |
MethodHandle invoke = INVOKES[nargs]; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
237 |
MethodType conType = CON_TYPES[nargs]; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
238 |
MethodHandle gcon = convertArguments(token, rawConstructor, conType, rawConType, null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
239 |
if (gcon == null) return null; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
240 |
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
241 |
assert(galloc.type() == newType.generic()); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
242 |
return convertArguments(token, galloc, newType, galloc.type(), null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
243 |
} else { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
244 |
MethodHandle invoke = VARARGS_INVOKE; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
245 |
MethodType conType = CON_TYPES[nargs]; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
246 |
MethodHandle gcon = spreadArguments(token, rawConstructor, conType, 1); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
247 |
if (gcon == null) return null; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
248 |
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
249 |
return collectArguments(token, galloc, newType, 1, null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
250 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
251 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
252 |
@Override |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
253 |
public String toString() { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
254 |
return allocateClass.getSimpleName(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
255 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
256 |
@SuppressWarnings("unchecked") |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
257 |
private C allocate() throws InstantiationException { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
258 |
return (C) unsafe.allocateInstance(allocateClass); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
259 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
260 |
private C invoke_V(Object... av) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
261 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
262 |
rawConstructor.<void>invokeExact((Object)obj, av); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
263 |
return obj; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
264 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
265 |
private C invoke_L0() throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
266 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
267 |
rawConstructor.<void>invokeExact((Object)obj); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
268 |
return obj; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
269 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
270 |
private C invoke_L1(Object a0) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
271 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
272 |
rawConstructor.<void>invokeExact((Object)obj, a0); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
273 |
return obj; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
274 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
275 |
private C invoke_L2(Object a0, Object a1) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
276 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
277 |
rawConstructor.<void>invokeExact((Object)obj, a0, a1); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
278 |
return obj; |
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 |
private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
281 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
282 |
rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
283 |
return obj; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
284 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
285 |
private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
286 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
287 |
rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
288 |
return obj; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
289 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
290 |
private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
291 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
292 |
rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
293 |
return obj; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
294 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
295 |
private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
296 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
297 |
rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4, a5); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
298 |
return obj; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
299 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
300 |
private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
301 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
302 |
rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
303 |
return obj; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
304 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
305 |
private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
306 |
C obj = allocate(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
307 |
rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
308 |
return obj; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
309 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
310 |
static MethodHandle[] makeInvokes() { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
311 |
ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
312 |
MethodHandles.Lookup lookup = IMPL_LOOKUP; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
313 |
for (;;) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
314 |
int nargs = invokes.size(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
315 |
String name = "invoke_L"+nargs; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
316 |
MethodHandle invoke = null; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
317 |
try { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
318 |
invoke = lookup.findVirtual(AllocateObject.class, name, MethodType.genericMethodType(nargs)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
319 |
} catch (NoAccessException ex) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
320 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
321 |
if (invoke == null) break; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
322 |
invokes.add(invoke); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
323 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
324 |
assert(invokes.size() == 9); // current number of methods |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
325 |
return invokes.toArray(new MethodHandle[0]); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
326 |
}; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
327 |
static final MethodHandle[] INVOKES = makeInvokes(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
328 |
// For testing use this: |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
329 |
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
330 |
static final MethodHandle VARARGS_INVOKE; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
331 |
static { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
332 |
try { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
333 |
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
334 |
} catch (NoAccessException ex) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
335 |
throw new InternalError(""); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
336 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
337 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
338 |
// Corresponding generic constructor types: |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
339 |
static final MethodType[] CON_TYPES = new MethodType[INVOKES.length]; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
340 |
static { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
341 |
for (int i = 0; i < INVOKES.length; i++) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
342 |
CON_TYPES[i] = makeConType(INVOKES[i]); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
343 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
344 |
static final MethodType VARARGS_CON_TYPE = makeConType(VARARGS_INVOKE); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
345 |
static MethodType makeConType(MethodHandle invoke) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
346 |
MethodType invType = invoke.type(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
347 |
return invType.changeParameterType(0, Object.class).changeReturnType(void.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
348 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
349 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
350 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
351 |
public static |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
352 |
MethodHandle accessField(Access token, |
4537 | 353 |
MemberName member, boolean isSetter, |
354 |
Class<?> lookupClass) { |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
355 |
Access.check(token); |
4537 | 356 |
// Use sun. misc.Unsafe to dig up the dirt on the field. |
357 |
MethodHandle mh = new FieldAccessor(token, member, isSetter); |
|
358 |
return mh; |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
359 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
360 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
361 |
public static |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
362 |
MethodHandle accessArrayElement(Access token, |
4537 | 363 |
Class<?> arrayClass, boolean isSetter) { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
364 |
Access.check(token); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
365 |
if (!arrayClass.isArray()) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
366 |
throw newIllegalArgumentException("not an array: "+arrayClass); |
4537 | 367 |
Class<?> elemClass = arrayClass.getComponentType(); |
368 |
MethodHandle[] mhs = FieldAccessor.ARRAY_CACHE.get(elemClass); |
|
369 |
if (mhs == null) { |
|
370 |
if (!FieldAccessor.doCache(elemClass)) |
|
371 |
return FieldAccessor.ahandle(arrayClass, isSetter); |
|
372 |
mhs = new MethodHandle[] { |
|
373 |
FieldAccessor.ahandle(arrayClass, false), |
|
374 |
FieldAccessor.ahandle(arrayClass, true) |
|
375 |
}; |
|
376 |
if (mhs[0].type().parameterType(0) == Class.class) { |
|
377 |
mhs[0] = MethodHandles.insertArguments(mhs[0], 0, elemClass); |
|
378 |
mhs[1] = MethodHandles.insertArguments(mhs[1], 0, elemClass); |
|
379 |
} |
|
380 |
synchronized (FieldAccessor.ARRAY_CACHE) {} // memory barrier |
|
381 |
FieldAccessor.ARRAY_CACHE.put(elemClass, mhs); |
|
382 |
} |
|
383 |
return mhs[isSetter ? 1 : 0]; |
|
384 |
} |
|
385 |
||
386 |
static final class FieldAccessor<C,V> extends JavaMethodHandle { |
|
387 |
private static final Unsafe unsafe = Unsafe.getUnsafe(); |
|
388 |
final Object base; // for static refs only |
|
389 |
final long offset; |
|
390 |
final String name; |
|
391 |
||
392 |
public FieldAccessor(Access token, MemberName field, boolean isSetter) { |
|
393 |
super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic())); |
|
394 |
this.offset = (long) field.getVMIndex(token); |
|
395 |
this.name = field.getName(); |
|
396 |
this.base = staticBase(field); |
|
397 |
} |
|
398 |
public String toString() { return name; } |
|
399 |
||
400 |
int getFieldI(C obj) { return unsafe.getInt(obj, offset); } |
|
401 |
void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); } |
|
402 |
long getFieldJ(C obj) { return unsafe.getLong(obj, offset); } |
|
403 |
void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); } |
|
404 |
float getFieldF(C obj) { return unsafe.getFloat(obj, offset); } |
|
405 |
void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); } |
|
406 |
double getFieldD(C obj) { return unsafe.getDouble(obj, offset); } |
|
407 |
void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); } |
|
408 |
boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); } |
|
409 |
void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); } |
|
410 |
byte getFieldB(C obj) { return unsafe.getByte(obj, offset); } |
|
411 |
void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); } |
|
412 |
short getFieldS(C obj) { return unsafe.getShort(obj, offset); } |
|
413 |
void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); } |
|
414 |
char getFieldC(C obj) { return unsafe.getChar(obj, offset); } |
|
415 |
void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); } |
|
416 |
@SuppressWarnings("unchecked") |
|
417 |
V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); } |
|
418 |
@SuppressWarnings("unchecked") |
|
419 |
void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); } |
|
420 |
// cast (V) is OK here, since we wrap convertArguments around the MH. |
|
421 |
||
422 |
static Object staticBase(MemberName field) { |
|
423 |
if (!field.isStatic()) return null; |
|
424 |
Class c = field.getDeclaringClass(); |
|
425 |
java.lang.reflect.Field f; |
|
426 |
try { |
|
427 |
// FIXME: Should not have to create 'f' to get this value. |
|
428 |
f = c.getDeclaredField(field.getName()); |
|
429 |
return unsafe.staticFieldBase(f); |
|
430 |
} catch (Exception ee) { |
|
431 |
Error e = new InternalError(); |
|
432 |
e.initCause(ee); |
|
433 |
throw e; |
|
434 |
} |
|
435 |
} |
|
436 |
||
437 |
int getStaticI() { return unsafe.getInt(base, offset); } |
|
438 |
void setStaticI(int x) { unsafe.putInt(base, offset, x); } |
|
439 |
long getStaticJ() { return unsafe.getLong(base, offset); } |
|
440 |
void setStaticJ(long x) { unsafe.putLong(base, offset, x); } |
|
441 |
float getStaticF() { return unsafe.getFloat(base, offset); } |
|
442 |
void setStaticF(float x) { unsafe.putFloat(base, offset, x); } |
|
443 |
double getStaticD() { return unsafe.getDouble(base, offset); } |
|
444 |
void setStaticD(double x) { unsafe.putDouble(base, offset, x); } |
|
445 |
boolean getStaticZ() { return unsafe.getBoolean(base, offset); } |
|
446 |
void setStaticZ(boolean x) { unsafe.putBoolean(base, offset, x); } |
|
447 |
byte getStaticB() { return unsafe.getByte(base, offset); } |
|
448 |
void setStaticB(byte x) { unsafe.putByte(base, offset, x); } |
|
449 |
short getStaticS() { return unsafe.getShort(base, offset); } |
|
450 |
void setStaticS(short x) { unsafe.putShort(base, offset, x); } |
|
451 |
char getStaticC() { return unsafe.getChar(base, offset); } |
|
452 |
void setStaticC(char x) { unsafe.putChar(base, offset, x); } |
|
453 |
V getStaticL() { return (V) unsafe.getObject(base, offset); } |
|
454 |
void setStaticL(V x) { unsafe.putObject(base, offset, x); } |
|
455 |
||
456 |
static String fname(Class<?> vclass, boolean isSetter, boolean isStatic) { |
|
457 |
String stem; |
|
458 |
if (!isStatic) |
|
459 |
stem = (!isSetter ? "getField" : "setField"); |
|
460 |
else |
|
461 |
stem = (!isSetter ? "getStatic" : "setStatic"); |
|
462 |
return stem + Wrapper.basicTypeChar(vclass); |
|
463 |
} |
|
464 |
static MethodType ftype(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) { |
|
465 |
MethodType type; |
|
466 |
if (!isStatic) { |
|
467 |
if (!isSetter) |
|
468 |
return MethodType.methodType(vclass, cclass); |
|
469 |
else |
|
470 |
return MethodType.methodType(void.class, cclass, vclass); |
|
471 |
} else { |
|
472 |
if (!isSetter) |
|
473 |
return MethodType.methodType(vclass); |
|
474 |
else |
|
475 |
return MethodType.methodType(void.class, vclass); |
|
476 |
} |
|
477 |
} |
|
478 |
static MethodHandle fhandle(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) { |
|
479 |
String name = FieldAccessor.fname(vclass, isSetter, isStatic); |
|
480 |
if (cclass.isPrimitive()) throw newIllegalArgumentException("primitive "+cclass); |
|
481 |
Class<?> ecclass = Object.class; //erase this type |
|
482 |
Class<?> evclass = vclass; |
|
483 |
if (!evclass.isPrimitive()) evclass = Object.class; |
|
484 |
MethodType type = FieldAccessor.ftype(ecclass, evclass, isSetter, isStatic); |
|
485 |
MethodHandle mh; |
|
486 |
try { |
|
487 |
mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type); |
|
488 |
} catch (NoAccessException ee) { |
|
489 |
Error e = new InternalError("name,type="+name+type); |
|
490 |
e.initCause(ee); |
|
491 |
throw e; |
|
492 |
} |
|
493 |
if (evclass != vclass || (!isStatic && ecclass != cclass)) { |
|
494 |
MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic); |
|
495 |
strongType = strongType.insertParameterTypes(0, FieldAccessor.class); |
|
496 |
mh = MethodHandles.convertArguments(mh, strongType); |
|
497 |
} |
|
498 |
return mh; |
|
499 |
} |
|
500 |
||
501 |
/// Support for array element access |
|
502 |
static final HashMap<Class<?>, MethodHandle[]> ARRAY_CACHE = |
|
503 |
new HashMap<Class<?>, MethodHandle[]>(); |
|
504 |
// FIXME: Cache on the classes themselves, not here. |
|
505 |
static boolean doCache(Class<?> elemClass) { |
|
506 |
if (elemClass.isPrimitive()) return true; |
|
507 |
ClassLoader cl = elemClass.getClassLoader(); |
|
508 |
return cl == null || cl == ClassLoader.getSystemClassLoader(); |
|
509 |
} |
|
510 |
static int getElementI(int[] a, int i) { return a[i]; } |
|
511 |
static void setElementI(int[] a, int i, int x) { a[i] = x; } |
|
512 |
static long getElementJ(long[] a, int i) { return a[i]; } |
|
513 |
static void setElementJ(long[] a, int i, long x) { a[i] = x; } |
|
514 |
static float getElementF(float[] a, int i) { return a[i]; } |
|
515 |
static void setElementF(float[] a, int i, float x) { a[i] = x; } |
|
516 |
static double getElementD(double[] a, int i) { return a[i]; } |
|
517 |
static void setElementD(double[] a, int i, double x) { a[i] = x; } |
|
518 |
static boolean getElementZ(boolean[] a, int i) { return a[i]; } |
|
519 |
static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; } |
|
520 |
static byte getElementB(byte[] a, int i) { return a[i]; } |
|
521 |
static void setElementB(byte[] a, int i, byte x) { a[i] = x; } |
|
522 |
static short getElementS(short[] a, int i) { return a[i]; } |
|
523 |
static void setElementS(short[] a, int i, short x) { a[i] = x; } |
|
524 |
static char getElementC(char[] a, int i) { return a[i]; } |
|
525 |
static void setElementC(char[] a, int i, char x) { a[i] = x; } |
|
526 |
static Object getElementL(Object[] a, int i) { return a[i]; } |
|
527 |
static void setElementL(Object[] a, int i, Object x) { a[i] = x; } |
|
528 |
static <V> V getElementL(Class<V[]> aclass, V[] a, int i) { return aclass.cast(a)[i]; } |
|
529 |
static <V> void setElementL(Class<V[]> aclass, V[] a, int i, V x) { aclass.cast(a)[i] = x; } |
|
530 |
||
531 |
static String aname(Class<?> aclass, boolean isSetter) { |
|
532 |
Class<?> vclass = aclass.getComponentType(); |
|
533 |
if (vclass == null) throw new IllegalArgumentException(); |
|
534 |
return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(vclass); |
|
535 |
} |
|
536 |
static MethodType atype(Class<?> aclass, boolean isSetter) { |
|
537 |
Class<?> vclass = aclass.getComponentType(); |
|
538 |
if (!isSetter) |
|
539 |
return MethodType.methodType(vclass, aclass, int.class); |
|
540 |
else |
|
541 |
return MethodType.methodType(void.class, aclass, int.class, vclass); |
|
542 |
} |
|
543 |
static MethodHandle ahandle(Class<?> aclass, boolean isSetter) { |
|
544 |
Class<?> vclass = aclass.getComponentType(); |
|
545 |
String name = FieldAccessor.aname(aclass, isSetter); |
|
546 |
Class<?> caclass = null; |
|
547 |
if (!vclass.isPrimitive() && vclass != Object.class) { |
|
548 |
caclass = aclass; |
|
549 |
aclass = Object[].class; |
|
550 |
vclass = Object.class; |
|
551 |
} |
|
552 |
MethodType type = FieldAccessor.atype(aclass, isSetter); |
|
553 |
if (caclass != null) |
|
554 |
type = type.insertParameterTypes(0, Class.class); |
|
555 |
MethodHandle mh; |
|
556 |
try { |
|
557 |
mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type); |
|
558 |
} catch (NoAccessException ee) { |
|
559 |
Error e = new InternalError("name,type="+name+type); |
|
560 |
e.initCause(ee); |
|
561 |
throw e; |
|
562 |
} |
|
563 |
if (caclass != null) { |
|
564 |
MethodType strongType = FieldAccessor.atype(caclass, isSetter); |
|
565 |
mh = MethodHandles.insertArguments(mh, 0, caclass); |
|
566 |
mh = MethodHandles.convertArguments(mh, strongType); |
|
567 |
} |
|
568 |
return mh; |
|
569 |
} |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
570 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
571 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
572 |
/** Bind a predetermined first argument to the given direct method handle. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
573 |
* Callable only from MethodHandles. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
574 |
* @param token Proof that the caller has access to this package. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
575 |
* @param target Any direct method handle. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
576 |
* @param receiver Receiver (or first static method argument) to pre-bind. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
577 |
* @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
578 |
*/ |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
579 |
public static |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
580 |
MethodHandle bindReceiver(Access token, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
581 |
MethodHandle target, Object receiver) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
582 |
Access.check(token); |
2764
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
583 |
if (target instanceof AdapterMethodHandle) { |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
584 |
Object info = MethodHandleNatives.getTargetInfo(target); |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
585 |
if (info instanceof DirectMethodHandle) { |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
586 |
DirectMethodHandle dmh = (DirectMethodHandle) info; |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
587 |
if (receiver == null || |
4537 | 588 |
dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) { |
589 |
MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0); |
|
590 |
MethodType newType = target.type().dropParameterTypes(0, 1); |
|
591 |
return convertArguments(token, bmh, newType, bmh.type(), null); |
|
592 |
} |
|
2764
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
593 |
} |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
594 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
595 |
if (target instanceof DirectMethodHandle) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
596 |
return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
597 |
return null; // let caller try something else |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
598 |
} |
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 |
/** Bind a predetermined argument to the given arbitrary method handle. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
601 |
* Callable only from MethodHandles. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
602 |
* @param token Proof that the caller has access to this package. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
603 |
* @param target Any method handle. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
604 |
* @param receiver Argument (which can be a boxed primitive) to pre-bind. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
605 |
* @return a suitable BoundMethodHandle |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
606 |
*/ |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
607 |
public static |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
608 |
MethodHandle bindArgument(Access token, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
609 |
MethodHandle target, int argnum, Object receiver) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
610 |
Access.check(token); |
4537 | 611 |
return new BoundMethodHandle(target, receiver, argnum); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
612 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
613 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
614 |
public static MethodHandle convertArguments(Access token, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
615 |
MethodHandle target, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
616 |
MethodType newType, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
617 |
MethodType oldType, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
618 |
int[] permutationOrNull) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
619 |
Access.check(token); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
620 |
assert(oldType.parameterCount() == target.type().parameterCount()); |
4537 | 621 |
if (permutationOrNull != null) { |
622 |
int outargs = oldType.parameterCount(), inargs = newType.parameterCount(); |
|
623 |
if (permutationOrNull.length != outargs) |
|
624 |
throw newIllegalArgumentException("wrong number of arguments in permutation"); |
|
625 |
// Make the individual outgoing argument types match up first. |
|
626 |
Class<?>[] callTypeArgs = new Class<?>[outargs]; |
|
627 |
for (int i = 0; i < outargs; i++) |
|
628 |
callTypeArgs[i] = newType.parameterType(permutationOrNull[i]); |
|
629 |
MethodType callType = MethodType.methodType(oldType.returnType(), callTypeArgs); |
|
630 |
target = convertArguments(token, target, callType, oldType, null); |
|
631 |
assert(target != null); |
|
632 |
oldType = target.type(); |
|
633 |
List<Integer> goal = new ArrayList<Integer>(); // i*TOKEN |
|
634 |
List<Integer> state = new ArrayList<Integer>(); // i*TOKEN |
|
635 |
List<Integer> drops = new ArrayList<Integer>(); // not tokens |
|
636 |
List<Integer> dups = new ArrayList<Integer>(); // not tokens |
|
637 |
final int TOKEN = 10; // to mark items which are symbolic only |
|
638 |
// state represents the argument values coming into target |
|
639 |
for (int i = 0; i < outargs; i++) { |
|
640 |
state.add(permutationOrNull[i] * TOKEN); |
|
641 |
} |
|
642 |
// goal represents the desired state |
|
643 |
for (int i = 0; i < inargs; i++) { |
|
644 |
if (state.contains(i * TOKEN)) { |
|
645 |
goal.add(i * TOKEN); |
|
646 |
} else { |
|
647 |
// adapter must initially drop all unused arguments |
|
648 |
drops.add(i); |
|
649 |
} |
|
650 |
} |
|
651 |
// detect duplications |
|
652 |
while (state.size() > goal.size()) { |
|
653 |
for (int i2 = 0; i2 < state.size(); i2++) { |
|
654 |
int arg1 = state.get(i2); |
|
655 |
int i1 = state.indexOf(arg1); |
|
656 |
if (i1 != i2) { |
|
657 |
// found duplicate occurrence at i2 |
|
658 |
int arg2 = (inargs++) * TOKEN; |
|
659 |
state.set(i2, arg2); |
|
660 |
dups.add(goal.indexOf(arg1)); |
|
661 |
goal.add(arg2); |
|
662 |
} |
|
663 |
} |
|
664 |
} |
|
665 |
assert(state.size() == goal.size()); |
|
666 |
int size = goal.size(); |
|
667 |
while (!state.equals(goal)) { |
|
668 |
// Look for a maximal sequence of adjacent misplaced arguments, |
|
669 |
// and try to rotate them into place. |
|
670 |
int bestRotArg = -10 * TOKEN, bestRotLen = 0; |
|
671 |
int thisRotArg = -10 * TOKEN, thisRotLen = 0; |
|
672 |
for (int i = 0; i < size; i++) { |
|
673 |
int arg = state.get(i); |
|
674 |
// Does this argument match the current run? |
|
675 |
if (arg == thisRotArg + TOKEN) { |
|
676 |
thisRotArg = arg; |
|
677 |
thisRotLen += 1; |
|
678 |
if (bestRotLen < thisRotLen) { |
|
679 |
bestRotLen = thisRotLen; |
|
680 |
bestRotArg = thisRotArg; |
|
681 |
} |
|
682 |
} else { |
|
683 |
// The old sequence (if any) stops here. |
|
684 |
thisRotLen = 0; |
|
685 |
thisRotArg = -10 * TOKEN; |
|
686 |
// But maybe a new one starts here also. |
|
687 |
int wantArg = goal.get(i); |
|
688 |
final int MAX_ARG_ROTATION = AdapterMethodHandle.MAX_ARG_ROTATION; |
|
689 |
if (arg != wantArg && |
|
690 |
arg >= wantArg - TOKEN * MAX_ARG_ROTATION && |
|
691 |
arg <= wantArg + TOKEN * MAX_ARG_ROTATION) { |
|
692 |
thisRotArg = arg; |
|
693 |
thisRotLen = 1; |
|
694 |
} |
|
695 |
} |
|
696 |
} |
|
697 |
if (bestRotLen >= 2) { |
|
698 |
// Do a rotation if it can improve argument positioning |
|
699 |
// by at least 2 arguments. This is not always optimal, |
|
700 |
// but it seems to catch common cases. |
|
701 |
int dstEnd = state.indexOf(bestRotArg); |
|
702 |
int srcEnd = goal.indexOf(bestRotArg); |
|
703 |
int rotBy = dstEnd - srcEnd; |
|
704 |
int dstBeg = dstEnd - (bestRotLen - 1); |
|
705 |
int srcBeg = srcEnd - (bestRotLen - 1); |
|
706 |
assert((dstEnd | dstBeg | srcEnd | srcBeg) >= 0); // no negs |
|
707 |
// Make a span which covers both source and destination. |
|
708 |
int rotBeg = Math.min(dstBeg, srcBeg); |
|
709 |
int rotEnd = Math.max(dstEnd, srcEnd); |
|
710 |
int score = 0; |
|
711 |
for (int i = rotBeg; i <= rotEnd; i++) { |
|
712 |
if ((int)state.get(i) != (int)goal.get(i)) |
|
713 |
score += 1; |
|
714 |
} |
|
715 |
List<Integer> rotSpan = state.subList(rotBeg, rotEnd+1); |
|
716 |
Collections.rotate(rotSpan, -rotBy); // reverse direction |
|
717 |
for (int i = rotBeg; i <= rotEnd; i++) { |
|
718 |
if ((int)state.get(i) != (int)goal.get(i)) |
|
719 |
score -= 1; |
|
720 |
} |
|
721 |
if (score >= 2) { |
|
722 |
// Improved at least two argument positions. Do it. |
|
723 |
List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray()); |
|
724 |
Collections.rotate(ptypes.subList(rotBeg, rotEnd+1), -rotBy); |
|
725 |
MethodType rotType = MethodType.methodType(oldType.returnType(), ptypes); |
|
726 |
MethodHandle nextTarget |
|
727 |
= AdapterMethodHandle.makeRotateArguments(token, rotType, target, |
|
728 |
rotBeg, rotSpan.size(), rotBy); |
|
729 |
if (nextTarget != null) { |
|
730 |
//System.out.println("Rot: "+rotSpan+" by "+rotBy); |
|
731 |
target = nextTarget; |
|
732 |
oldType = rotType; |
|
733 |
continue; |
|
734 |
} |
|
735 |
} |
|
736 |
// Else de-rotate, and drop through to the swap-fest. |
|
737 |
Collections.rotate(rotSpan, rotBy); |
|
738 |
} |
|
739 |
||
740 |
// Now swap like the wind! |
|
741 |
List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray()); |
|
742 |
for (int i = 0; i < size; i++) { |
|
743 |
// What argument do I want here? |
|
744 |
int arg = goal.get(i); |
|
745 |
if (arg != state.get(i)) { |
|
746 |
// Where is it now? |
|
747 |
int j = state.indexOf(arg); |
|
748 |
Collections.swap(ptypes, i, j); |
|
749 |
MethodType swapType = MethodType.methodType(oldType.returnType(), ptypes); |
|
750 |
target = AdapterMethodHandle.makeSwapArguments(token, swapType, target, i, j); |
|
751 |
if (target == null) throw newIllegalArgumentException("cannot swap"); |
|
752 |
assert(target.type() == swapType); |
|
753 |
oldType = swapType; |
|
754 |
Collections.swap(state, i, j); |
|
755 |
} |
|
756 |
} |
|
757 |
// One pass of swapping must finish the job. |
|
758 |
assert(state.equals(goal)); |
|
759 |
} |
|
760 |
while (!dups.isEmpty()) { |
|
761 |
// Grab a contiguous trailing sequence of dups. |
|
762 |
int grab = dups.size() - 1; |
|
763 |
int dupArgPos = dups.get(grab), dupArgCount = 1; |
|
764 |
while (grab - 1 >= 0) { |
|
765 |
int dup0 = dups.get(grab - 1); |
|
766 |
if (dup0 != dupArgPos - 1) break; |
|
767 |
dupArgPos -= 1; |
|
768 |
dupArgCount += 1; |
|
769 |
grab -= 1; |
|
770 |
} |
|
771 |
//if (dupArgCount > 1) System.out.println("Dup: "+dups.subList(grab, dups.size())); |
|
772 |
dups.subList(grab, dups.size()).clear(); |
|
773 |
// In the new target type drop that many args from the tail: |
|
774 |
List<Class<?>> ptypes = oldType.parameterList(); |
|
775 |
ptypes = ptypes.subList(0, ptypes.size() - dupArgCount); |
|
776 |
MethodType dupType = MethodType.methodType(oldType.returnType(), ptypes); |
|
777 |
target = AdapterMethodHandle.makeDupArguments(token, dupType, target, dupArgPos, dupArgCount); |
|
778 |
if (target == null) |
|
779 |
throw newIllegalArgumentException("cannot dup"); |
|
780 |
oldType = target.type(); |
|
781 |
} |
|
782 |
while (!drops.isEmpty()) { |
|
783 |
// Grab a contiguous initial sequence of drops. |
|
784 |
int dropArgPos = drops.get(0), dropArgCount = 1; |
|
785 |
while (dropArgCount < drops.size()) { |
|
786 |
int drop1 = drops.get(dropArgCount); |
|
787 |
if (drop1 != dropArgPos + dropArgCount) break; |
|
788 |
dropArgCount += 1; |
|
789 |
} |
|
790 |
//if (dropArgCount > 1) System.out.println("Drop: "+drops.subList(0, dropArgCount)); |
|
791 |
drops.subList(0, dropArgCount).clear(); |
|
792 |
List<Class<?>> dropTypes = newType.parameterList() |
|
793 |
.subList(dropArgPos, dropArgPos + dropArgCount); |
|
794 |
MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes); |
|
795 |
target = AdapterMethodHandle.makeDropArguments(token, dropType, target, dropArgPos, dropArgCount); |
|
796 |
if (target == null) throw newIllegalArgumentException("cannot drop"); |
|
797 |
oldType = target.type(); |
|
798 |
} |
|
799 |
} |
|
800 |
if (newType == oldType) |
|
801 |
return target; |
|
802 |
if (oldType.parameterCount() != newType.parameterCount()) |
|
803 |
throw newIllegalArgumentException("mismatched parameter count"); |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
804 |
MethodHandle res = AdapterMethodHandle.makePairwiseConvert(token, newType, target); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
805 |
if (res != null) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
806 |
return res; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
807 |
int argc = oldType.parameterCount(); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
808 |
// The JVM can't do it directly, so fill in the gap with a Java adapter. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
809 |
// TO DO: figure out what to put here from case-by-case experience |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
810 |
// Use a heavier method: Convert all the arguments to Object, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
811 |
// then back to the desired types. We might have to use Java-based |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
812 |
// method handles to do this. |
4537 | 813 |
MethodType objType = MethodType.genericMethodType(argc); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
814 |
MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
815 |
if (objTarget == null) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
816 |
objTarget = FromGeneric.make(target); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
817 |
res = AdapterMethodHandle.makePairwiseConvert(token, newType, objTarget); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
818 |
if (res != null) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
819 |
return res; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
820 |
return ToGeneric.make(newType, objTarget); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
821 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
822 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
823 |
public static MethodHandle spreadArguments(Access token, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
824 |
MethodHandle target, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
825 |
MethodType newType, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
826 |
int spreadArg) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
827 |
Access.check(token); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
828 |
// TO DO: maybe allow the restarg to be Object and implicitly cast to Object[] |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
829 |
MethodType oldType = target.type(); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
830 |
// spread the last argument of newType to oldType |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
831 |
int spreadCount = oldType.parameterCount() - spreadArg; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
832 |
Class<Object[]> spreadArgType = Object[].class; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
833 |
MethodHandle res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
834 |
if (res != null) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
835 |
return res; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
836 |
// try an intermediate adapter |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
837 |
Class<?> spreadType = null; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
838 |
if (spreadArg < 0 || spreadArg >= newType.parameterCount() |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
839 |
|| !VerifyType.isSpreadArgType(spreadType = newType.parameterType(spreadArg))) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
840 |
throw newIllegalArgumentException("no restarg in "+newType); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
841 |
Class<?>[] ptypes = oldType.parameterArray(); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
842 |
for (int i = 0; i < spreadCount; i++) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
843 |
ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i); |
4537 | 844 |
MethodType midType = MethodType.methodType(newType.returnType(), ptypes); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
845 |
// after spreading, some arguments may need further conversion |
4537 | 846 |
MethodHandle target2 = convertArguments(token, target, midType, oldType, null); |
847 |
if (target2 == null) |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
848 |
throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType); |
4537 | 849 |
res = AdapterMethodHandle.makeSpreadArguments(token, newType, target2, spreadArgType, spreadArg, spreadCount); |
850 |
if (res != null) |
|
851 |
return res; |
|
852 |
res = SpreadGeneric.make(target2, spreadCount); |
|
853 |
if (res != null) |
|
854 |
res = convertArguments(token, res, newType, res.type(), null); |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
855 |
return res; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
856 |
} |
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 |
public static MethodHandle collectArguments(Access token, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
859 |
MethodHandle target, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
860 |
MethodType newType, |
4537 | 861 |
int collectArg, |
862 |
MethodHandle collector) { |
|
863 |
MethodType oldType = target.type(); // (a...,c)=>r |
|
864 |
if (collector == null) { |
|
865 |
int numCollect = newType.parameterCount() - oldType.parameterCount() + 1; |
|
866 |
collector = ValueConversions.varargsArray(numCollect); |
|
867 |
} |
|
868 |
// newType // (a..., b...)=>r |
|
869 |
MethodType colType = collector.type(); // (b...)=>c |
|
870 |
// oldType // (a..., b...)=>r |
|
871 |
assert(newType.parameterCount() == collectArg + colType.parameterCount()); |
|
872 |
assert(oldType.parameterCount() == collectArg + 1); |
|
873 |
MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null); |
|
874 |
MethodHandle gcollector = convertArguments(token, collector, colType.generic(), colType, null); |
|
875 |
if (gtarget == null || gcollector == null) return null; |
|
876 |
MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget); |
|
877 |
MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null); |
|
878 |
return result; |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
879 |
} |
4537 | 880 |
|
881 |
public static MethodHandle filterArgument(Access token, |
|
882 |
MethodHandle target, |
|
883 |
int pos, |
|
884 |
MethodHandle filter) { |
|
885 |
Access.check(token); |
|
886 |
MethodType ttype = target.type(), gttype = ttype.generic(); |
|
887 |
if (ttype != gttype) { |
|
888 |
target = convertArguments(token, target, gttype, ttype, null); |
|
889 |
ttype = gttype; |
|
890 |
} |
|
891 |
MethodType ftype = filter.type(), gftype = ftype.generic(); |
|
892 |
if (ftype.parameterCount() != 1) |
|
893 |
throw new InternalError(); |
|
894 |
if (ftype != gftype) { |
|
895 |
filter = convertArguments(token, filter, gftype, ftype, null); |
|
896 |
ftype = gftype; |
|
897 |
} |
|
898 |
if (ftype == ttype) { |
|
899 |
// simple unary case |
|
900 |
return FilterOneArgument.make(filter, target); |
|
901 |
} |
|
902 |
return FilterGeneric.makeArgumentFilter(pos, filter, target); |
|
903 |
} |
|
904 |
||
905 |
public static MethodHandle foldArguments(Access token, |
|
906 |
MethodHandle target, |
|
907 |
MethodType newType, |
|
908 |
MethodHandle combiner) { |
|
909 |
Access.check(token); |
|
910 |
MethodType oldType = target.type(); |
|
911 |
MethodType ctype = combiner.type(); |
|
912 |
MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null); |
|
913 |
MethodHandle gcombiner = convertArguments(token, combiner, ctype.generic(), ctype, null); |
|
914 |
if (gtarget == null || gcombiner == null) return null; |
|
915 |
MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget); |
|
916 |
MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null); |
|
917 |
return result; |
|
918 |
} |
|
919 |
||
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
920 |
public static |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
921 |
MethodHandle dropArguments(Access token, MethodHandle target, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
922 |
MethodType newType, int argnum) { |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
923 |
Access.check(token); |
4537 | 924 |
int drops = newType.parameterCount() - target.type().parameterCount(); |
925 |
MethodHandle res = AdapterMethodHandle.makeDropArguments(token, newType, target, argnum, drops); |
|
926 |
if (res != null) |
|
927 |
return res; |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
928 |
throw new UnsupportedOperationException("NYI"); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
929 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
930 |
|
4537 | 931 |
private static class GuardWithTest extends JavaMethodHandle { |
932 |
private final MethodHandle test, target, fallback; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
933 |
private GuardWithTest(MethodHandle invoker, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
934 |
MethodHandle test, MethodHandle target, MethodHandle fallback) { |
4537 | 935 |
super(invoker); |
936 |
this.test = test; |
|
937 |
this.target = target; |
|
938 |
this.fallback = fallback; |
|
939 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
940 |
static MethodHandle make(Access token, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
941 |
MethodHandle test, MethodHandle target, MethodHandle fallback) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
942 |
Access.check(token); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
943 |
MethodType type = target.type(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
944 |
int nargs = type.parameterCount(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
945 |
if (nargs < INVOKES.length) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
946 |
MethodHandle invoke = INVOKES[nargs]; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
947 |
MethodType gtype = type.generic(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
948 |
assert(invoke.type().dropParameterTypes(0,1) == gtype); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
949 |
MethodHandle gtest = convertArguments(token, test, gtype.changeReturnType(boolean.class), test.type(), null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
950 |
MethodHandle gtarget = convertArguments(token, target, gtype, type, null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
951 |
MethodHandle gfallback = convertArguments(token, fallback, gtype, type, null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
952 |
if (gtest == null || gtarget == null || gfallback == null) return null; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
953 |
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
954 |
return convertArguments(token, gguard, type, gtype, null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
955 |
} else { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
956 |
MethodHandle invoke = VARARGS_INVOKE; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
957 |
MethodType gtype = MethodType.genericMethodType(1); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
958 |
assert(invoke.type().dropParameterTypes(0,1) == gtype); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
959 |
MethodHandle gtest = spreadArguments(token, test, gtype.changeReturnType(boolean.class), 0); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
960 |
MethodHandle gtarget = spreadArguments(token, target, gtype, 0); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
961 |
MethodHandle gfallback = spreadArguments(token, fallback, gtype, 0); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
962 |
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
963 |
if (gtest == null || gtarget == null || gfallback == null) return null; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
964 |
return collectArguments(token, gguard, type, 0, null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
965 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
966 |
} |
4537 | 967 |
@Override |
968 |
public String toString() { |
|
969 |
return target.toString(); |
|
970 |
} |
|
971 |
private Object invoke_V(Object... av) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
972 |
if (test.<boolean>invokeExact(av)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
973 |
return target.<Object>invokeExact(av); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
974 |
return fallback.<Object>invokeExact(av); |
4537 | 975 |
} |
976 |
private Object invoke_L0() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
977 |
if (test.<boolean>invokeExact()) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
978 |
return target.<Object>invokeExact(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
979 |
return fallback.<Object>invokeExact(); |
4537 | 980 |
} |
981 |
private Object invoke_L1(Object a0) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
982 |
if (test.<boolean>invokeExact(a0)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
983 |
return target.<Object>invokeExact(a0); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
984 |
return fallback.<Object>invokeExact(a0); |
4537 | 985 |
} |
986 |
private Object invoke_L2(Object a0, Object a1) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
987 |
if (test.<boolean>invokeExact(a0, a1)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
988 |
return target.<Object>invokeExact(a0, a1); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
989 |
return fallback.<Object>invokeExact(a0, a1); |
4537 | 990 |
} |
991 |
private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
992 |
if (test.<boolean>invokeExact(a0, a1, a2)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
993 |
return target.<Object>invokeExact(a0, a1, a2); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
994 |
return fallback.<Object>invokeExact(a0, a1, a2); |
4537 | 995 |
} |
996 |
private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
997 |
if (test.<boolean>invokeExact(a0, a1, a2, a3)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
998 |
return target.<Object>invokeExact(a0, a1, a2, a3); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
999 |
return fallback.<Object>invokeExact(a0, a1, a2, a3); |
4537 | 1000 |
} |
1001 |
private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1002 |
if (test.<boolean>invokeExact(a0, a1, a2, a3, a4)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1003 |
return target.<Object>invokeExact(a0, a1, a2, a3, a4); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1004 |
return fallback.<Object>invokeExact(a0, a1, a2, a3, a4); |
4537 | 1005 |
} |
1006 |
private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1007 |
if (test.<boolean>invokeExact(a0, a1, a2, a3, a4, a5)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1008 |
return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1009 |
return fallback.<Object>invokeExact(a0, a1, a2, a3, a4, a5); |
4537 | 1010 |
} |
1011 |
private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1012 |
if (test.<boolean>invokeExact(a0, a1, a2, a3, a4, a5, a6)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1013 |
return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1014 |
return fallback.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6); |
4537 | 1015 |
} |
1016 |
private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1017 |
if (test.<boolean>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1018 |
return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1019 |
return fallback.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); |
4537 | 1020 |
} |
1021 |
static MethodHandle[] makeInvokes() { |
|
1022 |
ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>(); |
|
1023 |
MethodHandles.Lookup lookup = IMPL_LOOKUP; |
|
1024 |
for (;;) { |
|
1025 |
int nargs = invokes.size(); |
|
1026 |
String name = "invoke_L"+nargs; |
|
1027 |
MethodHandle invoke = null; |
|
1028 |
try { |
|
1029 |
invoke = lookup.findVirtual(GuardWithTest.class, name, MethodType.genericMethodType(nargs)); |
|
1030 |
} catch (NoAccessException ex) { |
|
1031 |
} |
|
1032 |
if (invoke == null) break; |
|
1033 |
invokes.add(invoke); |
|
1034 |
} |
|
1035 |
assert(invokes.size() == 9); // current number of methods |
|
1036 |
return invokes.toArray(new MethodHandle[0]); |
|
1037 |
}; |
|
1038 |
static final MethodHandle[] INVOKES = makeInvokes(); |
|
1039 |
// For testing use this: |
|
1040 |
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2); |
|
1041 |
static final MethodHandle VARARGS_INVOKE; |
|
1042 |
static { |
|
1043 |
try { |
|
1044 |
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true)); |
|
1045 |
} catch (NoAccessException ex) { |
|
1046 |
throw new InternalError(""); |
|
1047 |
} |
|
1048 |
} |
|
1049 |
} |
|
1050 |
||
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1051 |
public static |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1052 |
MethodHandle makeGuardWithTest(Access token, |
4537 | 1053 |
MethodHandle test, |
1054 |
MethodHandle target, |
|
1055 |
MethodHandle fallback) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1056 |
return GuardWithTest.make(token, test, target, fallback); |
4537 | 1057 |
} |
1058 |
||
1059 |
private static class GuardWithCatch extends JavaMethodHandle { |
|
1060 |
private final MethodHandle target; |
|
1061 |
private final Class<? extends Throwable> exType; |
|
1062 |
private final MethodHandle catcher; |
|
1063 |
public GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) { |
|
1064 |
this(INVOKES[target.type().parameterCount()], target, exType, catcher); |
|
1065 |
} |
|
1066 |
public GuardWithCatch(MethodHandle invoker, |
|
1067 |
MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) { |
|
1068 |
super(invoker); |
|
1069 |
this.target = target; |
|
1070 |
this.exType = exType; |
|
1071 |
this.catcher = catcher; |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1072 |
} |
4537 | 1073 |
@Override |
1074 |
public String toString() { |
|
1075 |
return target.toString(); |
|
1076 |
} |
|
1077 |
private Object invoke_V(Object... av) throws Throwable { |
|
1078 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1079 |
return target.<Object>invokeExact(av); |
4537 | 1080 |
} catch (Throwable t) { |
1081 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1082 |
return catcher.<Object>invokeExact(t, av); |
4537 | 1083 |
} |
1084 |
} |
|
1085 |
private Object invoke_L0() throws Throwable { |
|
1086 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1087 |
return target.<Object>invokeExact(); |
4537 | 1088 |
} catch (Throwable t) { |
1089 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1090 |
return catcher.<Object>invokeExact(t); |
4537 | 1091 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1092 |
} |
4537 | 1093 |
private Object invoke_L1(Object a0) throws Throwable { |
1094 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1095 |
return target.<Object>invokeExact(a0); |
4537 | 1096 |
} catch (Throwable t) { |
1097 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1098 |
return catcher.<Object>invokeExact(t, a0); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1099 |
} |
4537 | 1100 |
} |
1101 |
private Object invoke_L2(Object a0, Object a1) throws Throwable { |
|
1102 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1103 |
return target.<Object>invokeExact(a0, a1); |
4537 | 1104 |
} catch (Throwable t) { |
1105 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1106 |
return catcher.<Object>invokeExact(t, a0, a1); |
4537 | 1107 |
} |
1108 |
} |
|
1109 |
private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { |
|
1110 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1111 |
return target.<Object>invokeExact(a0, a1, a2); |
4537 | 1112 |
} catch (Throwable t) { |
1113 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1114 |
return catcher.<Object>invokeExact(t, a0, a1, a2); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1115 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1116 |
} |
4537 | 1117 |
private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { |
1118 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1119 |
return target.<Object>invokeExact(a0, a1, a2, a3); |
4537 | 1120 |
} catch (Throwable t) { |
1121 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1122 |
return catcher.<Object>invokeExact(t, a0, a1, a2, a3); |
4537 | 1123 |
} |
1124 |
} |
|
1125 |
private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { |
|
1126 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1127 |
return target.<Object>invokeExact(a0, a1, a2, a3, a4); |
4537 | 1128 |
} catch (Throwable t) { |
1129 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1130 |
return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4); |
4537 | 1131 |
} |
1132 |
} |
|
1133 |
private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { |
|
1134 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1135 |
return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5); |
4537 | 1136 |
} catch (Throwable t) { |
1137 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1138 |
return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4, a5); |
4537 | 1139 |
} |
1140 |
} |
|
1141 |
private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { |
|
1142 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1143 |
return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6); |
4537 | 1144 |
} catch (Throwable t) { |
1145 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1146 |
return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4, a5, a6); |
4537 | 1147 |
} |
1148 |
} |
|
1149 |
private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { |
|
1150 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1151 |
return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); |
4537 | 1152 |
} catch (Throwable t) { |
1153 |
if (!exType.isInstance(t)) throw t; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1154 |
return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7); |
4537 | 1155 |
} |
1156 |
} |
|
1157 |
static MethodHandle[] makeInvokes() { |
|
1158 |
ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>(); |
|
1159 |
MethodHandles.Lookup lookup = IMPL_LOOKUP; |
|
1160 |
for (;;) { |
|
1161 |
int nargs = invokes.size(); |
|
1162 |
String name = "invoke_L"+nargs; |
|
1163 |
MethodHandle invoke = null; |
|
1164 |
try { |
|
1165 |
invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs)); |
|
1166 |
} catch (NoAccessException ex) { |
|
1167 |
} |
|
1168 |
if (invoke == null) break; |
|
1169 |
invokes.add(invoke); |
|
1170 |
} |
|
1171 |
assert(invokes.size() == 9); // current number of methods |
|
1172 |
return invokes.toArray(new MethodHandle[0]); |
|
1173 |
}; |
|
1174 |
static final MethodHandle[] INVOKES = makeInvokes(); |
|
1175 |
// For testing use this: |
|
1176 |
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2); |
|
1177 |
static final MethodHandle VARARGS_INVOKE; |
|
1178 |
static { |
|
1179 |
try { |
|
1180 |
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true)); |
|
1181 |
} catch (NoAccessException ex) { |
|
1182 |
throw new InternalError(""); |
|
1183 |
} |
|
1184 |
} |
|
1185 |
} |
|
1186 |
||
1187 |
||
1188 |
public static |
|
1189 |
MethodHandle makeGuardWithCatch(Access token, |
|
1190 |
MethodHandle target, |
|
1191 |
Class<? extends Throwable> exType, |
|
1192 |
MethodHandle catcher) { |
|
1193 |
Access.check(token); |
|
1194 |
MethodType type = target.type(); |
|
1195 |
MethodType ctype = catcher.type(); |
|
1196 |
int nargs = type.parameterCount(); |
|
1197 |
if (nargs < GuardWithCatch.INVOKES.length) { |
|
1198 |
MethodType gtype = type.generic(); |
|
1199 |
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); |
|
1200 |
MethodHandle gtarget = convertArguments(token, target, gtype, type, null); |
|
1201 |
MethodHandle gcatcher = convertArguments(token, catcher, gcatchType, ctype, null); |
|
1202 |
MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher); |
|
1203 |
if (gtarget == null || gcatcher == null || gguard == null) return null; |
|
1204 |
return convertArguments(token, gguard, type, gtype, null); |
|
1205 |
} else { |
|
1206 |
MethodType gtype = MethodType.genericMethodType(0, true); |
|
1207 |
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); |
|
1208 |
MethodHandle gtarget = spreadArguments(token, target, gtype, 0); |
|
1209 |
MethodHandle gcatcher = spreadArguments(token, catcher, gcatchType, 1); |
|
1210 |
MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher); |
|
1211 |
if (gtarget == null || gcatcher == null || gguard == null) return null; |
|
1212 |
return collectArguments(token, gguard, type, 0, null); |
|
1213 |
} |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1214 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1215 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1216 |
public static |
4537 | 1217 |
MethodHandle throwException(Access token, MethodType type) { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1218 |
Access.check(token); |
4537 | 1219 |
return AdapterMethodHandle.makeRetypeRaw(token, type, THROW_EXCEPTION); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1220 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1221 |
|
4537 | 1222 |
static final MethodHandle THROW_EXCEPTION |
1223 |
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException", |
|
1224 |
MethodType.methodType(Empty.class, Throwable.class)); |
|
1225 |
static <T extends Throwable> Empty throwException(T t) throws T { throw t; } |
|
1226 |
||
1227 |
public static String getNameString(Access token, MethodHandle target) { |
|
1228 |
Access.check(token); |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1229 |
MemberName name = null; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1230 |
if (target != null) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1231 |
name = MethodHandleNatives.getMethodName(target); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1232 |
if (name == null) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1233 |
return "<unknown>"; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1234 |
return name.getName(); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1235 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1236 |
|
4537 | 1237 |
public static String addTypeString(MethodHandle target) { |
1238 |
if (target == null) return "null"; |
|
1239 |
return target.toString() + target.type(); |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1240 |
} |
4537 | 1241 |
|
1242 |
public static void checkSpreadArgument(Object av, int n) { |
|
1243 |
if (av == null ? n != 0 : ((Object[])av).length != n) |
|
1244 |
throw newIllegalArgumentException("Array is not of length "+n); |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1245 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1246 |
|
4537 | 1247 |
public static void raiseException(int code, Object actual, Object required) { |
1248 |
String message; |
|
1249 |
// disregard the identity of the actual object, if it is not a class: |
|
1250 |
if (!(actual instanceof Class) && !(actual instanceof MethodType)) |
|
1251 |
actual = actual.getClass(); |
|
1252 |
if (actual != null) |
|
1253 |
message = "required "+required+" but encountered "+actual; |
|
1254 |
else |
|
1255 |
message = "required "+required; |
|
1256 |
switch (code) { |
|
1257 |
case 192: // checkcast |
|
1258 |
throw new ClassCastException(message); |
|
1259 |
default: |
|
1260 |
throw new InternalError("unexpected code "+code+": "+message); |
|
1261 |
} |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1262 |
} |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1263 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1264 |
// Linkage support: |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1265 |
public static void registerBootstrap(Access token, Class<?> callerClass, MethodHandle bootstrapMethod) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1266 |
Access.check(token); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1267 |
MethodHandleNatives.registerBootstrap(callerClass, bootstrapMethod); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1268 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1269 |
public static MethodHandle getBootstrap(Access token, Class<?> callerClass) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1270 |
Access.check(token); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1271 |
return MethodHandleNatives.getBootstrap(callerClass); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1272 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1273 |
} |