author | jrose |
Thu, 12 Jul 2012 00:11:35 -0700 | |
changeset 13420 | 62cedce8afa6 |
parent 11534 | 9949ffb8eb3a |
child 13423 | 17843fff200d |
permissions | -rw-r--r-- |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
1 |
/* |
8345
9e2483e6cfab
7013417: JSR 292 needs to support variadic method handle calls
jrose
parents:
7556
diff
changeset
|
2 |
* Copyright (c) 2008, 2011, 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 |
|
8822
8145ab9f5f86
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
8821
diff
changeset
|
26 |
package java.lang.invoke; |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
27 |
|
8822
8145ab9f5f86
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
8821
diff
changeset
|
28 |
import sun.invoke.util.VerifyType; |
9780
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
29 |
import java.security.AccessController; |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
30 |
import java.security.PrivilegedAction; |
4537 | 31 |
import java.util.ArrayList; |
32 |
import java.util.Arrays; |
|
33 |
import java.util.Collections; |
|
34 |
import java.util.HashMap; |
|
35 |
import java.util.List; |
|
8822
8145ab9f5f86
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
8821
diff
changeset
|
36 |
import sun.invoke.empty.Empty; |
8145ab9f5f86
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
8821
diff
changeset
|
37 |
import sun.invoke.util.ValueConversions; |
8145ab9f5f86
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
8821
diff
changeset
|
38 |
import sun.invoke.util.Wrapper; |
4537 | 39 |
import sun.misc.Unsafe; |
8822
8145ab9f5f86
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
8821
diff
changeset
|
40 |
import static java.lang.invoke.MethodHandleStatics.*; |
8145ab9f5f86
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
8821
diff
changeset
|
41 |
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
42 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
43 |
/** |
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
44 |
* Trusted implementation code for MethodHandle. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
45 |
* @author jrose |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
46 |
*/ |
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
47 |
/*non-public*/ abstract class MethodHandleImpl { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
48 |
/// Factory methods to create method handles: |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
49 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
50 |
private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE; |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
51 |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
52 |
static void initStatics() { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
53 |
// Trigger preceding sequence. |
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 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
56 |
/** Look up a given method. |
8822
8145ab9f5f86
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
8821
diff
changeset
|
57 |
* Callable only from sun.invoke and related packages. |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
58 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
59 |
* 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
|
60 |
* 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
|
61 |
* <p> |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
62 |
* 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
|
63 |
* 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
|
64 |
* 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
|
65 |
* the lookup class or a subclass. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
66 |
* @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
|
67 |
* @param member Resolved method or constructor to call. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
68 |
* @param name Name of the desired method. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
69 |
* @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
|
70 |
* @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
|
71 |
* @param lookupClass access-check relative to this class |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
72 |
* @return a direct handle to the matching method |
8347
e5daa5772ffd
7013730: JSR 292 reflective operations should report errors with standard exception types
jrose
parents:
8346
diff
changeset
|
73 |
* @throws IllegalAccessException if the given method cannot be accessed by the lookup class |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
74 |
*/ |
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
75 |
static |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
76 |
MethodHandle findMethod(MemberName method, |
8347
e5daa5772ffd
7013730: JSR 292 reflective operations should report errors with standard exception types
jrose
parents:
8346
diff
changeset
|
77 |
boolean doDispatch, Class<?> lookupClass) throws IllegalAccessException { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
78 |
MethodType mtype = method.getMethodType(); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
79 |
if (!method.isStatic()) { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
80 |
// 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
|
81 |
// (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
|
82 |
Class<?> recvType = method.getDeclaringClass(); |
4537 | 83 |
mtype = mtype.insertParameterTypes(0, recvType); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
84 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
85 |
DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
86 |
if (!mh.isValid()) |
9752
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
87 |
throw method.makeAccessException("no direct method handle", lookupClass); |
5723
a58a0eed34b0
6939196: method handle signatures off the boot class path get linkage errors
jrose
parents:
5722
diff
changeset
|
88 |
assert(mh.type() == mtype); |
8345
9e2483e6cfab
7013417: JSR 292 needs to support variadic method handle calls
jrose
parents:
7556
diff
changeset
|
89 |
if (!method.isVarargs()) |
9e2483e6cfab
7013417: JSR 292 needs to support variadic method handle calls
jrose
parents:
7556
diff
changeset
|
90 |
return mh; |
9752
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
91 |
int argc = mtype.parameterCount(); |
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
92 |
if (argc != 0) { |
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
93 |
Class<?> arrayType = mtype.parameterType(argc-1); |
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
94 |
if (arrayType.isArray()) |
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
95 |
return AdapterMethodHandle.makeVarargsCollector(mh, arrayType); |
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
96 |
} |
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
97 |
throw method.makeAccessException("cannot make variable arity", null); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
98 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
99 |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
100 |
static |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
101 |
MethodHandle makeAllocator(MethodHandle rawConstructor) { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
102 |
MethodType rawConType = rawConstructor.type(); |
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
103 |
Class<?> allocateClass = rawConType.parameterType(0); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
104 |
// Wrap the raw (unsafe) constructor with the allocation of a suitable object. |
10082 | 105 |
assert(AdapterMethodHandle.canCollectArguments(rawConType, MethodType.methodType(allocateClass), 0, true)); |
106 |
// allocator(arg...) |
|
107 |
// [fold]=> cookedConstructor(obj=allocate(C), arg...) |
|
108 |
// [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...)) |
|
109 |
MethodHandle returner = MethodHandles.identity(allocateClass); |
|
110 |
MethodType ctype = rawConType.insertParameterTypes(0, allocateClass).changeReturnType(allocateClass); |
|
111 |
MethodHandle cookedConstructor = AdapterMethodHandle.makeCollectArguments(returner, rawConstructor, 1, false); |
|
112 |
assert(cookedConstructor.type().equals(ctype)); |
|
113 |
ctype = ctype.dropParameterTypes(0, 1); |
|
114 |
cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true); |
|
11534
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
115 |
AllocateObject allocator = new AllocateObject(allocateClass); |
10082 | 116 |
// allocate() => new C(void) |
117 |
assert(allocator.type().equals(MethodType.methodType(allocateClass))); |
|
118 |
ctype = ctype.dropParameterTypes(0, 1); |
|
119 |
MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator); |
|
120 |
return fold; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
121 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
122 |
|
11534
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
123 |
static final class AllocateObject /*<C>*/ extends BoundMethodHandle { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
124 |
private static final Unsafe unsafe = Unsafe.getUnsafe(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
125 |
|
11534
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
126 |
private final Class<?> /*<C>*/ allocateClass; |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
127 |
|
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
128 |
// for allocation only: |
11534
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
129 |
private AllocateObject(Class<?> /*<C>*/ allocateClass) { |
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
130 |
super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class))); |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
131 |
this.allocateClass = allocateClass; |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
132 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
133 |
@SuppressWarnings("unchecked") |
11534
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
134 |
private Object /*C*/ allocate() throws InstantiationException { |
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
135 |
return unsafe.allocateInstance(allocateClass); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
136 |
} |
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
137 |
static final MethodHandle ALLOCATE; |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
138 |
static { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
139 |
try { |
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
140 |
ALLOCATE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "allocate", MethodType.genericMethodType(0)); |
8347
e5daa5772ffd
7013730: JSR 292 reflective operations should report errors with standard exception types
jrose
parents:
8346
diff
changeset
|
141 |
} catch (ReflectiveOperationException ex) { |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
5725
diff
changeset
|
142 |
throw uncaughtException(ex); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
143 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
144 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
145 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
146 |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
147 |
static |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
148 |
MethodHandle accessField(MemberName member, boolean isSetter, |
4537 | 149 |
Class<?> lookupClass) { |
150 |
// Use sun. misc.Unsafe to dig up the dirt on the field. |
|
11534
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
151 |
FieldAccessor accessor = new FieldAccessor(member, isSetter); |
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
152 |
return accessor; |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
153 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
154 |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
155 |
static |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
156 |
MethodHandle accessArrayElement(Class<?> arrayClass, boolean isSetter) { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
157 |
if (!arrayClass.isArray()) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
158 |
throw newIllegalArgumentException("not an array: "+arrayClass); |
4537 | 159 |
Class<?> elemClass = arrayClass.getComponentType(); |
160 |
MethodHandle[] mhs = FieldAccessor.ARRAY_CACHE.get(elemClass); |
|
161 |
if (mhs == null) { |
|
162 |
if (!FieldAccessor.doCache(elemClass)) |
|
163 |
return FieldAccessor.ahandle(arrayClass, isSetter); |
|
164 |
mhs = new MethodHandle[] { |
|
165 |
FieldAccessor.ahandle(arrayClass, false), |
|
166 |
FieldAccessor.ahandle(arrayClass, true) |
|
167 |
}; |
|
168 |
if (mhs[0].type().parameterType(0) == Class.class) { |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
169 |
mhs[0] = mhs[0].bindTo(elemClass); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
170 |
mhs[1] = mhs[1].bindTo(elemClass); |
4537 | 171 |
} |
172 |
synchronized (FieldAccessor.ARRAY_CACHE) {} // memory barrier |
|
173 |
FieldAccessor.ARRAY_CACHE.put(elemClass, mhs); |
|
174 |
} |
|
175 |
return mhs[isSetter ? 1 : 0]; |
|
176 |
} |
|
177 |
||
11534
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
178 |
static final class FieldAccessor /*<C,V>*/ extends BoundMethodHandle { |
4537 | 179 |
private static final Unsafe unsafe = Unsafe.getUnsafe(); |
180 |
final Object base; // for static refs only |
|
181 |
final long offset; |
|
182 |
final String name; |
|
183 |
||
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
184 |
FieldAccessor(MemberName field, boolean isSetter) { |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
185 |
super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic())); |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
186 |
this.offset = (long) field.getVMIndex(); |
4537 | 187 |
this.name = field.getName(); |
188 |
this.base = staticBase(field); |
|
189 |
} |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
190 |
@Override |
9731
d0f7a3e441c4
7044892: JSR 292: API entry points sometimes throw the wrong exceptions or doesn't throw the expected one
jrose
parents:
9730
diff
changeset
|
191 |
String debugString() { return addTypeString(name, this); } |
4537 | 192 |
|
13420
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
193 |
private static Object nullCheck(Object obj) { |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
194 |
obj.getClass(); // NPE |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
195 |
return obj; |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
196 |
} |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
197 |
|
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
198 |
int getFieldI(Object /*C*/ obj) { return unsafe.getInt(nullCheck(obj), offset); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
199 |
void setFieldI(Object /*C*/ obj, int x) { unsafe.putInt(nullCheck(obj), offset, x); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
200 |
long getFieldJ(Object /*C*/ obj) { return unsafe.getLong(nullCheck(obj), offset); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
201 |
void setFieldJ(Object /*C*/ obj, long x) { unsafe.putLong(nullCheck(obj), offset, x); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
202 |
float getFieldF(Object /*C*/ obj) { return unsafe.getFloat(nullCheck(obj), offset); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
203 |
void setFieldF(Object /*C*/ obj, float x) { unsafe.putFloat(nullCheck(obj), offset, x); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
204 |
double getFieldD(Object /*C*/ obj) { return unsafe.getDouble(nullCheck(obj), offset); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
205 |
void setFieldD(Object /*C*/ obj, double x) { unsafe.putDouble(nullCheck(obj), offset, x); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
206 |
boolean getFieldZ(Object /*C*/ obj) { return unsafe.getBoolean(nullCheck(obj), offset); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
207 |
void setFieldZ(Object /*C*/ obj, boolean x) { unsafe.putBoolean(nullCheck(obj), offset, x); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
208 |
byte getFieldB(Object /*C*/ obj) { return unsafe.getByte(nullCheck(obj), offset); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
209 |
void setFieldB(Object /*C*/ obj, byte x) { unsafe.putByte(nullCheck(obj), offset, x); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
210 |
short getFieldS(Object /*C*/ obj) { return unsafe.getShort(nullCheck(obj), offset); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
211 |
void setFieldS(Object /*C*/ obj, short x) { unsafe.putShort(nullCheck(obj), offset, x); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
212 |
char getFieldC(Object /*C*/ obj) { return unsafe.getChar(nullCheck(obj), offset); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
213 |
void setFieldC(Object /*C*/ obj, char x) { unsafe.putChar(nullCheck(obj), offset, x); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
214 |
Object /*V*/ getFieldL(Object /*C*/ obj) { return unsafe.getObject(nullCheck(obj), offset); } |
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
215 |
void setFieldL(Object /*C*/ obj, Object /*V*/ x) { unsafe.putObject(nullCheck(obj), offset, x); } |
4537 | 216 |
|
9780
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
217 |
static Object staticBase(final MemberName field) { |
4537 | 218 |
if (!field.isStatic()) return null; |
9780
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
219 |
return AccessController.doPrivileged(new PrivilegedAction<Object>() { |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
220 |
public Object run() { |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
221 |
try { |
13420
62cedce8afa6
7129034: VM crash with a field setter method with a filterArguments
jrose
parents:
11534
diff
changeset
|
222 |
Class<?> c = field.getDeclaringClass(); |
9780
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
223 |
// FIXME: Should not have to create 'f' to get this value. |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
224 |
java.lang.reflect.Field f = c.getDeclaredField(field.getName()); |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
225 |
return unsafe.staticFieldBase(f); |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
226 |
} catch (NoSuchFieldException ee) { |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
227 |
throw uncaughtException(ee); |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
228 |
} |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
229 |
} |
6fc3b49cfee4
7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager
jrose
parents:
9752
diff
changeset
|
230 |
}); |
4537 | 231 |
} |
232 |
||
233 |
int getStaticI() { return unsafe.getInt(base, offset); } |
|
234 |
void setStaticI(int x) { unsafe.putInt(base, offset, x); } |
|
235 |
long getStaticJ() { return unsafe.getLong(base, offset); } |
|
236 |
void setStaticJ(long x) { unsafe.putLong(base, offset, x); } |
|
237 |
float getStaticF() { return unsafe.getFloat(base, offset); } |
|
238 |
void setStaticF(float x) { unsafe.putFloat(base, offset, x); } |
|
239 |
double getStaticD() { return unsafe.getDouble(base, offset); } |
|
240 |
void setStaticD(double x) { unsafe.putDouble(base, offset, x); } |
|
241 |
boolean getStaticZ() { return unsafe.getBoolean(base, offset); } |
|
242 |
void setStaticZ(boolean x) { unsafe.putBoolean(base, offset, x); } |
|
243 |
byte getStaticB() { return unsafe.getByte(base, offset); } |
|
244 |
void setStaticB(byte x) { unsafe.putByte(base, offset, x); } |
|
245 |
short getStaticS() { return unsafe.getShort(base, offset); } |
|
246 |
void setStaticS(short x) { unsafe.putShort(base, offset, x); } |
|
247 |
char getStaticC() { return unsafe.getChar(base, offset); } |
|
248 |
void setStaticC(char x) { unsafe.putChar(base, offset, x); } |
|
11534
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
249 |
Object /*V*/ getStaticL() { return unsafe.getObject(base, offset); } |
9949ffb8eb3a
7117167: Misc warnings in java.lang.invoke and sun.invoke.*
jrose
parents:
11007
diff
changeset
|
250 |
void setStaticL(Object /*V*/ x) { unsafe.putObject(base, offset, x); } |
4537 | 251 |
|
252 |
static String fname(Class<?> vclass, boolean isSetter, boolean isStatic) { |
|
253 |
String stem; |
|
254 |
if (!isStatic) |
|
255 |
stem = (!isSetter ? "getField" : "setField"); |
|
256 |
else |
|
257 |
stem = (!isSetter ? "getStatic" : "setStatic"); |
|
258 |
return stem + Wrapper.basicTypeChar(vclass); |
|
259 |
} |
|
260 |
static MethodType ftype(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) { |
|
261 |
MethodType type; |
|
262 |
if (!isStatic) { |
|
263 |
if (!isSetter) |
|
264 |
return MethodType.methodType(vclass, cclass); |
|
265 |
else |
|
266 |
return MethodType.methodType(void.class, cclass, vclass); |
|
267 |
} else { |
|
268 |
if (!isSetter) |
|
269 |
return MethodType.methodType(vclass); |
|
270 |
else |
|
271 |
return MethodType.methodType(void.class, vclass); |
|
272 |
} |
|
273 |
} |
|
274 |
static MethodHandle fhandle(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) { |
|
275 |
String name = FieldAccessor.fname(vclass, isSetter, isStatic); |
|
276 |
if (cclass.isPrimitive()) throw newIllegalArgumentException("primitive "+cclass); |
|
277 |
Class<?> ecclass = Object.class; //erase this type |
|
278 |
Class<?> evclass = vclass; |
|
279 |
if (!evclass.isPrimitive()) evclass = Object.class; |
|
280 |
MethodType type = FieldAccessor.ftype(ecclass, evclass, isSetter, isStatic); |
|
281 |
MethodHandle mh; |
|
282 |
try { |
|
283 |
mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type); |
|
8347
e5daa5772ffd
7013730: JSR 292 reflective operations should report errors with standard exception types
jrose
parents:
8346
diff
changeset
|
284 |
} catch (ReflectiveOperationException ex) { |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
5725
diff
changeset
|
285 |
throw uncaughtException(ex); |
4537 | 286 |
} |
287 |
if (evclass != vclass || (!isStatic && ecclass != cclass)) { |
|
288 |
MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic); |
|
289 |
strongType = strongType.insertParameterTypes(0, FieldAccessor.class); |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
290 |
mh = convertArguments(mh, strongType, 0); |
4537 | 291 |
} |
292 |
return mh; |
|
293 |
} |
|
294 |
||
295 |
/// Support for array element access |
|
296 |
static final HashMap<Class<?>, MethodHandle[]> ARRAY_CACHE = |
|
297 |
new HashMap<Class<?>, MethodHandle[]>(); |
|
298 |
// FIXME: Cache on the classes themselves, not here. |
|
299 |
static boolean doCache(Class<?> elemClass) { |
|
300 |
if (elemClass.isPrimitive()) return true; |
|
301 |
ClassLoader cl = elemClass.getClassLoader(); |
|
302 |
return cl == null || cl == ClassLoader.getSystemClassLoader(); |
|
303 |
} |
|
304 |
static int getElementI(int[] a, int i) { return a[i]; } |
|
305 |
static void setElementI(int[] a, int i, int x) { a[i] = x; } |
|
306 |
static long getElementJ(long[] a, int i) { return a[i]; } |
|
307 |
static void setElementJ(long[] a, int i, long x) { a[i] = x; } |
|
308 |
static float getElementF(float[] a, int i) { return a[i]; } |
|
309 |
static void setElementF(float[] a, int i, float x) { a[i] = x; } |
|
310 |
static double getElementD(double[] a, int i) { return a[i]; } |
|
311 |
static void setElementD(double[] a, int i, double x) { a[i] = x; } |
|
312 |
static boolean getElementZ(boolean[] a, int i) { return a[i]; } |
|
313 |
static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; } |
|
314 |
static byte getElementB(byte[] a, int i) { return a[i]; } |
|
315 |
static void setElementB(byte[] a, int i, byte x) { a[i] = x; } |
|
316 |
static short getElementS(short[] a, int i) { return a[i]; } |
|
317 |
static void setElementS(short[] a, int i, short x) { a[i] = x; } |
|
318 |
static char getElementC(char[] a, int i) { return a[i]; } |
|
319 |
static void setElementC(char[] a, int i, char x) { a[i] = x; } |
|
320 |
static Object getElementL(Object[] a, int i) { return a[i]; } |
|
321 |
static void setElementL(Object[] a, int i, Object x) { a[i] = x; } |
|
322 |
static <V> V getElementL(Class<V[]> aclass, V[] a, int i) { return aclass.cast(a)[i]; } |
|
323 |
static <V> void setElementL(Class<V[]> aclass, V[] a, int i, V x) { aclass.cast(a)[i] = x; } |
|
324 |
||
325 |
static String aname(Class<?> aclass, boolean isSetter) { |
|
326 |
Class<?> vclass = aclass.getComponentType(); |
|
327 |
if (vclass == null) throw new IllegalArgumentException(); |
|
328 |
return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(vclass); |
|
329 |
} |
|
330 |
static MethodType atype(Class<?> aclass, boolean isSetter) { |
|
331 |
Class<?> vclass = aclass.getComponentType(); |
|
332 |
if (!isSetter) |
|
333 |
return MethodType.methodType(vclass, aclass, int.class); |
|
334 |
else |
|
335 |
return MethodType.methodType(void.class, aclass, int.class, vclass); |
|
336 |
} |
|
337 |
static MethodHandle ahandle(Class<?> aclass, boolean isSetter) { |
|
338 |
Class<?> vclass = aclass.getComponentType(); |
|
339 |
String name = FieldAccessor.aname(aclass, isSetter); |
|
340 |
Class<?> caclass = null; |
|
341 |
if (!vclass.isPrimitive() && vclass != Object.class) { |
|
342 |
caclass = aclass; |
|
343 |
aclass = Object[].class; |
|
344 |
vclass = Object.class; |
|
345 |
} |
|
346 |
MethodType type = FieldAccessor.atype(aclass, isSetter); |
|
347 |
if (caclass != null) |
|
348 |
type = type.insertParameterTypes(0, Class.class); |
|
349 |
MethodHandle mh; |
|
350 |
try { |
|
351 |
mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type); |
|
8347
e5daa5772ffd
7013730: JSR 292 reflective operations should report errors with standard exception types
jrose
parents:
8346
diff
changeset
|
352 |
} catch (ReflectiveOperationException ex) { |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
5725
diff
changeset
|
353 |
throw uncaughtException(ex); |
4537 | 354 |
} |
355 |
if (caclass != null) { |
|
356 |
MethodType strongType = FieldAccessor.atype(caclass, isSetter); |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
357 |
mh = mh.bindTo(caclass); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
358 |
mh = convertArguments(mh, strongType, 0); |
4537 | 359 |
} |
360 |
return mh; |
|
361 |
} |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
362 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
363 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
364 |
/** 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
|
365 |
* Callable only from MethodHandles. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
366 |
* @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
|
367 |
* @param target Any direct method handle. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
368 |
* @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
|
369 |
* @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
|
370 |
*/ |
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
371 |
static |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
372 |
MethodHandle bindReceiver(MethodHandle target, Object receiver) { |
9752
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
373 |
if (receiver == null) return null; |
7554
8a0ad9757002
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
7052
diff
changeset
|
374 |
if (target instanceof AdapterMethodHandle && |
8a0ad9757002
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
7052
diff
changeset
|
375 |
((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY |
8a0ad9757002
6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
jrose
parents:
7052
diff
changeset
|
376 |
) { |
2764
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
377 |
Object info = MethodHandleNatives.getTargetInfo(target); |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
378 |
if (info instanceof DirectMethodHandle) { |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
379 |
DirectMethodHandle dmh = (DirectMethodHandle) info; |
9752
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
380 |
if (dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) { |
4537 | 381 |
MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0); |
382 |
MethodType newType = target.type().dropParameterTypes(0, 1); |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
383 |
return convertArguments(bmh, newType, bmh.type(), 0); |
4537 | 384 |
} |
2764
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
385 |
} |
2e45af54c0f9
6839839: access checking logic is wrong at three points in MethodHandles
jrose
parents:
2707
diff
changeset
|
386 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
387 |
if (target instanceof DirectMethodHandle) |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
388 |
return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
389 |
return null; // let caller try something else |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
390 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
391 |
|
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
392 |
/** 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
|
393 |
* Callable only from MethodHandles. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
394 |
* @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
|
395 |
* @param target Any method handle. |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
396 |
* @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
|
397 |
* @return a suitable BoundMethodHandle |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
398 |
*/ |
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
399 |
static |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
400 |
MethodHandle bindArgument(MethodHandle target, int argnum, Object receiver) { |
4537 | 401 |
return new BoundMethodHandle(target, receiver, argnum); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
402 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
403 |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
404 |
static MethodHandle permuteArguments(MethodHandle target, |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
405 |
MethodType newType, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
406 |
MethodType oldType, |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
407 |
int[] permutationOrNull) { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
408 |
assert(oldType.parameterCount() == target.type().parameterCount()); |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
409 |
int outargs = oldType.parameterCount(), inargs = newType.parameterCount(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
410 |
if (permutationOrNull.length != outargs) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
411 |
throw newIllegalArgumentException("wrong number of arguments in permutation"); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
412 |
// Make the individual outgoing argument types match up first. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
413 |
Class<?>[] callTypeArgs = new Class<?>[outargs]; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
414 |
for (int i = 0; i < outargs; i++) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
415 |
callTypeArgs[i] = newType.parameterType(permutationOrNull[i]); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
416 |
MethodType callType = MethodType.methodType(oldType.returnType(), callTypeArgs); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
417 |
target = convertArguments(target, callType, oldType, 0); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
418 |
assert(target != null); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
419 |
oldType = target.type(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
420 |
List<Integer> goal = new ArrayList<Integer>(); // i*TOKEN |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
421 |
List<Integer> state = new ArrayList<Integer>(); // i*TOKEN |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
422 |
List<Integer> drops = new ArrayList<Integer>(); // not tokens |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
423 |
List<Integer> dups = new ArrayList<Integer>(); // not tokens |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
424 |
final int TOKEN = 10; // to mark items which are symbolic only |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
425 |
// state represents the argument values coming into target |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
426 |
for (int i = 0; i < outargs; i++) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
427 |
state.add(permutationOrNull[i] * TOKEN); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
428 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
429 |
// goal represents the desired state |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
430 |
for (int i = 0; i < inargs; i++) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
431 |
if (state.contains(i * TOKEN)) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
432 |
goal.add(i * TOKEN); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
433 |
} else { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
434 |
// adapter must initially drop all unused arguments |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
435 |
drops.add(i); |
4537 | 436 |
} |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
437 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
438 |
// detect duplications |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
439 |
while (state.size() > goal.size()) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
440 |
for (int i2 = 0; i2 < state.size(); i2++) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
441 |
int arg1 = state.get(i2); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
442 |
int i1 = state.indexOf(arg1); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
443 |
if (i1 != i2) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
444 |
// found duplicate occurrence at i2 |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
445 |
int arg2 = (inargs++) * TOKEN; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
446 |
state.set(i2, arg2); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
447 |
dups.add(goal.indexOf(arg1)); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
448 |
goal.add(arg2); |
4537 | 449 |
} |
450 |
} |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
451 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
452 |
assert(state.size() == goal.size()); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
453 |
int size = goal.size(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
454 |
while (!state.equals(goal)) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
455 |
// Look for a maximal sequence of adjacent misplaced arguments, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
456 |
// and try to rotate them into place. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
457 |
int bestRotArg = -10 * TOKEN, bestRotLen = 0; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
458 |
int thisRotArg = -10 * TOKEN, thisRotLen = 0; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
459 |
for (int i = 0; i < size; i++) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
460 |
int arg = state.get(i); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
461 |
// Does this argument match the current run? |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
462 |
if (arg == thisRotArg + TOKEN) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
463 |
thisRotArg = arg; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
464 |
thisRotLen += 1; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
465 |
if (bestRotLen < thisRotLen) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
466 |
bestRotLen = thisRotLen; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
467 |
bestRotArg = thisRotArg; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
468 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
469 |
} else { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
470 |
// The old sequence (if any) stops here. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
471 |
thisRotLen = 0; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
472 |
thisRotArg = -10 * TOKEN; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
473 |
// But maybe a new one starts here also. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
474 |
int wantArg = goal.get(i); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
475 |
final int MAX_ARG_ROTATION = AdapterMethodHandle.MAX_ARG_ROTATION; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
476 |
if (arg != wantArg && |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
477 |
arg >= wantArg - TOKEN * MAX_ARG_ROTATION && |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
478 |
arg <= wantArg + TOKEN * MAX_ARG_ROTATION) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
479 |
thisRotArg = arg; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
480 |
thisRotLen = 1; |
4537 | 481 |
} |
482 |
} |
|
483 |
} |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
484 |
if (bestRotLen >= 2) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
485 |
// Do a rotation if it can improve argument positioning |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
486 |
// by at least 2 arguments. This is not always optimal, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
487 |
// but it seems to catch common cases. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
488 |
int dstEnd = state.indexOf(bestRotArg); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
489 |
int srcEnd = goal.indexOf(bestRotArg); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
490 |
int rotBy = dstEnd - srcEnd; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
491 |
int dstBeg = dstEnd - (bestRotLen - 1); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
492 |
int srcBeg = srcEnd - (bestRotLen - 1); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
493 |
assert((dstEnd | dstBeg | srcEnd | srcBeg) >= 0); // no negs |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
494 |
// Make a span which covers both source and destination. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
495 |
int rotBeg = Math.min(dstBeg, srcBeg); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
496 |
int rotEnd = Math.max(dstEnd, srcEnd); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
497 |
int score = 0; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
498 |
for (int i = rotBeg; i <= rotEnd; i++) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
499 |
if ((int)state.get(i) != (int)goal.get(i)) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
500 |
score += 1; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
501 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
502 |
List<Integer> rotSpan = state.subList(rotBeg, rotEnd+1); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
503 |
Collections.rotate(rotSpan, -rotBy); // reverse direction |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
504 |
for (int i = rotBeg; i <= rotEnd; i++) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
505 |
if ((int)state.get(i) != (int)goal.get(i)) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
506 |
score -= 1; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
507 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
508 |
if (score >= 2) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
509 |
// Improved at least two argument positions. Do it. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
510 |
List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray()); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
511 |
Collections.rotate(ptypes.subList(rotBeg, rotEnd+1), -rotBy); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
512 |
MethodType rotType = MethodType.methodType(oldType.returnType(), ptypes); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
513 |
MethodHandle nextTarget |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
514 |
= AdapterMethodHandle.makeRotateArguments(rotType, target, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
515 |
rotBeg, rotSpan.size(), rotBy); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
516 |
if (nextTarget != null) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
517 |
//System.out.println("Rot: "+rotSpan+" by "+rotBy); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
518 |
target = nextTarget; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
519 |
oldType = rotType; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
520 |
continue; |
4537 | 521 |
} |
522 |
} |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
523 |
// Else de-rotate, and drop through to the swap-fest. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
524 |
Collections.rotate(rotSpan, rotBy); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
525 |
} |
4537 | 526 |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
527 |
// Now swap like the wind! |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
528 |
List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray()); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
529 |
for (int i = 0; i < size; i++) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
530 |
// What argument do I want here? |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
531 |
int arg = goal.get(i); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
532 |
if (arg != state.get(i)) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
533 |
// Where is it now? |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
534 |
int j = state.indexOf(arg); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
535 |
Collections.swap(ptypes, i, j); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
536 |
MethodType swapType = MethodType.methodType(oldType.returnType(), ptypes); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
537 |
target = AdapterMethodHandle.makeSwapArguments(swapType, target, i, j); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
538 |
if (target == null) throw newIllegalArgumentException("cannot swap"); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
539 |
assert(target.type() == swapType); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
540 |
oldType = swapType; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
541 |
Collections.swap(state, i, j); |
4537 | 542 |
} |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
543 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
544 |
// One pass of swapping must finish the job. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
545 |
assert(state.equals(goal)); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
546 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
547 |
while (!dups.isEmpty()) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
548 |
// Grab a contiguous trailing sequence of dups. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
549 |
int grab = dups.size() - 1; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
550 |
int dupArgPos = dups.get(grab), dupArgCount = 1; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
551 |
while (grab - 1 >= 0) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
552 |
int dup0 = dups.get(grab - 1); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
553 |
if (dup0 != dupArgPos - 1) break; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
554 |
dupArgPos -= 1; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
555 |
dupArgCount += 1; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
556 |
grab -= 1; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
557 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
558 |
//if (dupArgCount > 1) System.out.println("Dup: "+dups.subList(grab, dups.size())); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
559 |
dups.subList(grab, dups.size()).clear(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
560 |
// In the new target type drop that many args from the tail: |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
561 |
List<Class<?>> ptypes = oldType.parameterList(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
562 |
ptypes = ptypes.subList(0, ptypes.size() - dupArgCount); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
563 |
MethodType dupType = MethodType.methodType(oldType.returnType(), ptypes); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
564 |
target = AdapterMethodHandle.makeDupArguments(dupType, target, dupArgPos, dupArgCount); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
565 |
if (target == null) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
566 |
throw newIllegalArgumentException("cannot dup"); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
567 |
oldType = target.type(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
568 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
569 |
while (!drops.isEmpty()) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
570 |
// Grab a contiguous initial sequence of drops. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
571 |
int dropArgPos = drops.get(0), dropArgCount = 1; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
572 |
while (dropArgCount < drops.size()) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
573 |
int drop1 = drops.get(dropArgCount); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
574 |
if (drop1 != dropArgPos + dropArgCount) break; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
575 |
dropArgCount += 1; |
4537 | 576 |
} |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
577 |
//if (dropArgCount > 1) System.out.println("Drop: "+drops.subList(0, dropArgCount)); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
578 |
drops.subList(0, dropArgCount).clear(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
579 |
List<Class<?>> dropTypes = newType.parameterList() |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
580 |
.subList(dropArgPos, dropArgPos + dropArgCount); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
581 |
MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
582 |
target = AdapterMethodHandle.makeDropArguments(dropType, target, dropArgPos, dropArgCount); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
583 |
if (target == null) throw newIllegalArgumentException("cannot drop"); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
584 |
oldType = target.type(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
585 |
} |
9752
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
586 |
target = convertArguments(target, newType, oldType, 0); |
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
587 |
assert(target != null); |
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
588 |
return target; |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
589 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
590 |
|
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
591 |
/*non-public*/ static |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
592 |
MethodHandle convertArguments(MethodHandle target, MethodType newType, int level) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
593 |
MethodType oldType = target.type(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
594 |
if (oldType.equals(newType)) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
595 |
return target; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
596 |
assert(level > 1 || oldType.isConvertibleTo(newType)); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
597 |
MethodHandle retFilter = null; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
598 |
Class<?> oldRT = oldType.returnType(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
599 |
Class<?> newRT = newType.returnType(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
600 |
if (!VerifyType.isNullConversion(oldRT, newRT)) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
601 |
if (oldRT == void.class) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
602 |
Wrapper wrap = newRT.isPrimitive() ? Wrapper.forPrimitiveType(newRT) : Wrapper.OBJECT; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
603 |
retFilter = ValueConversions.zeroConstantFunction(wrap); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
604 |
} else { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
605 |
retFilter = MethodHandles.identity(newRT); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
606 |
retFilter = convertArguments(retFilter, retFilter.type().changeParameterType(0, oldRT), level); |
4537 | 607 |
} |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
608 |
newType = newType.changeReturnType(oldRT); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
609 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
610 |
MethodHandle res = null; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
611 |
Exception ex = null; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
612 |
try { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
613 |
res = convertArguments(target, newType, oldType, level); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
614 |
} catch (IllegalArgumentException ex1) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
615 |
ex = ex1; |
4537 | 616 |
} |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
617 |
if (res == null) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
618 |
WrongMethodTypeException wmt = new WrongMethodTypeException("cannot convert to "+newType+": "+target); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
619 |
wmt.initCause(ex); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
620 |
throw wmt; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
621 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
622 |
if (retFilter != null) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
623 |
res = MethodHandles.filterReturnValue(res, retFilter); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
624 |
return res; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
625 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
626 |
|
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
627 |
static MethodHandle convertArguments(MethodHandle target, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
628 |
MethodType newType, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
629 |
MethodType oldType, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
630 |
int level) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
631 |
assert(oldType.parameterCount() == target.type().parameterCount()); |
4537 | 632 |
if (newType == oldType) |
633 |
return target; |
|
634 |
if (oldType.parameterCount() != newType.parameterCount()) |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
635 |
throw newIllegalArgumentException("mismatched parameter count", oldType, newType); |
10082 | 636 |
return AdapterMethodHandle.makePairwiseConvert(newType, target, level); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
637 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
638 |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
639 |
static MethodHandle spreadArguments(MethodHandle target, Class<?> arrayType, int arrayLength) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
640 |
MethodType oldType = target.type(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
641 |
int nargs = oldType.parameterCount(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
642 |
int keepPosArgs = nargs - arrayLength; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
643 |
MethodType newType = oldType |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
644 |
.dropParameterTypes(keepPosArgs, nargs) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
645 |
.insertParameterTypes(keepPosArgs, arrayType); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
646 |
return spreadArguments(target, newType, keepPosArgs, arrayType, arrayLength); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
647 |
} |
9859
47e26ad535c4
7052202: JSR 292: Crash in sun.invoke.util.ValueConversions.fillArray
jrose
parents:
9780
diff
changeset
|
648 |
// called internally only |
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
649 |
static MethodHandle spreadArgumentsFromPos(MethodHandle target, MethodType newType, int spreadArgPos) { |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
650 |
int arrayLength = target.type().parameterCount() - spreadArgPos; |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
651 |
return spreadArguments(target, newType, spreadArgPos, Object[].class, arrayLength); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
652 |
} |
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
653 |
static MethodHandle spreadArguments(MethodHandle target, |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
654 |
MethodType newType, |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
655 |
int spreadArgPos, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
656 |
Class<?> arrayType, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
657 |
int arrayLength) { |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
658 |
// 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
|
659 |
MethodType oldType = target.type(); |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
660 |
// spread the last argument of newType to oldType |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
661 |
assert(arrayLength == oldType.parameterCount() - spreadArgPos); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
662 |
assert(newType.parameterType(spreadArgPos) == arrayType); |
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
663 |
return AdapterMethodHandle.makeSpreadArguments(newType, target, arrayType, spreadArgPos, arrayLength); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
664 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
665 |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
666 |
static MethodHandle collectArguments(MethodHandle target, |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
667 |
int collectArg, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
668 |
MethodHandle collector) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
669 |
MethodType type = target.type(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
670 |
Class<?> collectType = collector.type().returnType(); |
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
671 |
assert(collectType != void.class); // else use foldArguments |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
672 |
if (collectType != type.parameterType(collectArg)) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
673 |
target = target.asType(type.changeParameterType(collectArg, collectType)); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
674 |
MethodType newType = type |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
675 |
.dropParameterTypes(collectArg, collectArg+1) |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
676 |
.insertParameterTypes(collectArg, collector.type().parameterArray()); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
677 |
return collectArguments(target, newType, collectArg, collector); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
678 |
} |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
679 |
static MethodHandle collectArguments(MethodHandle target, |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
680 |
MethodType newType, |
4537 | 681 |
int collectArg, |
682 |
MethodHandle collector) { |
|
683 |
MethodType oldType = target.type(); // (a...,c)=>r |
|
684 |
// newType // (a..., b...)=>r |
|
685 |
MethodType colType = collector.type(); // (b...)=>c |
|
686 |
// oldType // (a..., b...)=>r |
|
687 |
assert(newType.parameterCount() == collectArg + colType.parameterCount()); |
|
688 |
assert(oldType.parameterCount() == collectArg + 1); |
|
10082 | 689 |
assert(AdapterMethodHandle.canCollectArguments(oldType, colType, collectArg, false)); |
690 |
return AdapterMethodHandle.makeCollectArguments(target, collector, collectArg, false); |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
691 |
} |
4537 | 692 |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
693 |
static MethodHandle filterArgument(MethodHandle target, |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
694 |
int pos, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
695 |
MethodHandle filter) { |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
696 |
MethodType ttype = target.type(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
697 |
MethodType ftype = filter.type(); |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
698 |
assert(ftype.parameterCount() == 1); |
10082 | 699 |
return AdapterMethodHandle.makeCollectArguments(target, filter, pos, false); |
4537 | 700 |
} |
701 |
||
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
702 |
static MethodHandle foldArguments(MethodHandle target, |
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
703 |
MethodType newType, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
704 |
int foldPos, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
705 |
MethodHandle combiner) { |
4537 | 706 |
MethodType oldType = target.type(); |
707 |
MethodType ctype = combiner.type(); |
|
10082 | 708 |
assert(AdapterMethodHandle.canCollectArguments(oldType, ctype, foldPos, true)); |
709 |
return AdapterMethodHandle.makeCollectArguments(target, combiner, foldPos, true); |
|
4537 | 710 |
} |
711 |
||
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
712 |
static |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
713 |
MethodHandle dropArguments(MethodHandle target, |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
714 |
MethodType newType, int argnum) { |
4537 | 715 |
int drops = newType.parameterCount() - target.type().parameterCount(); |
10082 | 716 |
return AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops); |
4537 | 717 |
} |
718 |
||
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
719 |
static |
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
720 |
MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) { |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
721 |
return testResult ? target : fallback; |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
722 |
} |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
723 |
|
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
724 |
static MethodHandle SELECT_ALTERNATIVE; |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
725 |
static MethodHandle selectAlternative() { |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
726 |
if (SELECT_ALTERNATIVE != null) return SELECT_ALTERNATIVE; |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
727 |
try { |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
728 |
SELECT_ALTERNATIVE |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
729 |
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative", |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
730 |
MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class)); |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
731 |
} catch (ReflectiveOperationException ex) { |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
732 |
throw new RuntimeException(ex); |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
733 |
} |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
734 |
return SELECT_ALTERNATIVE; |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
735 |
} |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
736 |
|
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
737 |
static |
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
738 |
MethodHandle makeGuardWithTest(MethodHandle test, |
4537 | 739 |
MethodHandle target, |
740 |
MethodHandle fallback) { |
|
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
741 |
// gwt(arg...) |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
742 |
// [fold]=> continueAfterTest(z=test(arg...), arg...) |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
743 |
// [filter]=> (tf=select(z))(arg...) |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
744 |
// where select(z) = select(z, t, f).bindTo(t, f) => z ? t f |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
745 |
// [tailcall]=> tf(arg...) |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
746 |
assert(test.type().returnType() == boolean.class); |
9752
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
747 |
MethodType targetType = target.type(); |
88ab34b6da6d
7032323: code changes for JSR 292 EG adjustments to API, through Public Review
jrose
parents:
9731
diff
changeset
|
748 |
MethodType foldTargetType = targetType.insertParameterTypes(0, boolean.class); |
10082 | 749 |
assert(AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true)); |
750 |
// working backwards, as usual: |
|
751 |
assert(target.type().equals(fallback.type())); |
|
752 |
MethodHandle tailcall = MethodHandles.exactInvoker(target.type()); |
|
753 |
MethodHandle select = selectAlternative(); |
|
10615 | 754 |
select = bindArgument(select, 2, CountingMethodHandle.wrap(fallback)); |
755 |
select = bindArgument(select, 1, CountingMethodHandle.wrap(target)); |
|
10082 | 756 |
// select(z: boolean) => (z ? target : fallback) |
757 |
MethodHandle filter = filterArgument(tailcall, 0, select); |
|
758 |
assert(filter.type().parameterType(0) == boolean.class); |
|
759 |
MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test); |
|
760 |
return fold; |
|
4537 | 761 |
} |
762 |
||
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
763 |
private static class GuardWithCatch extends BoundMethodHandle { |
4537 | 764 |
private final MethodHandle target; |
765 |
private final Class<? extends Throwable> exType; |
|
766 |
private final MethodHandle catcher; |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
767 |
GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) { |
4537 | 768 |
this(INVOKES[target.type().parameterCount()], target, exType, catcher); |
769 |
} |
|
9646
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
770 |
// FIXME: Build the control flow out of foldArguments. |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
771 |
GuardWithCatch(MethodHandle invoker, |
5ebbe5ab084f
6939861: JVM should handle more conversion operations
jrose
parents:
8822
diff
changeset
|
772 |
MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) { |
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
773 |
super(invoker); |
4537 | 774 |
this.target = target; |
775 |
this.exType = exType; |
|
776 |
this.catcher = catcher; |
|
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
777 |
} |
4537 | 778 |
@Override |
9731
d0f7a3e441c4
7044892: JSR 292: API entry points sometimes throw the wrong exceptions or doesn't throw the expected one
jrose
parents:
9730
diff
changeset
|
779 |
String debugString() { |
7555
a279ebc3b25c
6981777: implement JSR 292 EG adjustments from summer 2010
jrose
parents:
7554
diff
changeset
|
780 |
return addTypeString(target, this); |
4537 | 781 |
} |
782 |
private Object invoke_V(Object... av) throws Throwable { |
|
783 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
784 |
return target.invokeExact(av); |
4537 | 785 |
} catch (Throwable t) { |
786 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
787 |
return catcher.invokeExact(t, av); |
4537 | 788 |
} |
789 |
} |
|
790 |
private Object invoke_L0() throws Throwable { |
|
791 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
792 |
return target.invokeExact(); |
4537 | 793 |
} catch (Throwable t) { |
794 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
795 |
return catcher.invokeExact(t); |
4537 | 796 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
797 |
} |
4537 | 798 |
private Object invoke_L1(Object a0) throws Throwable { |
799 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
800 |
return target.invokeExact(a0); |
4537 | 801 |
} catch (Throwable t) { |
802 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
803 |
return catcher.invokeExact(t, a0); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
804 |
} |
4537 | 805 |
} |
806 |
private Object invoke_L2(Object a0, Object a1) throws Throwable { |
|
807 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
808 |
return target.invokeExact(a0, a1); |
4537 | 809 |
} catch (Throwable t) { |
810 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
811 |
return catcher.invokeExact(t, a0, a1); |
4537 | 812 |
} |
813 |
} |
|
814 |
private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { |
|
815 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
816 |
return target.invokeExact(a0, a1, a2); |
4537 | 817 |
} catch (Throwable t) { |
818 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
819 |
return catcher.invokeExact(t, a0, a1, a2); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
820 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
821 |
} |
4537 | 822 |
private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { |
823 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
824 |
return target.invokeExact(a0, a1, a2, a3); |
4537 | 825 |
} catch (Throwable t) { |
826 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
827 |
return catcher.invokeExact(t, a0, a1, a2, a3); |
4537 | 828 |
} |
829 |
} |
|
830 |
private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { |
|
831 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
832 |
return target.invokeExact(a0, a1, a2, a3, a4); |
4537 | 833 |
} catch (Throwable t) { |
834 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
835 |
return catcher.invokeExact(t, a0, a1, a2, a3, a4); |
4537 | 836 |
} |
837 |
} |
|
838 |
private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { |
|
839 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
840 |
return target.invokeExact(a0, a1, a2, a3, a4, a5); |
4537 | 841 |
} catch (Throwable t) { |
842 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
843 |
return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5); |
4537 | 844 |
} |
845 |
} |
|
846 |
private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { |
|
847 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
848 |
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); |
4537 | 849 |
} catch (Throwable t) { |
850 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
851 |
return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6); |
4537 | 852 |
} |
853 |
} |
|
854 |
private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { |
|
855 |
try { |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
856 |
return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); |
4537 | 857 |
} catch (Throwable t) { |
858 |
if (!exType.isInstance(t)) throw t; |
|
7556
4a5711d43948
6979327: method handle invocation should use casts instead of type parameters to specify return type
jrose
parents:
7555
diff
changeset
|
859 |
return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7); |
4537 | 860 |
} |
861 |
} |
|
862 |
static MethodHandle[] makeInvokes() { |
|
863 |
ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>(); |
|
864 |
MethodHandles.Lookup lookup = IMPL_LOOKUP; |
|
865 |
for (;;) { |
|
866 |
int nargs = invokes.size(); |
|
867 |
String name = "invoke_L"+nargs; |
|
868 |
MethodHandle invoke = null; |
|
869 |
try { |
|
870 |
invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs)); |
|
8347
e5daa5772ffd
7013730: JSR 292 reflective operations should report errors with standard exception types
jrose
parents:
8346
diff
changeset
|
871 |
} catch (ReflectiveOperationException ex) { |
4537 | 872 |
} |
873 |
if (invoke == null) break; |
|
874 |
invokes.add(invoke); |
|
875 |
} |
|
876 |
assert(invokes.size() == 9); // current number of methods |
|
877 |
return invokes.toArray(new MethodHandle[0]); |
|
878 |
}; |
|
879 |
static final MethodHandle[] INVOKES = makeInvokes(); |
|
880 |
// For testing use this: |
|
881 |
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2); |
|
882 |
static final MethodHandle VARARGS_INVOKE; |
|
883 |
static { |
|
884 |
try { |
|
885 |
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true)); |
|
8347
e5daa5772ffd
7013730: JSR 292 reflective operations should report errors with standard exception types
jrose
parents:
8346
diff
changeset
|
886 |
} catch (ReflectiveOperationException ex) { |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
5725
diff
changeset
|
887 |
throw uncaughtException(ex); |
4537 | 888 |
} |
889 |
} |
|
890 |
} |
|
891 |
||
892 |
||
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
893 |
static |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
894 |
MethodHandle makeGuardWithCatch(MethodHandle target, |
4537 | 895 |
Class<? extends Throwable> exType, |
896 |
MethodHandle catcher) { |
|
897 |
MethodType type = target.type(); |
|
898 |
MethodType ctype = catcher.type(); |
|
899 |
int nargs = type.parameterCount(); |
|
900 |
if (nargs < GuardWithCatch.INVOKES.length) { |
|
901 |
MethodType gtype = type.generic(); |
|
902 |
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); |
|
9859
47e26ad535c4
7052202: JSR 292: Crash in sun.invoke.util.ValueConversions.fillArray
jrose
parents:
9780
diff
changeset
|
903 |
// Note: convertArguments(...2) avoids interface casts present in convertArguments(...0) |
47e26ad535c4
7052202: JSR 292: Crash in sun.invoke.util.ValueConversions.fillArray
jrose
parents:
9780
diff
changeset
|
904 |
MethodHandle gtarget = convertArguments(target, gtype, type, 2); |
47e26ad535c4
7052202: JSR 292: Crash in sun.invoke.util.ValueConversions.fillArray
jrose
parents:
9780
diff
changeset
|
905 |
MethodHandle gcatcher = convertArguments(catcher, gcatchType, ctype, 2); |
4537 | 906 |
MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher); |
907 |
if (gtarget == null || gcatcher == null || gguard == null) return null; |
|
9859
47e26ad535c4
7052202: JSR 292: Crash in sun.invoke.util.ValueConversions.fillArray
jrose
parents:
9780
diff
changeset
|
908 |
return convertArguments(gguard, type, gtype, 2); |
4537 | 909 |
} else { |
910 |
MethodType gtype = MethodType.genericMethodType(0, true); |
|
911 |
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); |
|
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
912 |
MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0); |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
913 |
catcher = catcher.asType(ctype.changeParameterType(0, Throwable.class)); |
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
914 |
MethodHandle gcatcher = spreadArgumentsFromPos(catcher, gcatchType, 1); |
4537 | 915 |
MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher); |
916 |
if (gtarget == null || gcatcher == null || gguard == null) return null; |
|
9730
e4b334d47f4b
7032850: MethodHandle.invokeGeneric throws unspecified RuntimeException if parameterized method is called
jrose
parents:
9646
diff
changeset
|
917 |
return collectArguments(gguard, type, 0, ValueConversions.varargsArray(nargs)).asType(type); |
4537 | 918 |
} |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
919 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
920 |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
921 |
static |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
922 |
MethodHandle throwException(MethodType type) { |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
923 |
return AdapterMethodHandle.makeRetypeRaw(type, throwException()); |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
924 |
} |
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
925 |
|
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
926 |
static MethodHandle THROW_EXCEPTION; |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
927 |
static MethodHandle throwException() { |
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
928 |
if (THROW_EXCEPTION != null) return THROW_EXCEPTION; |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
5725
diff
changeset
|
929 |
try { |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
5725
diff
changeset
|
930 |
THROW_EXCEPTION |
4537 | 931 |
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException", |
932 |
MethodType.methodType(Empty.class, Throwable.class)); |
|
8347
e5daa5772ffd
7013730: JSR 292 reflective operations should report errors with standard exception types
jrose
parents:
8346
diff
changeset
|
933 |
} catch (ReflectiveOperationException ex) { |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
5725
diff
changeset
|
934 |
throw new RuntimeException(ex); |
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
5725
diff
changeset
|
935 |
} |
8821
2836ee97ee27
6839872: remove implementation inheritance from JSR 292 APIs
jrose
parents:
8347
diff
changeset
|
936 |
return THROW_EXCEPTION; |
7052
963a5baf2ba3
6980096: JSR 292 reflective lookup should throw checked exceptions
jrose
parents:
5725
diff
changeset
|
937 |
} |
4537 | 938 |
static <T extends Throwable> Empty throwException(T t) throws T { throw t; } |
2707
5a17df307cbc
6829144: JSR 292 JVM features need a provisional Java API
jrose
parents:
diff
changeset
|
939 |
} |