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