author | jrose |
Fri, 30 Apr 2010 23:48:23 -0700 | |
changeset 5722 | 4ada807383c8 |
parent 4537 | 7c3c7f8d5195 |
child 5723 | a58a0eed34b0 |
permissions | -rw-r--r-- |
4535 | 1 |
/* |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
2 |
* Copyright 2009-2010 Sun Microsystems, Inc. All Rights Reserved. |
4535 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Sun designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Sun in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 |
* have any questions. |
|
24 |
*/ |
|
25 |
||
26 |
/* @test |
|
27 |
* @summary unit tests for java.dyn.MethodHandles |
|
28 |
* @compile -XDinvokedynamic MethodHandlesTest.java |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
29 |
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic test.java.dyn.MethodHandlesTest |
4535 | 30 |
*/ |
31 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
32 |
package test.java.dyn; |
4535 | 33 |
|
34 |
import java.dyn.*; |
|
35 |
import java.dyn.MethodHandles.Lookup; |
|
36 |
import java.lang.reflect.*; |
|
37 |
import java.util.*; |
|
38 |
import org.junit.*; |
|
39 |
import static org.junit.Assert.*; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
40 |
import static org.junit.Assume.*; |
4535 | 41 |
|
42 |
||
43 |
/** |
|
44 |
* |
|
45 |
* @author jrose |
|
46 |
*/ |
|
47 |
public class MethodHandlesTest { |
|
48 |
// How much output? |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
49 |
static int verbosity = 0; |
4535 | 50 |
|
51 |
// Set this true during development if you want to fast-forward to |
|
52 |
// a particular new, non-working test. Tests which are known to |
|
53 |
// work (or have recently worked) test this flag and return on true. |
|
54 |
static boolean CAN_SKIP_WORKING = false; |
|
55 |
//static { CAN_SKIP_WORKING = true; } |
|
56 |
||
57 |
// Set true to test more calls. If false, some tests are just |
|
58 |
// lookups, without exercising the actual method handle. |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
59 |
static boolean DO_MORE_CALLS = true; |
4535 | 60 |
|
61 |
||
62 |
@Test |
|
63 |
public void testFirst() throws Throwable { |
|
64 |
verbosity += 9; try { |
|
65 |
// left blank for debugging |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
66 |
} finally { printCounts(); verbosity -= 9; } |
4535 | 67 |
} |
68 |
||
4537 | 69 |
// current failures |
70 |
@Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric") |
|
71 |
public void testFail_1() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
72 |
// AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters |
4537 | 73 |
testSpreadArguments(int.class, 0, 6); |
74 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
75 |
@Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args") |
4537 | 76 |
public void testFail_2() throws Throwable { |
77 |
// if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes: |
|
78 |
testSpreadArguments(Object.class, 0, 2); |
|
79 |
} |
|
80 |
@Test @Ignore("IllArgEx failure in call to ToGeneric.make") |
|
81 |
public void testFail_3() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
82 |
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object |
4537 | 83 |
testSpreadArguments(int.class, 1, 2); |
84 |
} |
|
85 |
@Test @Ignore("IllArgEx failure in call to ToGeneric.make") |
|
86 |
public void testFail_4() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
87 |
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object |
4537 | 88 |
testCollectArguments(int.class, 1, 2); |
89 |
} |
|
90 |
@Test @Ignore("cannot collect leading primitive types") |
|
91 |
public void testFail_5() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
92 |
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object |
4537 | 93 |
testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class)); |
94 |
} |
|
95 |
@Test @Ignore("should not insert arguments beyond MethodHandlePushLimit") |
|
96 |
public void testFail_6() throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
97 |
// ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13 |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
98 |
testInsertArguments(0, 0, MAX_ARG_INCREASE+10); |
4537 | 99 |
} |
4535 | 100 |
static final int MAX_ARG_INCREASE = 3; |
101 |
||
102 |
public MethodHandlesTest() { |
|
103 |
} |
|
104 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
105 |
@Before |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
106 |
public void checkImplementedPlatform() { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
107 |
boolean platformOK = false; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
108 |
Properties properties = System.getProperties(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
109 |
String vers = properties.getProperty("java.vm.version"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
110 |
String name = properties.getProperty("java.vm.name"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
111 |
String arch = properties.getProperty("os.arch"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
112 |
if ((arch.equals("i386") || arch.equals("amd64") || |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
113 |
arch.equals("sparc") || arch.equals("sparcv9")) && |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
114 |
(name.contains("Client") || name.contains("Server")) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
115 |
) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
116 |
platformOK = true; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
117 |
} else { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
118 |
System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
119 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
120 |
assumeTrue(platformOK); |
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 |
|
4535 | 123 |
String testName; |
124 |
int posTests, negTests; |
|
125 |
@After |
|
126 |
public void printCounts() { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
127 |
if (verbosity >= 2 && (posTests | negTests) != 0) { |
4535 | 128 |
System.out.println(); |
129 |
if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run"); |
|
130 |
if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
131 |
posTests = negTests = 0; |
4535 | 132 |
} |
133 |
} |
|
134 |
void countTest(boolean positive) { |
|
135 |
if (positive) ++posTests; |
|
136 |
else ++negTests; |
|
137 |
} |
|
138 |
void countTest() { countTest(true); } |
|
139 |
void startTest(String name) { |
|
140 |
if (testName != null) printCounts(); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
141 |
if (verbosity >= 1) |
4535 | 142 |
System.out.println(name); |
143 |
posTests = negTests = 0; |
|
144 |
testName = name; |
|
145 |
} |
|
146 |
||
147 |
@BeforeClass |
|
148 |
public static void setUpClass() throws Exception { |
|
149 |
calledLog.clear(); |
|
150 |
calledLog.add(null); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
151 |
nextArgVal = INITIAL_ARG_VAL; |
4535 | 152 |
} |
153 |
||
154 |
@AfterClass |
|
155 |
public static void tearDownClass() throws Exception { |
|
156 |
} |
|
157 |
||
158 |
static List<Object> calledLog = new ArrayList<Object>(); |
|
159 |
static Object logEntry(String name, Object... args) { |
|
160 |
return Arrays.asList(name, Arrays.asList(args)); |
|
161 |
} |
|
162 |
static Object called(String name, Object... args) { |
|
163 |
Object entry = logEntry(name, args); |
|
164 |
calledLog.add(entry); |
|
165 |
return entry; |
|
166 |
} |
|
167 |
static void assertCalled(String name, Object... args) { |
|
168 |
Object expected = logEntry(name, args); |
|
169 |
Object actual = calledLog.get(calledLog.size() - 1); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
170 |
if (expected.equals(actual) && verbosity < 9) return; |
4535 | 171 |
System.out.println("assertCalled "+name+":"); |
172 |
System.out.println("expected: "+expected); |
|
173 |
System.out.println("actual: "+actual); |
|
174 |
System.out.println("ex. types: "+getClasses(expected)); |
|
175 |
System.out.println("act. types: "+getClasses(actual)); |
|
176 |
assertEquals("previous method call", expected, actual); |
|
177 |
} |
|
178 |
static void printCalled(MethodHandle target, String name, Object... args) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
179 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
180 |
System.out.println("calling MH="+target+" to "+name+Arrays.toString(args)); |
4535 | 181 |
} |
182 |
||
183 |
static Object castToWrapper(Object value, Class<?> dst) { |
|
184 |
Object wrap = null; |
|
185 |
if (value instanceof Number) |
|
186 |
wrap = castToWrapperOrNull(((Number)value).longValue(), dst); |
|
187 |
if (value instanceof Character) |
|
188 |
wrap = castToWrapperOrNull((char)(Character)value, dst); |
|
189 |
if (wrap != null) return wrap; |
|
190 |
return dst.cast(value); |
|
191 |
} |
|
192 |
||
193 |
static Object castToWrapperOrNull(long value, Class<?> dst) { |
|
194 |
if (dst == int.class || dst == Integer.class) |
|
195 |
return (int)(value); |
|
196 |
if (dst == long.class || dst == Long.class) |
|
197 |
return (long)(value); |
|
198 |
if (dst == char.class || dst == Character.class) |
|
199 |
return (char)(value); |
|
200 |
if (dst == short.class || dst == Short.class) |
|
201 |
return (short)(value); |
|
202 |
if (dst == float.class || dst == Float.class) |
|
203 |
return (float)(value); |
|
204 |
if (dst == double.class || dst == Double.class) |
|
205 |
return (double)(value); |
|
4537 | 206 |
if (dst == byte.class || dst == Byte.class) |
207 |
return (byte)(value); |
|
208 |
if (dst == boolean.class || dst == boolean.class) |
|
209 |
return ((value % 29) & 1) == 0; |
|
4535 | 210 |
return null; |
211 |
} |
|
212 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
213 |
static final int ONE_MILLION = (1000*1000), // first int value |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
214 |
TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
215 |
INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
216 |
static long nextArgVal; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
217 |
static long nextArg(boolean moreBits) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
218 |
long val = nextArgVal++; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
219 |
long sign = -(val & 1); // alternate signs |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
220 |
val >>= 1; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
221 |
if (moreBits) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
222 |
// Guarantee some bits in the high word. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
223 |
// In any case keep the decimal representation simple-looking, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
224 |
// with lots of zeroes, so as not to make the printed decimal |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
225 |
// strings unnecessarily noisy. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
226 |
val += (val % ONE_MILLION) * TEN_BILLION; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
227 |
return val ^ sign; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
228 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
229 |
static int nextArg() { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
230 |
// Produce a 32-bit result something like ONE_MILLION+(smallint). |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
231 |
// Example: 1_000_042. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
232 |
return (int) nextArg(false); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
233 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
234 |
static long nextArg(Class<?> kind) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
235 |
if (kind == long.class || kind == Long.class || |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
236 |
kind == double.class || kind == Double.class) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
237 |
// produce a 64-bit result something like |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
238 |
// ((TEN_BILLION+1) * (ONE_MILLION+(smallint))) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
239 |
// Example: 10_000_420_001_000_042. |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
240 |
return nextArg(true); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
241 |
return (long) nextArg(); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
242 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
243 |
|
4535 | 244 |
static Object randomArg(Class<?> param) { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
245 |
Object wrap = castToWrapperOrNull(nextArg(param), param); |
4535 | 246 |
if (wrap != null) { |
247 |
return wrap; |
|
248 |
} |
|
249 |
// import sun.dyn.util.Wrapper; |
|
250 |
// Wrapper wrap = Wrapper.forBasicType(dst); |
|
251 |
// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst)) |
|
252 |
// wrap = Wrapper.forWrapperType(dst); |
|
253 |
// if (wrap != Wrapper.OBJECT) |
|
254 |
// return wrap.wrap(nextArg++); |
|
255 |
if (param.isInterface() || param.isAssignableFrom(String.class)) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
256 |
return "#"+nextArg(); |
4535 | 257 |
else |
258 |
try { |
|
259 |
return param.newInstance(); |
|
260 |
} catch (InstantiationException ex) { |
|
261 |
} catch (IllegalAccessException ex) { |
|
262 |
} |
|
263 |
return null; // random class not Object, String, Integer, etc. |
|
264 |
} |
|
265 |
static Object[] randomArgs(Class<?>... params) { |
|
266 |
Object[] args = new Object[params.length]; |
|
267 |
for (int i = 0; i < args.length; i++) |
|
268 |
args[i] = randomArg(params[i]); |
|
269 |
return args; |
|
270 |
} |
|
271 |
static Object[] randomArgs(int nargs, Class<?> param) { |
|
272 |
Object[] args = new Object[nargs]; |
|
273 |
for (int i = 0; i < args.length; i++) |
|
274 |
args[i] = randomArg(param); |
|
275 |
return args; |
|
276 |
} |
|
277 |
||
278 |
static <T, E extends T> T[] array(Class<T[]> atype, E... a) { |
|
279 |
return Arrays.copyOf(a, a.length, atype); |
|
280 |
} |
|
281 |
static <T> T[] cat(T[] a, T... b) { |
|
282 |
int alen = a.length, blen = b.length; |
|
283 |
if (blen == 0) return a; |
|
284 |
T[] c = Arrays.copyOf(a, alen + blen); |
|
285 |
System.arraycopy(b, 0, c, alen, blen); |
|
286 |
return c; |
|
287 |
} |
|
288 |
static Integer[] boxAll(int... vx) { |
|
289 |
Integer[] res = new Integer[vx.length]; |
|
290 |
for (int i = 0; i < res.length; i++) { |
|
291 |
res[i] = vx[i]; |
|
292 |
} |
|
293 |
return res; |
|
294 |
} |
|
295 |
static Object getClasses(Object x) { |
|
296 |
if (x == null) return x; |
|
297 |
if (x instanceof String) return x; // keep the name |
|
298 |
if (x instanceof List) { |
|
299 |
// recursively report classes of the list elements |
|
300 |
Object[] xa = ((List)x).toArray(); |
|
301 |
for (int i = 0; i < xa.length; i++) |
|
302 |
xa[i] = getClasses(xa[i]); |
|
303 |
return Arrays.asList(xa); |
|
304 |
} |
|
305 |
return x.getClass().getSimpleName(); |
|
306 |
} |
|
307 |
||
308 |
static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) { |
|
309 |
return changeArgTypes(target, 0, 999, argType); |
|
310 |
} |
|
311 |
static MethodHandle changeArgTypes(MethodHandle target, |
|
312 |
int beg, int end, Class<?> argType) { |
|
313 |
MethodType targetType = target.type(); |
|
314 |
end = Math.min(end, targetType.parameterCount()); |
|
315 |
ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList()); |
|
316 |
Collections.fill(argTypes.subList(beg, end), argType); |
|
4537 | 317 |
MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); |
4535 | 318 |
return MethodHandles.convertArguments(target, ttype2); |
319 |
} |
|
320 |
||
321 |
// This lookup is good for all members in and under MethodHandlesTest. |
|
322 |
static final Lookup PRIVATE = MethodHandles.lookup(); |
|
323 |
// This lookup is good for package-private members but not private ones. |
|
324 |
static final Lookup PACKAGE = PackageSibling.lookup(); |
|
325 |
// This lookup is good only for public members. |
|
4537 | 326 |
static final Lookup PUBLIC = MethodHandles.publicLookup(); |
4535 | 327 |
|
328 |
// Subject methods... |
|
329 |
static class Example implements IntExample { |
|
330 |
final String name; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
331 |
public Example() { name = "Example#"+nextArg(); } |
4535 | 332 |
protected Example(String name) { this.name = name; } |
333 |
protected Example(int x) { this(); called("protected <init>", this, x); } |
|
334 |
@Override public String toString() { return name; } |
|
335 |
||
336 |
public void v0() { called("v0", this); } |
|
337 |
void pkg_v0() { called("pkg_v0", this); } |
|
338 |
private void pri_v0() { called("pri_v0", this); } |
|
339 |
public static void s0() { called("s0"); } |
|
340 |
static void pkg_s0() { called("pkg_s0"); } |
|
341 |
private static void pri_s0() { called("pri_s0"); } |
|
342 |
||
343 |
public Object v1(Object x) { return called("v1", this, x); } |
|
344 |
public Object v2(Object x, Object y) { return called("v2", this, x, y); } |
|
345 |
public Object v2(Object x, int y) { return called("v2", this, x, y); } |
|
346 |
public Object v2(int x, Object y) { return called("v2", this, x, y); } |
|
347 |
public Object v2(int x, int y) { return called("v2", this, x, y); } |
|
348 |
public static Object s1(Object x) { return called("s1", x); } |
|
349 |
public static Object s2(int x) { return called("s2", x); } |
|
350 |
public static Object s3(long x) { return called("s3", x); } |
|
351 |
public static Object s4(int x, int y) { return called("s4", x, y); } |
|
352 |
public static Object s5(long x, int y) { return called("s5", x, y); } |
|
353 |
public static Object s6(int x, long y) { return called("s6", x, y); } |
|
354 |
public static Object s7(float x, double y) { return called("s7", x, y); } |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
355 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
356 |
static final Lookup EXAMPLE = MethodHandles.lookup(); // for testing findSpecial |
4535 | 357 |
} |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
358 |
static final Lookup EXAMPLE = Example.EXAMPLE; |
4535 | 359 |
public static class PubExample extends Example { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
360 |
public PubExample() { super("PubExample#"+nextArg()); } |
4535 | 361 |
} |
362 |
static class SubExample extends Example { |
|
363 |
@Override public void v0() { called("Sub/v0", this); } |
|
364 |
@Override void pkg_v0() { called("Sub/pkg_v0", this); } |
|
365 |
private SubExample(int x) { called("<init>", this, x); } |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
366 |
public SubExample() { super("SubExample#"+nextArg()); } |
4535 | 367 |
} |
368 |
public static interface IntExample { |
|
369 |
public void v0(); |
|
370 |
static class Impl implements IntExample { |
|
371 |
public void v0() { called("Int/v0", this); } |
|
372 |
final String name; |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
373 |
public Impl() { name = "Impl#"+nextArg(); } |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
374 |
@Override public String toString() { return name; } |
4535 | 375 |
} |
376 |
} |
|
377 |
||
378 |
static final Object[][][] ACCESS_CASES = { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
379 |
{ { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
380 |
{ { false, PUBLIC }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
381 |
{ { false, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[2]: PUBLIC false |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
382 |
{ { true, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[3]: all true |
4535 | 383 |
}; |
384 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
385 |
static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
386 |
Object[][] cases; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
387 |
if (name.contains("pri_") || isSpecial) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
388 |
cases = ACCESS_CASES[1]; // PRIVATE only |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
389 |
} else if (name.contains("pkg_") || !Modifier.isPublic(defc.getModifiers())) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
390 |
cases = ACCESS_CASES[2]; // not PUBLIC |
4537 | 391 |
} else { |
392 |
assertTrue(name.indexOf('_') < 0); |
|
393 |
boolean pubc = Modifier.isPublic(defc.getModifiers()); |
|
394 |
if (pubc) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
395 |
cases = ACCESS_CASES[3]; // all access levels |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
396 |
else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
397 |
cases = ACCESS_CASES[2]; // PACKAGE but not PUBLIC |
4537 | 398 |
} |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
399 |
if (defc != Example.class && cases[cases.length-1][1] == EXAMPLE) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
400 |
cases = Arrays.copyOfRange(cases, 0, cases.length-1); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
401 |
return cases; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
402 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
403 |
static Object[][] accessCases(Class<?> defc, String name) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
404 |
return accessCases(defc, name, false); |
4535 | 405 |
} |
406 |
||
407 |
@Test |
|
408 |
public void testFindStatic() throws Throwable { |
|
409 |
if (CAN_SKIP_WORKING) return; |
|
410 |
startTest("findStatic"); |
|
411 |
testFindStatic(PubExample.class, void.class, "s0"); |
|
412 |
testFindStatic(Example.class, void.class, "s0"); |
|
413 |
testFindStatic(Example.class, void.class, "pkg_s0"); |
|
414 |
testFindStatic(Example.class, void.class, "pri_s0"); |
|
415 |
||
416 |
testFindStatic(Example.class, Object.class, "s1", Object.class); |
|
417 |
testFindStatic(Example.class, Object.class, "s2", int.class); |
|
418 |
testFindStatic(Example.class, Object.class, "s3", long.class); |
|
419 |
testFindStatic(Example.class, Object.class, "s4", int.class, int.class); |
|
420 |
testFindStatic(Example.class, Object.class, "s5", long.class, int.class); |
|
421 |
testFindStatic(Example.class, Object.class, "s6", int.class, long.class); |
|
422 |
testFindStatic(Example.class, Object.class, "s7", float.class, double.class); |
|
423 |
||
424 |
testFindStatic(false, PRIVATE, Example.class, void.class, "bogus"); |
|
425 |
} |
|
426 |
||
427 |
void testFindStatic(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
428 |
for (Object[] ac : accessCases(defc, name)) { |
|
429 |
testFindStatic((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); |
|
430 |
} |
|
431 |
} |
|
432 |
void testFindStatic(Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
433 |
testFindStatic(true, lookup, defc, ret, name, params); |
|
434 |
} |
|
435 |
void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
436 |
countTest(positive); |
|
4537 | 437 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 438 |
MethodHandle target = null; |
439 |
RuntimeException noAccess = null; |
|
440 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
441 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4535 | 442 |
target = lookup.findStatic(defc, name, type); |
443 |
} catch (NoAccessException ex) { |
|
444 |
noAccess = ex; |
|
445 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
446 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
447 |
System.out.println("findStatic "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target |
4535 | 448 |
+(noAccess == null ? "" : " !! "+noAccess)); |
449 |
if (positive && noAccess != null) throw noAccess; |
|
450 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
451 |
if (!positive) return; // negative test failed as expected |
|
452 |
assertEquals(type, target.type()); |
|
453 |
assertTrue(target.toString().contains(name)); // rough check |
|
454 |
if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
|
455 |
Object[] args = randomArgs(params); |
|
456 |
printCalled(target, name, args); |
|
4537 | 457 |
target.invokeVarargs(args); |
4535 | 458 |
assertCalled(name, args); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
459 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
460 |
System.out.print(':'); |
4535 | 461 |
} |
462 |
||
463 |
@Test |
|
464 |
public void testFindVirtual() throws Throwable { |
|
465 |
if (CAN_SKIP_WORKING) return; |
|
466 |
startTest("findVirtual"); |
|
467 |
testFindVirtual(Example.class, void.class, "v0"); |
|
468 |
testFindVirtual(Example.class, void.class, "pkg_v0"); |
|
469 |
testFindVirtual(Example.class, void.class, "pri_v0"); |
|
470 |
testFindVirtual(Example.class, Object.class, "v1", Object.class); |
|
471 |
testFindVirtual(Example.class, Object.class, "v2", Object.class, Object.class); |
|
472 |
testFindVirtual(Example.class, Object.class, "v2", Object.class, int.class); |
|
473 |
testFindVirtual(Example.class, Object.class, "v2", int.class, Object.class); |
|
474 |
testFindVirtual(Example.class, Object.class, "v2", int.class, int.class); |
|
475 |
testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "bogus"); |
|
476 |
// test dispatch |
|
477 |
testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/v0"); |
|
478 |
testFindVirtual(SubExample.class, Example.class, void.class, "Sub/v0"); |
|
479 |
testFindVirtual(SubExample.class, IntExample.class, void.class, "Sub/v0"); |
|
480 |
testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/pkg_v0"); |
|
481 |
testFindVirtual(SubExample.class, Example.class, void.class, "Sub/pkg_v0"); |
|
482 |
testFindVirtual(Example.class, IntExample.class, void.class, "v0"); |
|
483 |
testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0"); |
|
484 |
} |
|
485 |
||
486 |
void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
487 |
Class<?> rcvc = defc; |
|
488 |
testFindVirtual(rcvc, defc, ret, name, params); |
|
489 |
} |
|
490 |
void testFindVirtual(Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
491 |
for (Object[] ac : accessCases(defc, name)) { |
|
492 |
testFindVirtual((Boolean)ac[0], (Lookup)ac[1], rcvc, defc, ret, name, params); |
|
493 |
} |
|
494 |
} |
|
495 |
void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
496 |
testFindVirtual(true, lookup, rcvc, defc, ret, name, params); |
|
497 |
} |
|
498 |
void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
499 |
countTest(positive); |
|
500 |
String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo |
|
4537 | 501 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 502 |
MethodHandle target = null; |
503 |
RuntimeException noAccess = null; |
|
504 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
505 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4535 | 506 |
target = lookup.findVirtual(defc, methodName, type); |
507 |
} catch (NoAccessException ex) { |
|
508 |
noAccess = ex; |
|
509 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
510 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
511 |
System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target |
4535 | 512 |
+(noAccess == null ? "" : " !! "+noAccess)); |
513 |
if (positive && noAccess != null) throw noAccess; |
|
514 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
515 |
if (!positive) return; // negative test failed as expected |
|
516 |
Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); |
|
4537 | 517 |
MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
518 |
if (defc.getClassLoader() != null) // detune due to 6939196 |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
519 |
assertEquals(typeWithSelf.dropParameterTypes(0,1), |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
520 |
target.type().dropParameterTypes(0,1)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
521 |
else // FIXME: use only this test when 6939196 is fixed |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
522 |
assertEquals(typeWithSelf, target.type()); |
4535 | 523 |
assertTrue(target.toString().contains(methodName)); // rough check |
524 |
if (!DO_MORE_CALLS && lookup != PRIVATE) return; |
|
525 |
Object[] argsWithSelf = randomArgs(paramsWithSelf); |
|
526 |
if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); |
|
527 |
printCalled(target, name, argsWithSelf); |
|
4537 | 528 |
target.invokeVarargs(argsWithSelf); |
4535 | 529 |
assertCalled(name, argsWithSelf); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
530 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
531 |
System.out.print(':'); |
4535 | 532 |
} |
533 |
||
534 |
@Test |
|
535 |
public void testFindSpecial() throws Throwable { |
|
536 |
if (CAN_SKIP_WORKING) return; |
|
537 |
startTest("findSpecial"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
538 |
testFindSpecial(SubExample.class, Example.class, void.class, "v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
539 |
testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
540 |
// Do some negative testing: |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
541 |
for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
542 |
testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
543 |
testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
544 |
testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
545 |
testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
546 |
} |
4535 | 547 |
} |
548 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
549 |
void testFindSpecial(Class<?> specialCaller, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
550 |
Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
551 |
testFindSpecial(true, EXAMPLE, specialCaller, defc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
552 |
testFindSpecial(true, PRIVATE, specialCaller, defc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
553 |
testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
554 |
testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params); |
4535 | 555 |
} |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
556 |
void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
557 |
Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4535 | 558 |
countTest(positive); |
4537 | 559 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 560 |
MethodHandle target = null; |
561 |
RuntimeException noAccess = null; |
|
562 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
563 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
564 |
target = lookup.findSpecial(defc, name, type, specialCaller); |
4535 | 565 |
} catch (NoAccessException ex) { |
566 |
noAccess = ex; |
|
567 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
568 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
569 |
System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
570 |
+(target == null ? "" : target.type()) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
571 |
+(noAccess == null ? "" : " !! "+noAccess)); |
4535 | 572 |
if (positive && noAccess != null) throw noAccess; |
573 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
574 |
if (!positive) return; // negative test failed as expected |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
575 |
assertEquals(specialCaller, target.type().parameterType(0)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
576 |
assertEquals(type, target.type().dropParameterTypes(0,1)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
577 |
Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params); |
4537 | 578 |
MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); |
4535 | 579 |
assertTrue(target.toString().contains(name)); // rough check |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
580 |
if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE) return; |
4535 | 581 |
Object[] args = randomArgs(paramsWithSelf); |
582 |
printCalled(target, name, args); |
|
4537 | 583 |
target.invokeVarargs(args); |
4535 | 584 |
assertCalled(name, args); |
585 |
} |
|
586 |
||
587 |
@Test |
|
588 |
public void testBind() throws Throwable { |
|
589 |
if (CAN_SKIP_WORKING) return; |
|
590 |
startTest("bind"); |
|
591 |
testBind(Example.class, void.class, "v0"); |
|
592 |
testBind(Example.class, void.class, "pkg_v0"); |
|
593 |
testBind(Example.class, void.class, "pri_v0"); |
|
594 |
testBind(Example.class, Object.class, "v1", Object.class); |
|
595 |
testBind(Example.class, Object.class, "v2", Object.class, Object.class); |
|
596 |
testBind(Example.class, Object.class, "v2", Object.class, int.class); |
|
597 |
testBind(Example.class, Object.class, "v2", int.class, Object.class); |
|
598 |
testBind(Example.class, Object.class, "v2", int.class, int.class); |
|
599 |
testBind(false, PRIVATE, Example.class, void.class, "bogus"); |
|
600 |
testBind(SubExample.class, void.class, "Sub/v0"); |
|
601 |
testBind(SubExample.class, void.class, "Sub/pkg_v0"); |
|
602 |
testBind(IntExample.Impl.class, void.class, "Int/v0"); |
|
603 |
} |
|
604 |
||
605 |
void testBind(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
606 |
for (Object[] ac : accessCases(defc, name)) { |
|
607 |
testBind((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); |
|
608 |
} |
|
609 |
} |
|
610 |
||
611 |
void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
612 |
countTest(positive); |
|
613 |
String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo |
|
4537 | 614 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 615 |
Object receiver = randomArg(defc); |
616 |
MethodHandle target = null; |
|
617 |
RuntimeException noAccess = null; |
|
618 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
619 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4535 | 620 |
target = lookup.bind(receiver, methodName, type); |
621 |
} catch (NoAccessException ex) { |
|
622 |
noAccess = ex; |
|
623 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
624 |
if (verbosity >= 3) |
4535 | 625 |
System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target |
626 |
+(noAccess == null ? "" : " !! "+noAccess)); |
|
627 |
if (positive && noAccess != null) throw noAccess; |
|
628 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
629 |
if (!positive) return; // negative test failed as expected |
|
630 |
assertEquals(type, target.type()); |
|
631 |
Object[] args = randomArgs(params); |
|
632 |
printCalled(target, name, args); |
|
4537 | 633 |
target.invokeVarargs(args); |
4535 | 634 |
Object[] argsWithReceiver = cat(array(Object[].class, receiver), args); |
635 |
assertCalled(name, argsWithReceiver); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
636 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
637 |
System.out.print(':'); |
4535 | 638 |
} |
639 |
||
640 |
@Test |
|
641 |
public void testUnreflect() throws Throwable { |
|
642 |
if (CAN_SKIP_WORKING) return; |
|
643 |
startTest("unreflect"); |
|
644 |
testUnreflect(Example.class, true, void.class, "s0"); |
|
645 |
testUnreflect(Example.class, true, void.class, "pkg_s0"); |
|
646 |
testUnreflect(Example.class, true, void.class, "pri_s0"); |
|
647 |
||
648 |
testUnreflect(Example.class, true, Object.class, "s1", Object.class); |
|
649 |
testUnreflect(Example.class, true, Object.class, "s2", int.class); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
650 |
testUnreflect(Example.class, true, Object.class, "s3", long.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
651 |
testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
652 |
testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
653 |
testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class); |
4535 | 654 |
|
655 |
testUnreflect(Example.class, false, void.class, "v0"); |
|
656 |
testUnreflect(Example.class, false, void.class, "pkg_v0"); |
|
657 |
testUnreflect(Example.class, false, void.class, "pri_v0"); |
|
658 |
testUnreflect(Example.class, false, Object.class, "v1", Object.class); |
|
659 |
testUnreflect(Example.class, false, Object.class, "v2", Object.class, Object.class); |
|
660 |
testUnreflect(Example.class, false, Object.class, "v2", Object.class, int.class); |
|
661 |
testUnreflect(Example.class, false, Object.class, "v2", int.class, Object.class); |
|
662 |
testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class); |
|
663 |
} |
|
664 |
||
665 |
void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable { |
|
666 |
for (Object[] ac : accessCases(defc, name)) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
667 |
testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params); |
4535 | 668 |
} |
669 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
670 |
void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
671 |
for (Object[] ac : accessCases(defc, name)) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
672 |
testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
673 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
674 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
675 |
void testUnreflectMaybeSpecial(Class<?> specialCaller, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
676 |
boolean positive, Lookup lookup, |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
677 |
Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4535 | 678 |
countTest(positive); |
4537 | 679 |
MethodType type = MethodType.methodType(ret, params); |
4535 | 680 |
Method rmethod = null; |
681 |
MethodHandle target = null; |
|
682 |
RuntimeException noAccess = null; |
|
683 |
try { |
|
684 |
rmethod = defc.getDeclaredMethod(name, params); |
|
685 |
} catch (NoSuchMethodException ex) { |
|
686 |
throw new NoAccessException(ex); |
|
687 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
688 |
boolean isStatic = (rcvc == null); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
689 |
boolean isSpecial = (specialCaller != null); |
4535 | 690 |
try { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
691 |
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
692 |
if (isSpecial) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
693 |
target = lookup.unreflectSpecial(rmethod, specialCaller); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
694 |
else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
695 |
target = lookup.unreflect(rmethod); |
4535 | 696 |
} catch (NoAccessException ex) { |
697 |
noAccess = ex; |
|
698 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
699 |
if (verbosity >= 3) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
700 |
System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
701 |
+(!isSpecial ? "" : " specialCaller="+specialCaller) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
702 |
+( isStatic ? "" : " receiver="+rcvc) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
703 |
+" => "+target |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
704 |
+(noAccess == null ? "" : " !! "+noAccess)); |
4535 | 705 |
if (positive && noAccess != null) throw noAccess; |
706 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
707 |
if (!positive) return; // negative test failed as expected |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
708 |
assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers())); |
4535 | 709 |
Class<?>[] paramsMaybeWithSelf = params; |
710 |
if (!isStatic) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
711 |
paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params); |
4535 | 712 |
} |
4537 | 713 |
MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
714 |
if (isStatic) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
715 |
assertEquals(typeMaybeWithSelf, target.type()); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
716 |
} else { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
717 |
if (defc.getClassLoader() != null) // detune due to 6939196 |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
718 |
assertEquals(typeMaybeWithSelf.dropParameterTypes(0,1), |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
719 |
target.type().dropParameterTypes(0,1)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
720 |
else // FIXME: use only this test when 6939196 is fixed |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
721 |
if (isSpecial) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
722 |
assertEquals(specialCaller, target.type().parameterType(0)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
723 |
else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
724 |
assertEquals(defc, target.type().parameterType(0)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
725 |
assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc)); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
726 |
} |
4535 | 727 |
Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); |
728 |
printCalled(target, name, argsMaybeWithSelf); |
|
4537 | 729 |
target.invokeVarargs(argsMaybeWithSelf); |
4535 | 730 |
assertCalled(name, argsMaybeWithSelf); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
731 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
732 |
System.out.print(':'); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
733 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
734 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
735 |
void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
736 |
for (Object[] ac : accessCases(defc, name, true)) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
737 |
Class<?> specialCaller = rcvc; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
738 |
testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
739 |
} |
4535 | 740 |
} |
741 |
||
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
742 |
@Test |
4535 | 743 |
public void testUnreflectSpecial() throws Throwable { |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
744 |
if (CAN_SKIP_WORKING) return; |
4535 | 745 |
startTest("unreflectSpecial"); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
746 |
testUnreflectSpecial(Example.class, Example.class, void.class, "v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
747 |
testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
748 |
testUnreflectSpecial(Example.class, Example.class, void.class, "pkg_v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
749 |
testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0"); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
750 |
testUnreflectSpecial(Example.class, Example.class, Object.class, "v2", int.class, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
751 |
testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
752 |
testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0"); |
4535 | 753 |
} |
754 |
||
4537 | 755 |
public static class HasFields { |
756 |
boolean fZ = false; |
|
757 |
byte fB = (byte)'B'; |
|
758 |
short fS = (short)'S'; |
|
759 |
char fC = 'C'; |
|
760 |
int fI = 'I'; |
|
761 |
long fJ = 'J'; |
|
762 |
float fF = 'F'; |
|
763 |
double fD = 'D'; |
|
764 |
static boolean sZ = true; |
|
765 |
static byte sB = 1+(byte)'B'; |
|
766 |
static short sS = 1+(short)'S'; |
|
767 |
static char sC = 1+'C'; |
|
768 |
static int sI = 1+'I'; |
|
769 |
static long sJ = 1+'J'; |
|
770 |
static float sF = 1+'F'; |
|
771 |
static double sD = 1+'D'; |
|
772 |
||
773 |
Object fL = 'L'; |
|
774 |
String fR = "R"; |
|
775 |
static Object sL = 'M'; |
|
776 |
static String sR = "S"; |
|
777 |
||
778 |
static final Object[][] CASES; |
|
779 |
static { |
|
780 |
ArrayList<Object[]> cases = new ArrayList<Object[]>(); |
|
781 |
Object types[][] = { |
|
782 |
{'L',Object.class}, {'R',String.class}, |
|
783 |
{'I',int.class}, {'J',long.class}, |
|
784 |
{'F',float.class}, {'D',double.class}, |
|
785 |
{'Z',boolean.class}, {'B',byte.class}, |
|
786 |
{'S',short.class}, {'C',char.class}, |
|
787 |
}; |
|
788 |
HasFields fields = new HasFields(); |
|
789 |
for (Object[] t : types) { |
|
790 |
for (int kind = 0; kind <= 1; kind++) { |
|
791 |
boolean isStatic = (kind != 0); |
|
792 |
char btc = (Character)t[0]; |
|
793 |
String name = (isStatic ? "s" : "f") + btc; |
|
794 |
Class<?> type = (Class<?>) t[1]; |
|
795 |
Object value; |
|
796 |
Field field; |
|
797 |
try { |
|
798 |
field = HasFields.class.getDeclaredField(name); |
|
799 |
} catch (Exception ex) { |
|
800 |
throw new InternalError("no field HasFields."+name); |
|
801 |
} |
|
802 |
try { |
|
803 |
value = field.get(fields); |
|
804 |
} catch (Exception ex) { |
|
805 |
throw new InternalError("cannot fetch field HasFields."+name); |
|
806 |
} |
|
807 |
if (type == float.class) { |
|
808 |
float v = 'F'; |
|
809 |
if (isStatic) v++; |
|
810 |
assert(value.equals(v)); |
|
811 |
} |
|
812 |
assert(name.equals(field.getName())); |
|
813 |
assert(type.equals(field.getType())); |
|
814 |
assert(isStatic == (Modifier.isStatic(field.getModifiers()))); |
|
815 |
cases.add(new Object[]{ field, value }); |
|
816 |
} |
|
817 |
} |
|
818 |
CASES = cases.toArray(new Object[0][]); |
|
819 |
} |
|
820 |
} |
|
821 |
||
822 |
@Test |
|
4535 | 823 |
public void testUnreflectGetter() throws Throwable { |
824 |
Lookup lookup = PRIVATE; // FIXME: test more lookups than this one |
|
825 |
startTest("unreflectGetter"); |
|
4537 | 826 |
for (Object[] c : HasFields.CASES) { |
827 |
Field f = (Field)c[0]; |
|
828 |
Object value = c[1]; |
|
829 |
Class<?> type = f.getType(); |
|
830 |
if (type.isPrimitive() && type != int.class) |
|
831 |
continue; //FIXME |
|
832 |
testUnreflectGetter(lookup, f, type, value); |
|
833 |
} |
|
834 |
} |
|
835 |
public void testUnreflectGetter(MethodHandles.Lookup lookup, |
|
836 |
Field f, Class<?> type, Object value) throws Throwable { |
|
837 |
countTest(true); |
|
838 |
boolean isStatic = Modifier.isStatic(f.getModifiers()); |
|
839 |
MethodType expType = MethodType.methodType(type, HasFields.class); |
|
840 |
if (isStatic) expType = expType.dropParameterTypes(0, 1); |
|
841 |
MethodHandle mh = lookup.unreflectGetter(f); |
|
842 |
assertSame(mh.type(), expType); |
|
843 |
assertEquals(mh.toString(), f.getName()); |
|
844 |
HasFields fields = new HasFields(); |
|
845 |
Object sawValue; |
|
846 |
Class<?> rtype = type; |
|
847 |
if (type != int.class) rtype = Object.class; |
|
848 |
mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(rtype)); |
|
849 |
Object expValue = value; |
|
850 |
for (int i = 0; i <= 1; i++) { |
|
851 |
if (isStatic) { |
|
852 |
if (type == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
853 |
sawValue = mh.<int>invokeExact(); // do these exactly |
4537 | 854 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
855 |
sawValue = mh.invokeExact(); |
4537 | 856 |
} else { |
857 |
if (type == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
858 |
sawValue = mh.<int>invokeExact((Object) fields); |
4537 | 859 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
860 |
sawValue = mh.invokeExact((Object) fields); |
4537 | 861 |
} |
862 |
assertEquals(sawValue, expValue); |
|
863 |
Object random = randomArg(type); |
|
864 |
f.set(fields, random); |
|
865 |
expValue = random; |
|
866 |
} |
|
867 |
f.set(fields, value); // put it back |
|
4535 | 868 |
} |
869 |
||
4537 | 870 |
|
871 |
@Test |
|
4535 | 872 |
public void testUnreflectSetter() throws Throwable { |
873 |
Lookup lookup = PRIVATE; // FIXME: test more lookups than this one |
|
874 |
startTest("unreflectSetter"); |
|
4537 | 875 |
for (Object[] c : HasFields.CASES) { |
876 |
Field f = (Field)c[0]; |
|
877 |
Object value = c[1]; |
|
878 |
Class<?> type = f.getType(); |
|
879 |
if (type.isPrimitive() && type != int.class) |
|
880 |
continue; //FIXME |
|
881 |
testUnreflectSetter(lookup, f, type, value); |
|
882 |
} |
|
883 |
} |
|
884 |
public void testUnreflectSetter(MethodHandles.Lookup lookup, |
|
885 |
Field f, Class<?> type, Object value) throws Throwable { |
|
886 |
countTest(true); |
|
887 |
boolean isStatic = Modifier.isStatic(f.getModifiers()); |
|
888 |
MethodType expType = MethodType.methodType(void.class, HasFields.class, type); |
|
889 |
if (isStatic) expType = expType.dropParameterTypes(0, 1); |
|
890 |
MethodHandle mh = lookup.unreflectSetter(f); |
|
891 |
assertSame(mh.type(), expType); |
|
892 |
assertEquals(mh.toString(), f.getName()); |
|
893 |
HasFields fields = new HasFields(); |
|
894 |
Object sawValue; |
|
895 |
Class<?> vtype = type; |
|
896 |
if (type != int.class) vtype = Object.class; |
|
897 |
int last = mh.type().parameterCount() - 1; |
|
898 |
mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(void.class).changeParameterType(last, vtype)); |
|
899 |
assertEquals(f.get(fields), value); // clean to start with |
|
900 |
for (int i = 0; i <= 1; i++) { |
|
901 |
Object putValue = randomArg(type); |
|
902 |
if (isStatic) { |
|
903 |
if (type == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
904 |
mh.<void>invokeExact((int)(Integer)putValue); // do these exactly |
4537 | 905 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
906 |
mh.<void>invokeExact(putValue); |
4537 | 907 |
} else { |
908 |
if (type == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
909 |
mh.<void>invokeExact((Object) fields, (int)(Integer)putValue); |
4537 | 910 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
911 |
mh.<void>invokeExact((Object) fields, putValue); |
4537 | 912 |
} |
913 |
assertEquals(f.get(fields), putValue); |
|
914 |
} |
|
915 |
f.set(fields, value); // put it back |
|
4535 | 916 |
} |
917 |
||
4537 | 918 |
@Test |
4535 | 919 |
public void testArrayElementGetter() throws Throwable { |
920 |
startTest("arrayElementGetter"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
921 |
testArrayElementGetterSetter(false); |
4537 | 922 |
} |
923 |
||
924 |
@Test |
|
925 |
public void testArrayElementSetter() throws Throwable { |
|
926 |
startTest("arrayElementSetter"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
927 |
testArrayElementGetterSetter(true); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
928 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
929 |
|
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
930 |
public void testArrayElementGetterSetter(boolean testSetter) throws Throwable { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
931 |
testArrayElementGetterSetter(new Object[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
932 |
testArrayElementGetterSetter(new String[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
933 |
testArrayElementGetterSetter(new boolean[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
934 |
testArrayElementGetterSetter(new byte[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
935 |
testArrayElementGetterSetter(new char[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
936 |
testArrayElementGetterSetter(new short[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
937 |
testArrayElementGetterSetter(new int[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
938 |
testArrayElementGetterSetter(new float[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
939 |
testArrayElementGetterSetter(new long[10], testSetter); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
940 |
testArrayElementGetterSetter(new double[10], testSetter); |
4535 | 941 |
} |
942 |
||
4537 | 943 |
public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable { |
944 |
countTest(true); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
945 |
if (verbosity >= 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]"); |
4537 | 946 |
Class<?> arrayType = array.getClass(); |
947 |
Class<?> elemType = arrayType.getComponentType(); |
|
948 |
MethodType expType = !testSetter |
|
949 |
? MethodType.methodType(elemType, arrayType, int.class) |
|
950 |
: MethodType.methodType(void.class, arrayType, int.class, elemType); |
|
951 |
MethodHandle mh = !testSetter |
|
952 |
? MethodHandles.arrayElementGetter(arrayType) |
|
953 |
: MethodHandles.arrayElementSetter(arrayType); |
|
954 |
assertSame(mh.type(), expType); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
955 |
if (elemType != int.class && elemType != boolean.class) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
956 |
MethodType gtype; |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
957 |
if (true) { // FIXME: remove this path (and remove <void> below in the mh.invokes) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
958 |
gtype = mh.type().changeParameterType(0, Object.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
959 |
if (testSetter) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
960 |
gtype = gtype.changeParameterType(2, Object.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
961 |
else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
962 |
gtype = gtype.changeReturnType(Object.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
963 |
} else |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
964 |
// FIXME: This simpler path hits a bug in convertArguments => ToGeneric |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
965 |
gtype = mh.type().generic().changeParameterType(1, int.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
966 |
mh = MethodHandles.convertArguments(mh, gtype); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
967 |
} |
4537 | 968 |
Object sawValue, expValue; |
969 |
List<Object> model = array2list(array); |
|
970 |
int length = Array.getLength(array); |
|
971 |
for (int i = 0; i < length; i++) { |
|
972 |
// update array element |
|
973 |
Object random = randomArg(elemType); |
|
974 |
model.set(i, random); |
|
975 |
if (testSetter) { |
|
976 |
if (elemType == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
977 |
mh.<void>invokeExact((int[]) array, i, (int)(Integer)random); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
978 |
else if (elemType == boolean.class) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
979 |
mh.<void>invokeExact((boolean[]) array, i, (boolean)(Boolean)random); |
4537 | 980 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
981 |
mh.<void>invokeExact(array, i, random); |
4537 | 982 |
assertEquals(model, array2list(array)); |
983 |
} else { |
|
984 |
Array.set(array, i, random); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
985 |
} |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
986 |
if (verbosity >= 5) { |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
987 |
List<Object> array2list = array2list(array); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
988 |
System.out.println("a["+i+"]="+random+" => "+array2list); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
989 |
if (!array2list.equals(model)) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
990 |
System.out.println("*** != "+model); |
4537 | 991 |
} |
992 |
// observe array element |
|
993 |
sawValue = Array.get(array, i); |
|
994 |
if (!testSetter) { |
|
995 |
expValue = sawValue; |
|
996 |
if (elemType == int.class) |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
997 |
sawValue = mh.<int>invokeExact((int[]) array, i); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
998 |
else if (elemType == boolean.class) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
999 |
sawValue = mh.<boolean>invokeExact((boolean[]) array, i); |
4537 | 1000 |
else |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1001 |
sawValue = mh.invokeExact(array, i); |
4537 | 1002 |
assertEquals(sawValue, expValue); |
1003 |
assertEquals(model, array2list(array)); |
|
1004 |
} |
|
1005 |
} |
|
1006 |
} |
|
1007 |
||
1008 |
List<Object> array2list(Object array) { |
|
1009 |
int length = Array.getLength(array); |
|
1010 |
ArrayList<Object> model = new ArrayList<Object>(length); |
|
1011 |
for (int i = 0; i < length; i++) |
|
1012 |
model.add(Array.get(array, i)); |
|
1013 |
return model; |
|
4535 | 1014 |
} |
1015 |
||
1016 |
static class Callee { |
|
1017 |
static Object id() { return called("id"); } |
|
1018 |
static Object id(Object x) { return called("id", x); } |
|
1019 |
static Object id(Object x, Object y) { return called("id", x, y); } |
|
1020 |
static Object id(Object x, Object y, Object z) { return called("id", x, y, z); } |
|
1021 |
static Object id(Object... vx) { return called("id", vx); } |
|
1022 |
static MethodHandle ofType(int n) { |
|
1023 |
return ofType(Object.class, n); |
|
1024 |
} |
|
1025 |
static MethodHandle ofType(Class<?> rtype, int n) { |
|
1026 |
if (n == -1) |
|
4537 | 1027 |
return ofType(MethodType.methodType(rtype, Object[].class)); |
1028 |
return ofType(MethodType.genericMethodType(n).changeReturnType(rtype)); |
|
4535 | 1029 |
} |
1030 |
static MethodHandle ofType(Class<?> rtype, Class<?>... ptypes) { |
|
4537 | 1031 |
return ofType(MethodType.methodType(rtype, ptypes)); |
4535 | 1032 |
} |
1033 |
static MethodHandle ofType(MethodType type) { |
|
1034 |
Class<?> rtype = type.returnType(); |
|
1035 |
String pfx = ""; |
|
1036 |
if (rtype != Object.class) |
|
1037 |
pfx = rtype.getSimpleName().substring(0, 1).toLowerCase(); |
|
1038 |
String name = pfx+"id"; |
|
1039 |
return PRIVATE.findStatic(Callee.class, name, type); |
|
1040 |
} |
|
1041 |
} |
|
1042 |
||
1043 |
@Test |
|
1044 |
public void testConvertArguments() throws Throwable { |
|
1045 |
if (CAN_SKIP_WORKING) return; |
|
1046 |
startTest("convertArguments"); |
|
1047 |
testConvert(Callee.ofType(1), null, "id", int.class); |
|
1048 |
testConvert(Callee.ofType(1), null, "id", String.class); |
|
1049 |
testConvert(Callee.ofType(1), null, "id", Integer.class); |
|
1050 |
testConvert(Callee.ofType(1), null, "id", short.class); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1051 |
testConvert(Callee.ofType(1), null, "id", char.class); |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1052 |
testConvert(Callee.ofType(1), null, "id", byte.class); |
4535 | 1053 |
} |
1054 |
||
1055 |
void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable { |
|
1056 |
testConvert(true, id, rtype, name, params); |
|
1057 |
} |
|
1058 |
||
1059 |
void testConvert(boolean positive, MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable { |
|
1060 |
countTest(positive); |
|
1061 |
MethodType idType = id.type(); |
|
1062 |
if (rtype == null) rtype = idType.returnType(); |
|
1063 |
for (int i = 0; i < params.length; i++) { |
|
1064 |
if (params[i] == null) params[i] = idType.parameterType(i); |
|
1065 |
} |
|
1066 |
// simulate the pairwise conversion |
|
4537 | 1067 |
MethodType newType = MethodType.methodType(rtype, params); |
4535 | 1068 |
Object[] args = randomArgs(newType.parameterArray()); |
1069 |
Object[] convArgs = args.clone(); |
|
1070 |
for (int i = 0; i < args.length; i++) { |
|
1071 |
Class<?> src = newType.parameterType(i); |
|
1072 |
Class<?> dst = idType.parameterType(i); |
|
1073 |
if (src != dst) |
|
1074 |
convArgs[i] = castToWrapper(convArgs[i], dst); |
|
1075 |
} |
|
4537 | 1076 |
Object convResult = id.invokeVarargs(convArgs); |
4535 | 1077 |
{ |
1078 |
Class<?> dst = newType.returnType(); |
|
1079 |
Class<?> src = idType.returnType(); |
|
1080 |
if (src != dst) |
|
1081 |
convResult = castToWrapper(convResult, dst); |
|
1082 |
} |
|
1083 |
MethodHandle target = null; |
|
1084 |
RuntimeException error = null; |
|
1085 |
try { |
|
1086 |
target = MethodHandles.convertArguments(id, newType); |
|
1087 |
} catch (RuntimeException ex) { |
|
1088 |
error = ex; |
|
1089 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1090 |
if (verbosity >= 3) |
4535 | 1091 |
System.out.println("convert "+id+ " to "+newType+" => "+target |
1092 |
+(error == null ? "" : " !! "+error)); |
|
1093 |
if (positive && error != null) throw error; |
|
1094 |
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); |
|
1095 |
if (!positive) return; // negative test failed as expected |
|
1096 |
assertEquals(newType, target.type()); |
|
1097 |
printCalled(target, id.toString(), args); |
|
4537 | 1098 |
Object result = target.invokeVarargs(args); |
4535 | 1099 |
assertCalled(name, convArgs); |
1100 |
assertEquals(convResult, result); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1101 |
if (verbosity >= 1) |
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1102 |
System.out.print(':'); |
4535 | 1103 |
} |
1104 |
||
1105 |
@Test |
|
4537 | 1106 |
public void testPermuteArguments() throws Throwable { |
1107 |
if (CAN_SKIP_WORKING) return; |
|
1108 |
startTest("permuteArguments"); |
|
1109 |
testPermuteArguments(4, Integer.class, 2, String.class, 0); |
|
1110 |
//testPermuteArguments(6, Integer.class, 0, null, 30); |
|
1111 |
//testPermuteArguments(4, Integer.class, 1, int.class, 6); |
|
1112 |
} |
|
1113 |
public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1114 |
if (verbosity >= 2) |
4537 | 1115 |
System.out.println("permuteArguments "+max+"*"+type1.getName() |
1116 |
+(t2c==0?"":"/"+t2c+"*"+type2.getName()) |
|
1117 |
+(dilution > 0 ? " with dilution "+dilution : "")); |
|
1118 |
int t2pos = t2c == 0 ? 0 : 1; |
|
1119 |
for (int inargs = t2pos+1; inargs <= max; inargs++) { |
|
1120 |
Class<?>[] types = new Class<?>[inargs]; |
|
1121 |
Arrays.fill(types, type1); |
|
1122 |
if (t2c != 0) { |
|
1123 |
// Fill in a middle range with type2: |
|
1124 |
Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2); |
|
1125 |
} |
|
1126 |
Object[] args = randomArgs(types); |
|
1127 |
int numcases = 1; |
|
1128 |
for (int outargs = 0; outargs <= max; outargs++) { |
|
1129 |
if (outargs - inargs >= MAX_ARG_INCREASE) continue; |
|
1130 |
int[] reorder = new int[outargs]; |
|
1131 |
int casStep = dilution + 1; |
|
1132 |
// Avoid some common factors: |
|
1133 |
while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) || |
|
1134 |
(casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0)) |
|
1135 |
casStep++; |
|
1136 |
for (int cas = 0; cas < numcases; cas += casStep) { |
|
1137 |
for (int i = 0, c = cas; i < outargs; i++) { |
|
1138 |
reorder[i] = c % inargs; |
|
1139 |
c /= inargs; |
|
1140 |
} |
|
1141 |
testPermuteArguments(args, types, reorder); |
|
1142 |
} |
|
1143 |
numcases *= inargs; |
|
1144 |
if (dilution > 10 && outargs >= 4) { |
|
1145 |
// Do some special patterns, which we probably missed. |
|
1146 |
// Replication of a single argument or argument pair. |
|
1147 |
for (int i = 0; i < inargs; i++) { |
|
1148 |
Arrays.fill(reorder, i); |
|
1149 |
testPermuteArguments(args, types, reorder); |
|
1150 |
for (int d = 1; d <= 2; d++) { |
|
1151 |
if (i + d >= inargs) continue; |
|
1152 |
for (int j = 1; j < outargs; j += 2) |
|
1153 |
reorder[j] += 1; |
|
1154 |
testPermuteArguments(args, types, reorder); |
|
1155 |
testPermuteArguments(args, types, reverse(reorder)); |
|
1156 |
} |
|
1157 |
} |
|
1158 |
// Repetition of a sequence of 3 or more arguments. |
|
1159 |
for (int i = 1; i < inargs; i++) { |
|
1160 |
for (int len = 3; len <= inargs; len++) { |
|
1161 |
for (int j = 0; j < outargs; j++) |
|
1162 |
reorder[j] = (i + (j % len)) % inargs; |
|
1163 |
testPermuteArguments(args, types, reorder); |
|
1164 |
testPermuteArguments(args, types, reverse(reorder)); |
|
1165 |
} |
|
1166 |
} |
|
1167 |
} |
|
1168 |
} |
|
1169 |
} |
|
1170 |
} |
|
1171 |
||
1172 |
static int[] reverse(int[] reorder) { |
|
1173 |
reorder = reorder.clone(); |
|
1174 |
for (int i = 0, imax = reorder.length / 2; i < imax; i++) { |
|
1175 |
int j = reorder.length - 1 - i; |
|
1176 |
int tem = reorder[i]; |
|
1177 |
reorder[i] = reorder[j]; |
|
1178 |
reorder[j] = tem; |
|
1179 |
} |
|
1180 |
return reorder; |
|
1181 |
} |
|
1182 |
||
1183 |
void testPermuteArguments(Object[] args, Class<?>[] types, int[] reorder) throws Throwable { |
|
1184 |
countTest(); |
|
1185 |
if (args == null && types == null) { |
|
1186 |
int max = 0; |
|
1187 |
for (int j : reorder) { |
|
1188 |
if (max < j) max = j; |
|
1189 |
} |
|
1190 |
args = randomArgs(max+1, Integer.class); |
|
1191 |
} |
|
1192 |
if (args == null) { |
|
1193 |
args = randomArgs(types); |
|
1194 |
} |
|
1195 |
if (types == null) { |
|
1196 |
types = new Class<?>[args.length]; |
|
1197 |
for (int i = 0; i < args.length; i++) |
|
1198 |
types[i] = args[i].getClass(); |
|
1199 |
} |
|
1200 |
int inargs = args.length, outargs = reorder.length; |
|
1201 |
assert(inargs == types.length); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1202 |
if (verbosity >= 3) |
4537 | 1203 |
System.out.println("permuteArguments "+Arrays.toString(reorder)); |
1204 |
Object[] permArgs = new Object[outargs]; |
|
1205 |
Class<?>[] permTypes = new Class<?>[outargs]; |
|
1206 |
for (int i = 0; i < outargs; i++) { |
|
1207 |
permArgs[i] = args[reorder[i]]; |
|
1208 |
permTypes[i] = types[reorder[i]]; |
|
1209 |
} |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1210 |
if (verbosity >= 4) { |
4537 | 1211 |
System.out.println("in args: "+Arrays.asList(args)); |
1212 |
System.out.println("out args: "+Arrays.asList(permArgs)); |
|
1213 |
System.out.println("in types: "+Arrays.asList(types)); |
|
1214 |
System.out.println("out types: "+Arrays.asList(permTypes)); |
|
1215 |
} |
|
1216 |
MethodType inType = MethodType.methodType(Object.class, types); |
|
1217 |
MethodType outType = MethodType.methodType(Object.class, permTypes); |
|
1218 |
MethodHandle target = MethodHandles.convertArguments(ValueConversions.varargsList(outargs), outType); |
|
1219 |
MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder); |
|
1220 |
Object result = newTarget.invokeVarargs(args); |
|
1221 |
Object expected = Arrays.asList(permArgs); |
|
1222 |
assertEquals(expected, result); |
|
1223 |
} |
|
1224 |
||
1225 |
||
1226 |
@Test |
|
1227 |
public void testSpreadArguments() throws Throwable { |
|
1228 |
if (CAN_SKIP_WORKING) return; |
|
1229 |
startTest("spreadArguments"); |
|
1230 |
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1231 |
if (verbosity >= 3) |
4537 | 1232 |
System.out.println("spreadArguments "+argType); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1233 |
// FIXME: enable _adapter_spread_args and fix Fail_2 |
4537 | 1234 |
for (int nargs = 0; nargs < 10; nargs++) { |
1235 |
if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1 |
|
1236 |
for (int pos = 0; pos < nargs; pos++) { |
|
1237 |
if (argType == int.class && pos > 0) continue; // FIXME Fail_3 |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1238 |
testSpreadArguments(argType, pos, nargs); |
4537 | 1239 |
} |
1240 |
} |
|
1241 |
} |
|
1242 |
} |
|
1243 |
public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable { |
|
1244 |
countTest(); |
|
1245 |
MethodHandle target = ValueConversions.varargsArray(nargs); |
|
1246 |
MethodHandle target2 = changeArgTypes(target, argType); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1247 |
if (verbosity >= 3) |
4537 | 1248 |
System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]"); |
1249 |
Object[] args = randomArgs(target2.type().parameterArray()); |
|
1250 |
// make sure the target does what we think it does: |
|
1251 |
if (pos == 0 && nargs < 5) { |
|
1252 |
Object[] check = (Object[]) target.invokeVarargs(args); |
|
1253 |
assertArrayEquals(args, check); |
|
1254 |
switch (nargs) { |
|
1255 |
case 0: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1256 |
check = target.<Object[]>invokeExact(); |
4537 | 1257 |
assertArrayEquals(args, check); |
1258 |
break; |
|
1259 |
case 1: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1260 |
check = target.<Object[]>invokeExact(args[0]); |
4537 | 1261 |
assertArrayEquals(args, check); |
1262 |
break; |
|
1263 |
case 2: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1264 |
check = target.<Object[]>invokeExact(args[0], args[1]); |
4537 | 1265 |
assertArrayEquals(args, check); |
1266 |
break; |
|
1267 |
} |
|
1268 |
} |
|
1269 |
List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList()); |
|
1270 |
{ // modify newParams in place |
|
1271 |
List<Class<?>> spreadParams = newParams.subList(pos, nargs); |
|
1272 |
spreadParams.clear(); spreadParams.add(Object[].class); |
|
1273 |
} |
|
1274 |
MethodType newType = MethodType.methodType(Object.class, newParams); |
|
1275 |
MethodHandle result = MethodHandles.spreadArguments(target2, newType); |
|
1276 |
Object[] returnValue; |
|
1277 |
if (pos == 0) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1278 |
returnValue = (Object[]) result.invokeExact(args); |
4537 | 1279 |
} else { |
1280 |
Object[] args1 = Arrays.copyOfRange(args, 0, pos+1); |
|
1281 |
args1[pos] = Arrays.copyOfRange(args, pos, args.length); |
|
1282 |
returnValue = (Object[]) result.invokeVarargs(args1); |
|
1283 |
} |
|
1284 |
assertArrayEquals(args, returnValue); |
|
1285 |
} |
|
1286 |
||
1287 |
@Test |
|
1288 |
public void testCollectArguments() throws Throwable { |
|
1289 |
if (CAN_SKIP_WORKING) return; |
|
1290 |
startTest("collectArguments"); |
|
1291 |
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1292 |
if (verbosity >= 3) |
4537 | 1293 |
System.out.println("collectArguments "+argType); |
1294 |
for (int nargs = 0; nargs < 10; nargs++) { |
|
1295 |
for (int pos = 0; pos < nargs; pos++) { |
|
1296 |
if (argType == int.class) continue; // FIXME Fail_4 |
|
1297 |
testCollectArguments(argType, pos, nargs); |
|
1298 |
} |
|
1299 |
} |
|
1300 |
} |
|
1301 |
} |
|
1302 |
public void testCollectArguments(Class<?> argType, int pos, int nargs) throws Throwable { |
|
1303 |
countTest(); |
|
1304 |
// fake up a MH with the same type as the desired adapter: |
|
1305 |
MethodHandle fake = ValueConversions.varargsArray(nargs); |
|
1306 |
fake = changeArgTypes(fake, argType); |
|
1307 |
MethodType newType = fake.type(); |
|
1308 |
Object[] args = randomArgs(newType.parameterArray()); |
|
1309 |
// here is what should happen: |
|
1310 |
Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1); |
|
1311 |
collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length); |
|
1312 |
// here is the MH which will witness the collected argument tail: |
|
1313 |
MethodHandle target = ValueConversions.varargsArray(pos+1); |
|
1314 |
target = changeArgTypes(target, 0, pos, argType); |
|
1315 |
target = changeArgTypes(target, pos, pos+1, Object[].class); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1316 |
if (verbosity >= 3) |
4537 | 1317 |
System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]"); |
1318 |
MethodHandle result = MethodHandles.collectArguments(target, newType); |
|
1319 |
Object[] returnValue = (Object[]) result.invokeVarargs(args); |
|
1320 |
// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]); |
|
1321 |
// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]); |
|
1322 |
// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]); |
|
1323 |
assertArrayEquals(collectedArgs, returnValue); |
|
1324 |
} |
|
1325 |
||
1326 |
@Test |
|
4535 | 1327 |
public void testInsertArguments() throws Throwable { |
1328 |
if (CAN_SKIP_WORKING) return; |
|
1329 |
startTest("insertArguments"); |
|
1330 |
for (int nargs = 0; nargs <= 4; nargs++) { |
|
1331 |
for (int ins = 0; ins <= 4; ins++) { |
|
1332 |
if (ins > MAX_ARG_INCREASE) continue; // FIXME Fail_6 |
|
1333 |
for (int pos = 0; pos <= nargs; pos++) { |
|
1334 |
testInsertArguments(nargs, pos, ins); |
|
1335 |
} |
|
1336 |
} |
|
1337 |
} |
|
1338 |
} |
|
1339 |
||
1340 |
void testInsertArguments(int nargs, int pos, int ins) throws Throwable { |
|
1341 |
countTest(); |
|
1342 |
MethodHandle target = ValueConversions.varargsArray(nargs + ins); |
|
1343 |
Object[] args = randomArgs(target.type().parameterArray()); |
|
1344 |
List<Object> resList = Arrays.asList(args); |
|
1345 |
List<Object> argsToPass = new ArrayList<Object>(resList); |
|
1346 |
List<Object> argsToInsert = argsToPass.subList(pos, pos + ins); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1347 |
if (verbosity >= 3) |
4535 | 1348 |
System.out.println("insert: "+argsToInsert+" into "+target); |
4537 | 1349 |
MethodHandle target2 = MethodHandles.insertArguments(target, pos, |
1350 |
(Object[]) argsToInsert.toArray()); |
|
4535 | 1351 |
argsToInsert.clear(); // remove from argsToInsert |
4537 | 1352 |
Object res2 = target2.invokeVarargs(argsToPass); |
4535 | 1353 |
Object res2List = Arrays.asList((Object[])res2); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1354 |
if (verbosity >= 3) |
4535 | 1355 |
System.out.println("result: "+res2List); |
1356 |
//if (!resList.equals(res2List)) |
|
1357 |
// System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List); |
|
1358 |
assertEquals(resList, res2List); |
|
1359 |
} |
|
1360 |
||
4537 | 1361 |
@Test |
1362 |
public void testFilterArguments() throws Throwable { |
|
1363 |
if (CAN_SKIP_WORKING) return; |
|
1364 |
startTest("filterArguments"); |
|
1365 |
for (int nargs = 1; nargs <= 6; nargs++) { |
|
1366 |
for (int pos = 0; pos < nargs; pos++) { |
|
1367 |
testFilterArguments(nargs, pos); |
|
1368 |
} |
|
1369 |
} |
|
1370 |
} |
|
1371 |
||
1372 |
void testFilterArguments(int nargs, int pos) throws Throwable { |
|
1373 |
countTest(); |
|
1374 |
MethodHandle target = ValueConversions.varargsList(nargs); |
|
1375 |
MethodHandle filter = ValueConversions.varargsList(1); |
|
1376 |
filter = MethodHandles.convertArguments(filter, filter.type().generic()); |
|
1377 |
Object[] argsToPass = randomArgs(nargs, Object.class); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1378 |
if (verbosity >= 3) |
4537 | 1379 |
System.out.println("filter "+target+" at "+pos+" with "+filter); |
1380 |
MethodHandle[] filters = new MethodHandle[pos*2+1]; |
|
1381 |
filters[pos] = filter; |
|
1382 |
MethodHandle target2 = MethodHandles.filterArguments(target, filters); |
|
1383 |
// Simulate expected effect of filter on arglist: |
|
1384 |
Object[] filteredArgs = argsToPass.clone(); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1385 |
filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]); |
4537 | 1386 |
List<Object> expected = Arrays.asList(filteredArgs); |
1387 |
Object result = target2.invokeVarargs(argsToPass); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1388 |
if (verbosity >= 3) |
4537 | 1389 |
System.out.println("result: "+result); |
1390 |
if (!expected.equals(result)) |
|
1391 |
System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+argsToPass+" => "+result); |
|
1392 |
assertEquals(expected, result); |
|
1393 |
} |
|
1394 |
||
1395 |
@Test |
|
1396 |
public void testFoldArguments() throws Throwable { |
|
1397 |
if (CAN_SKIP_WORKING) return; |
|
1398 |
startTest("foldArguments"); |
|
1399 |
for (int nargs = 0; nargs <= 4; nargs++) { |
|
1400 |
for (int fold = 0; fold <= nargs; fold++) { |
|
1401 |
for (int pos = 0; pos <= nargs; pos++) { |
|
1402 |
testFoldArguments(nargs, pos, fold); |
|
1403 |
} |
|
1404 |
} |
|
1405 |
} |
|
1406 |
} |
|
1407 |
||
1408 |
void testFoldArguments(int nargs, int pos, int fold) throws Throwable { |
|
1409 |
if (pos != 0) return; // can fold only at pos=0 for now |
|
1410 |
countTest(); |
|
1411 |
MethodHandle target = ValueConversions.varargsList(1 + nargs); |
|
1412 |
MethodHandle combine = ValueConversions.varargsList(fold); |
|
1413 |
List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class)); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1414 |
if (verbosity >= 3) |
4537 | 1415 |
System.out.println("fold "+target+" with "+combine); |
1416 |
MethodHandle target2 = MethodHandles.foldArguments(target, combine); |
|
1417 |
// Simulate expected effect of combiner on arglist: |
|
1418 |
List<Object> expected = new ArrayList<Object>(argsToPass); |
|
1419 |
List<Object> argsToFold = expected.subList(pos, pos + fold); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1420 |
if (verbosity >= 3) |
4537 | 1421 |
System.out.println("fold: "+argsToFold+" into "+target2); |
1422 |
Object foldedArgs = combine.invokeVarargs(argsToFold); |
|
1423 |
argsToFold.add(0, foldedArgs); |
|
1424 |
Object result = target2.invokeVarargs(argsToPass); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1425 |
if (verbosity >= 3) |
4537 | 1426 |
System.out.println("result: "+result); |
1427 |
if (!expected.equals(result)) |
|
1428 |
System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result); |
|
1429 |
assertEquals(expected, result); |
|
1430 |
} |
|
1431 |
||
1432 |
@Test |
|
1433 |
public void testDropArguments() throws Throwable { |
|
1434 |
if (CAN_SKIP_WORKING) return; |
|
1435 |
startTest("dropArguments"); |
|
1436 |
for (int nargs = 0; nargs <= 4; nargs++) { |
|
1437 |
for (int drop = 1; drop <= 4; drop++) { |
|
1438 |
for (int pos = 0; pos <= nargs; pos++) { |
|
1439 |
testDropArguments(nargs, pos, drop); |
|
1440 |
} |
|
1441 |
} |
|
1442 |
} |
|
1443 |
} |
|
1444 |
||
1445 |
void testDropArguments(int nargs, int pos, int drop) throws Throwable { |
|
1446 |
countTest(); |
|
1447 |
MethodHandle target = ValueConversions.varargsArray(nargs); |
|
1448 |
Object[] args = randomArgs(target.type().parameterArray()); |
|
1449 |
MethodHandle target2 = MethodHandles.dropArguments(target, pos, |
|
1450 |
Collections.nCopies(drop, Object.class).toArray(new Class[0])); |
|
1451 |
List<Object> resList = Arrays.asList(args); |
|
1452 |
List<Object> argsToDrop = new ArrayList<Object>(resList); |
|
1453 |
for (int i = drop; i > 0; i--) { |
|
1454 |
argsToDrop.add(pos, "blort#"+i); |
|
1455 |
} |
|
1456 |
Object res2 = target2.invokeVarargs(argsToDrop); |
|
1457 |
Object res2List = Arrays.asList((Object[])res2); |
|
1458 |
//if (!resList.equals(res2List)) |
|
1459 |
// System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List); |
|
1460 |
assertEquals(resList, res2List); |
|
1461 |
} |
|
1462 |
||
1463 |
@Test |
|
1464 |
public void testInvokers() throws Throwable { |
|
1465 |
if (CAN_SKIP_WORKING) return; |
|
1466 |
startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker"); |
|
1467 |
// exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker |
|
1468 |
Set<MethodType> done = new HashSet<MethodType>(); |
|
1469 |
for (int i = 0; i <= 6; i++) { |
|
1470 |
MethodType gtype = MethodType.genericMethodType(i); |
|
1471 |
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { |
|
1472 |
for (int j = -1; j < i; j++) { |
|
1473 |
MethodType type = gtype; |
|
1474 |
if (j < 0) |
|
1475 |
type = type.changeReturnType(argType); |
|
1476 |
else if (argType == void.class) |
|
1477 |
continue; |
|
1478 |
else |
|
1479 |
type = type.changeParameterType(j, argType); |
|
1480 |
if (argType.isPrimitive() && j != i-1) continue; // FIXME Fail_5 |
|
1481 |
if (done.add(type)) |
|
1482 |
testInvokers(type); |
|
1483 |
MethodType vtype = type.changeReturnType(void.class); |
|
1484 |
if (done.add(vtype)) |
|
1485 |
testInvokers(vtype); |
|
1486 |
} |
|
1487 |
} |
|
1488 |
} |
|
1489 |
} |
|
1490 |
||
1491 |
public void testInvokers(MethodType type) throws Throwable { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1492 |
if (verbosity >= 3) |
4537 | 1493 |
System.out.println("test invokers for "+type); |
1494 |
int nargs = type.parameterCount(); |
|
1495 |
boolean testRetCode = type.returnType() != void.class; |
|
1496 |
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee", |
|
1497 |
MethodType.genericMethodType(0, true)); |
|
1498 |
target = MethodHandles.collectArguments(target, type); |
|
1499 |
Object[] args = randomArgs(type.parameterArray()); |
|
1500 |
List<Object> targetPlusArgs = new ArrayList<Object>(Arrays.asList(args)); |
|
1501 |
targetPlusArgs.add(0, target); |
|
1502 |
int code = (Integer) invokee(args); |
|
1503 |
Object log = logEntry("invokee", args); |
|
1504 |
assertEquals(log.hashCode(), code); |
|
1505 |
assertCalled("invokee", args); |
|
1506 |
MethodHandle inv; |
|
1507 |
Object result; |
|
1508 |
// exact invoker |
|
1509 |
countTest(); |
|
1510 |
calledLog.clear(); |
|
1511 |
inv = MethodHandles.exactInvoker(type); |
|
1512 |
result = inv.invokeVarargs(targetPlusArgs); |
|
1513 |
if (testRetCode) assertEquals(code, result); |
|
1514 |
assertCalled("invokee", args); |
|
1515 |
// generic invoker |
|
1516 |
countTest(); |
|
1517 |
inv = MethodHandles.genericInvoker(type); |
|
1518 |
if (nargs <= 3) { |
|
1519 |
calledLog.clear(); |
|
1520 |
switch (nargs) { |
|
1521 |
case 0: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1522 |
result = inv.invokeExact(target); |
4537 | 1523 |
break; |
1524 |
case 1: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1525 |
result = inv.invokeExact(target, args[0]); |
4537 | 1526 |
break; |
1527 |
case 2: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1528 |
result = inv.invokeExact(target, args[0], args[1]); |
4537 | 1529 |
break; |
1530 |
case 3: |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1531 |
result = inv.invokeExact(target, args[0], args[1], args[2]); |
4537 | 1532 |
break; |
1533 |
} |
|
1534 |
if (testRetCode) assertEquals(code, result); |
|
1535 |
assertCalled("invokee", args); |
|
1536 |
} |
|
1537 |
calledLog.clear(); |
|
1538 |
result = inv.invokeVarargs(targetPlusArgs); |
|
1539 |
if (testRetCode) assertEquals(code, result); |
|
1540 |
assertCalled("invokee", args); |
|
1541 |
// varargs invoker #0 |
|
1542 |
calledLog.clear(); |
|
1543 |
inv = MethodHandles.varargsInvoker(type, 0); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1544 |
result = inv.invokeExact(target, args); |
4537 | 1545 |
if (testRetCode) assertEquals(code, result); |
1546 |
assertCalled("invokee", args); |
|
1547 |
if (nargs >= 1) { |
|
1548 |
// varargs invoker #1 |
|
1549 |
calledLog.clear(); |
|
1550 |
inv = MethodHandles.varargsInvoker(type, 1); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1551 |
result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs)); |
4537 | 1552 |
if (testRetCode) assertEquals(code, result); |
1553 |
assertCalled("invokee", args); |
|
1554 |
} |
|
1555 |
if (nargs >= 2) { |
|
1556 |
// varargs invoker #2 |
|
1557 |
calledLog.clear(); |
|
1558 |
inv = MethodHandles.varargsInvoker(type, 2); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1559 |
result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs)); |
4537 | 1560 |
if (testRetCode) assertEquals(code, result); |
1561 |
assertCalled("invokee", args); |
|
1562 |
} |
|
1563 |
if (nargs >= 3) { |
|
1564 |
// varargs invoker #3 |
|
1565 |
calledLog.clear(); |
|
1566 |
inv = MethodHandles.varargsInvoker(type, 3); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1567 |
result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs)); |
4537 | 1568 |
if (testRetCode) assertEquals(code, result); |
1569 |
assertCalled("invokee", args); |
|
1570 |
} |
|
1571 |
for (int k = 0; k <= nargs; k++) { |
|
1572 |
// varargs invoker #0..N |
|
1573 |
countTest(); |
|
1574 |
calledLog.clear(); |
|
1575 |
inv = MethodHandles.varargsInvoker(type, k); |
|
1576 |
List<Object> targetPlusVarArgs = new ArrayList<Object>(targetPlusArgs); |
|
1577 |
List<Object> tailList = targetPlusVarArgs.subList(1+k, 1+nargs); |
|
1578 |
Object[] tail = tailList.toArray(); |
|
1579 |
tailList.clear(); tailList.add(tail); |
|
1580 |
result = inv.invokeVarargs(targetPlusVarArgs); |
|
1581 |
if (testRetCode) assertEquals(code, result); |
|
1582 |
assertCalled("invokee", args); |
|
1583 |
} |
|
1584 |
// dynamic invoker |
|
1585 |
countTest(); |
|
1586 |
CallSite site = new CallSite(MethodHandlesTest.class, "foo", type); |
|
1587 |
inv = MethodHandles.dynamicInvoker(site); |
|
1588 |
site.setTarget(target); |
|
1589 |
calledLog.clear(); |
|
1590 |
result = inv.invokeVarargs(args); |
|
1591 |
if (testRetCode) assertEquals(code, result); |
|
1592 |
assertCalled("invokee", args); |
|
1593 |
} |
|
1594 |
||
1595 |
static Object invokee(Object... args) { |
|
1596 |
return called("invokee", args).hashCode(); |
|
1597 |
} |
|
1598 |
||
4535 | 1599 |
private static final String MISSING_ARG = "missingArg"; |
1600 |
static Object targetIfEquals() { |
|
1601 |
return called("targetIfEquals"); |
|
1602 |
} |
|
1603 |
static Object fallbackIfNotEquals() { |
|
1604 |
return called("fallbackIfNotEquals"); |
|
1605 |
} |
|
1606 |
static Object targetIfEquals(Object x) { |
|
1607 |
assertEquals(x, MISSING_ARG); |
|
1608 |
return called("targetIfEquals", x); |
|
1609 |
} |
|
1610 |
static Object fallbackIfNotEquals(Object x) { |
|
1611 |
assertFalse(x.toString(), x.equals(MISSING_ARG)); |
|
1612 |
return called("fallbackIfNotEquals", x); |
|
1613 |
} |
|
1614 |
static Object targetIfEquals(Object x, Object y) { |
|
1615 |
assertEquals(x, y); |
|
1616 |
return called("targetIfEquals", x, y); |
|
1617 |
} |
|
1618 |
static Object fallbackIfNotEquals(Object x, Object y) { |
|
1619 |
assertFalse(x.toString(), x.equals(y)); |
|
1620 |
return called("fallbackIfNotEquals", x, y); |
|
1621 |
} |
|
1622 |
static Object targetIfEquals(Object x, Object y, Object z) { |
|
1623 |
assertEquals(x, y); |
|
1624 |
return called("targetIfEquals", x, y, z); |
|
1625 |
} |
|
1626 |
static Object fallbackIfNotEquals(Object x, Object y, Object z) { |
|
1627 |
assertFalse(x.toString(), x.equals(y)); |
|
1628 |
return called("fallbackIfNotEquals", x, y, z); |
|
1629 |
} |
|
1630 |
||
4537 | 1631 |
@Test |
1632 |
public void testGuardWithTest() throws Throwable { |
|
1633 |
if (CAN_SKIP_WORKING) return; |
|
1634 |
startTest("guardWithTest"); |
|
1635 |
for (int nargs = 0; nargs <= 3; nargs++) { |
|
1636 |
if (nargs != 2) continue; // FIXME: test more later |
|
1637 |
testGuardWithTest(nargs, Object.class); |
|
1638 |
testGuardWithTest(nargs, String.class); |
|
1639 |
} |
|
1640 |
} |
|
1641 |
void testGuardWithTest(int nargs, Class<?> argClass) throws Throwable { |
|
1642 |
countTest(); |
|
1643 |
MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class)); |
|
1644 |
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs)); |
|
1645 |
MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs)); |
|
1646 |
while (test.type().parameterCount() < nargs) |
|
1647 |
test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class); |
|
1648 |
while (test.type().parameterCount() > nargs) |
|
1649 |
test = MethodHandles.insertArguments(test, 0, MISSING_ARG); |
|
1650 |
if (argClass != Object.class) { |
|
1651 |
test = changeArgTypes(test, argClass); |
|
1652 |
target = changeArgTypes(target, argClass); |
|
1653 |
fallback = changeArgTypes(fallback, argClass); |
|
1654 |
} |
|
1655 |
MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback); |
|
1656 |
assertEquals(target.type(), mh.type()); |
|
1657 |
Object[][] argLists = { |
|
1658 |
{ }, |
|
1659 |
{ "foo" }, { MISSING_ARG }, |
|
1660 |
{ "foo", "foo" }, { "foo", "bar" }, |
|
1661 |
{ "foo", "foo", "baz" }, { "foo", "bar", "baz" } |
|
1662 |
}; |
|
1663 |
for (Object[] argList : argLists) { |
|
1664 |
if (argList.length != nargs) continue; |
|
1665 |
boolean equals; |
|
1666 |
switch (nargs) { |
|
1667 |
case 0: equals = true; break; |
|
1668 |
case 1: equals = MISSING_ARG.equals(argList[0]); break; |
|
1669 |
default: equals = argList[0].equals(argList[1]); break; |
|
1670 |
} |
|
1671 |
String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1672 |
if (verbosity >= 3) |
4537 | 1673 |
System.out.println(logEntry(willCall, argList)); |
1674 |
Object result = mh.invokeVarargs(argList); |
|
1675 |
assertCalled(willCall, argList); |
|
1676 |
} |
|
1677 |
} |
|
1678 |
||
1679 |
@Test |
|
1680 |
public void testCatchException() throws Throwable { |
|
1681 |
if (CAN_SKIP_WORKING) return; |
|
1682 |
startTest("catchException"); |
|
1683 |
for (int nargs = 2; nargs <= 6; nargs++) { |
|
1684 |
for (int ti = 0; ti <= 1; ti++) { |
|
1685 |
boolean throwIt = (ti != 0); |
|
1686 |
testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs); |
|
1687 |
testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs); |
|
1688 |
testCatchException(String.class, new LinkageError("testing"), throwIt, nargs); |
|
1689 |
} |
|
1690 |
} |
|
1691 |
} |
|
1692 |
||
1693 |
private static <T extends Throwable> |
|
1694 |
Object throwOrReturn(Object normal, T exception) throws T { |
|
1695 |
if (exception != null) throw exception; |
|
1696 |
return normal; |
|
1697 |
} |
|
1698 |
||
1699 |
void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable { |
|
1700 |
countTest(); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1701 |
if (verbosity >= 3) |
4537 | 1702 |
System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs); |
1703 |
Class<? extends Throwable> exType = thrown.getClass(); |
|
1704 |
MethodHandle throwOrReturn |
|
1705 |
= PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn", |
|
1706 |
MethodType.methodType(Object.class, Object.class, Throwable.class)); |
|
1707 |
MethodHandle thrower = throwOrReturn; |
|
1708 |
while (thrower.type().parameterCount() < nargs) |
|
1709 |
thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class); |
|
1710 |
MethodHandle target = MethodHandles.catchException(thrower, |
|
1711 |
thrown.getClass(), ValueConversions.varargsList(1+nargs)); |
|
1712 |
assertEquals(thrower.type(), target.type()); |
|
1713 |
//System.out.println("catching with "+target+" : "+throwOrReturn); |
|
1714 |
Object[] args = randomArgs(nargs, Object.class); |
|
1715 |
args[1] = (throwIt ? thrown : null); |
|
1716 |
Object returned = target.invokeVarargs(args); |
|
1717 |
//System.out.println("return from "+target+" : "+returned); |
|
1718 |
if (!throwIt) { |
|
1719 |
assertSame(args[0], returned); |
|
1720 |
} else { |
|
1721 |
List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args)); |
|
1722 |
catchArgs.add(0, thrown); |
|
1723 |
assertEquals(catchArgs, returned); |
|
1724 |
} |
|
1725 |
} |
|
1726 |
||
1727 |
@Test |
|
1728 |
public void testThrowException() throws Throwable { |
|
1729 |
if (CAN_SKIP_WORKING) return; |
|
1730 |
startTest("throwException"); |
|
1731 |
testThrowException(int.class, new ClassCastException("testing")); |
|
1732 |
testThrowException(void.class, new java.io.IOException("testing")); |
|
1733 |
testThrowException(String.class, new LinkageError("testing")); |
|
1734 |
} |
|
1735 |
||
1736 |
void testThrowException(Class<?> returnType, Throwable thrown) throws Throwable { |
|
1737 |
countTest(); |
|
1738 |
Class<? extends Throwable> exType = thrown.getClass(); |
|
1739 |
MethodHandle target = MethodHandles.throwException(returnType, exType); |
|
1740 |
//System.out.println("throwing with "+target+" : "+thrown); |
|
1741 |
MethodType expectedType = MethodType.methodType(returnType, exType); |
|
1742 |
assertEquals(expectedType, target.type()); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1743 |
target = MethodHandles.convertArguments(target, target.type().generic()); |
4537 | 1744 |
Throwable caught = null; |
1745 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1746 |
Object res = target.invokeExact((Object) thrown); |
4537 | 1747 |
fail("got "+res+" instead of throwing "+thrown); |
1748 |
} catch (Throwable ex) { |
|
1749 |
if (ex != thrown) { |
|
1750 |
if (ex instanceof Error) throw (Error)ex; |
|
1751 |
if (ex instanceof RuntimeException) throw (RuntimeException)ex; |
|
1752 |
} |
|
1753 |
caught = ex; |
|
1754 |
} |
|
1755 |
assertSame(thrown, caught); |
|
1756 |
} |
|
1757 |
||
1758 |
@Test |
|
1759 |
public void testCastFailure() throws Throwable { |
|
1760 |
if (CAN_SKIP_WORKING) return; |
|
1761 |
startTest("testCastFailure"); |
|
1762 |
testCastFailure("cast/argument", 11000); |
|
1763 |
testCastFailure("unbox/argument", 11000); |
|
1764 |
testCastFailure("cast/return", 11000); |
|
1765 |
testCastFailure("unbox/return", 11000); |
|
1766 |
} |
|
1767 |
||
1768 |
static class Surprise extends JavaMethodHandle { |
|
1769 |
Surprise() { super("value"); } |
|
1770 |
Object value(Object x) { |
|
1771 |
trace("value", x); |
|
1772 |
if (boo != null) return boo; |
|
1773 |
return x; |
|
1774 |
} |
|
1775 |
Object boo; |
|
1776 |
void boo(Object x) { boo = x; } |
|
1777 |
||
1778 |
static void trace(String x, Object y) { |
|
1779 |
if (verbosity > 8) System.out.println(x+"="+y); |
|
1780 |
} |
|
1781 |
static Object refIdentity(Object x) { trace("ref.x", x); return x; } |
|
1782 |
static Integer boxIdentity(Integer x) { trace("box.x", x); return x; } |
|
1783 |
static int intIdentity(int x) { trace("int.x", x); return x; } |
|
1784 |
static MethodHandle REF_IDENTITY = PRIVATE.findStatic( |
|
1785 |
Surprise.class, "refIdentity", |
|
1786 |
MethodType.methodType(Object.class, Object.class)); |
|
1787 |
static MethodHandle BOX_IDENTITY = PRIVATE.findStatic( |
|
1788 |
Surprise.class, "boxIdentity", |
|
1789 |
MethodType.methodType(Integer.class, Integer.class)); |
|
1790 |
static MethodHandle INT_IDENTITY = PRIVATE.findStatic( |
|
1791 |
Surprise.class, "intIdentity", |
|
1792 |
MethodType.methodType(int.class, int.class)); |
|
1793 |
} |
|
1794 |
||
1795 |
void testCastFailure(String mode, int okCount) throws Throwable { |
|
1796 |
countTest(false); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1797 |
if (verbosity > 2) System.out.println("mode="+mode); |
4537 | 1798 |
Surprise boo = new Surprise(); |
1799 |
MethodHandle identity = Surprise.REF_IDENTITY, surprise = boo; |
|
1800 |
if (mode.endsWith("/return")) { |
|
1801 |
if (mode.equals("unbox/return")) { |
|
1802 |
// fail on return to ((Integer)surprise).intValue |
|
1803 |
surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(int.class, Object.class)); |
|
1804 |
identity = MethodHandles.convertArguments(identity, MethodType.methodType(int.class, Object.class)); |
|
1805 |
} else if (mode.equals("cast/return")) { |
|
1806 |
// fail on return to (Integer)surprise |
|
1807 |
surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(Integer.class, Object.class)); |
|
1808 |
identity = MethodHandles.convertArguments(identity, MethodType.methodType(Integer.class, Object.class)); |
|
1809 |
} |
|
1810 |
} else if (mode.endsWith("/argument")) { |
|
1811 |
MethodHandle callee = null; |
|
1812 |
if (mode.equals("unbox/argument")) { |
|
1813 |
// fail on handing surprise to int argument |
|
1814 |
callee = Surprise.INT_IDENTITY; |
|
1815 |
} else if (mode.equals("cast/argument")) { |
|
1816 |
// fail on handing surprise to Integer argument |
|
1817 |
callee = Surprise.BOX_IDENTITY; |
|
1818 |
} |
|
1819 |
if (callee != null) { |
|
1820 |
callee = MethodHandles.convertArguments(callee, MethodType.genericMethodType(1)); |
|
1821 |
surprise = MethodHandles.filterArguments(callee, surprise); |
|
1822 |
identity = MethodHandles.filterArguments(callee, identity); |
|
1823 |
} |
|
1824 |
} |
|
1825 |
assertNotSame(mode, surprise, boo); |
|
1826 |
identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1)); |
|
1827 |
surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1)); |
|
1828 |
Object x = 42; |
|
1829 |
for (int i = 0; i < okCount; i++) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1830 |
Object y = identity.invokeExact(x); |
4537 | 1831 |
assertEquals(x, y); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1832 |
Object z = surprise.invokeExact(x); |
4537 | 1833 |
assertEquals(x, z); |
1834 |
} |
|
1835 |
boo.boo("Boo!"); |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1836 |
Object y = identity.invokeExact(x); |
4537 | 1837 |
assertEquals(x, y); |
1838 |
try { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1839 |
Object z = surprise.invokeExact(x); |
4537 | 1840 |
System.out.println("Failed to throw; got z="+z); |
1841 |
assertTrue(false); |
|
1842 |
} catch (Exception ex) { |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1843 |
if (verbosity > 2) |
4537 | 1844 |
System.out.println("caught "+ex); |
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1845 |
if (verbosity > 3) |
4537 | 1846 |
ex.printStackTrace(); |
1847 |
assertTrue(ex instanceof ClassCastException |
|
1848 |
// FIXME: accept only one of the two for any given unit test |
|
1849 |
|| ex instanceof WrongMethodTypeException |
|
1850 |
); |
|
1851 |
} |
|
1852 |
} |
|
1853 |
||
4535 | 1854 |
} |
1855 |
// Local abbreviated copy of sun.dyn.util.ValueConversions |
|
1856 |
class ValueConversions { |
|
1857 |
private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); |
|
1858 |
private static final Object[] NO_ARGS_ARRAY = {}; |
|
1859 |
private static Object[] makeArray(Object... args) { return args; } |
|
1860 |
private static Object[] array() { return NO_ARGS_ARRAY; } |
|
1861 |
private static Object[] array(Object a0) |
|
1862 |
{ return makeArray(a0); } |
|
1863 |
private static Object[] array(Object a0, Object a1) |
|
1864 |
{ return makeArray(a0, a1); } |
|
1865 |
private static Object[] array(Object a0, Object a1, Object a2) |
|
1866 |
{ return makeArray(a0, a1, a2); } |
|
1867 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3) |
|
1868 |
{ return makeArray(a0, a1, a2, a3); } |
|
1869 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1870 |
Object a4) |
|
1871 |
{ return makeArray(a0, a1, a2, a3, a4); } |
|
1872 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1873 |
Object a4, Object a5) |
|
1874 |
{ return makeArray(a0, a1, a2, a3, a4, a5); } |
|
1875 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1876 |
Object a4, Object a5, Object a6) |
|
1877 |
{ return makeArray(a0, a1, a2, a3, a4, a5, a6); } |
|
1878 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1879 |
Object a4, Object a5, Object a6, Object a7) |
|
1880 |
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } |
|
1881 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1882 |
Object a4, Object a5, Object a6, Object a7, |
|
1883 |
Object a8) |
|
1884 |
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } |
|
1885 |
private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1886 |
Object a4, Object a5, Object a6, Object a7, |
|
1887 |
Object a8, Object a9) |
|
1888 |
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } |
|
1889 |
static MethodHandle[] makeArrays() { |
|
1890 |
ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>(); |
|
1891 |
MethodHandles.Lookup lookup = IMPL_LOOKUP; |
|
1892 |
for (;;) { |
|
1893 |
int nargs = arrays.size(); |
|
4537 | 1894 |
MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class); |
4535 | 1895 |
String name = "array"; |
1896 |
MethodHandle array = null; |
|
1897 |
try { |
|
1898 |
array = lookup.findStatic(ValueConversions.class, name, type); |
|
1899 |
} catch (NoAccessException ex) { |
|
1900 |
} |
|
1901 |
if (array == null) break; |
|
1902 |
arrays.add(array); |
|
1903 |
} |
|
1904 |
assert(arrays.size() == 11); // current number of methods |
|
1905 |
return arrays.toArray(new MethodHandle[0]); |
|
1906 |
} |
|
1907 |
static final MethodHandle[] ARRAYS = makeArrays(); |
|
1908 |
||
1909 |
/** Return a method handle that takes the indicated number of Object |
|
1910 |
* arguments and returns an Object array of them, as if for varargs. |
|
1911 |
*/ |
|
1912 |
public static MethodHandle varargsArray(int nargs) { |
|
1913 |
if (nargs < ARRAYS.length) |
|
1914 |
return ARRAYS[nargs]; |
|
1915 |
// else need to spin bytecode or do something else fancy |
|
5722
4ada807383c8
6939134: JSR 292 adjustments to method handle invocation
jrose
parents:
4537
diff
changeset
|
1916 |
throw new UnsupportedOperationException("NYI: cannot form a varargs array of length "+nargs); |
4535 | 1917 |
} |
4537 | 1918 |
|
1919 |
private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY); |
|
1920 |
private static List<Object> makeList(Object... args) { return Arrays.asList(args); } |
|
1921 |
private static List<Object> list() { return NO_ARGS_LIST; } |
|
1922 |
private static List<Object> list(Object a0) |
|
1923 |
{ return makeList(a0); } |
|
1924 |
private static List<Object> list(Object a0, Object a1) |
|
1925 |
{ return makeList(a0, a1); } |
|
1926 |
private static List<Object> list(Object a0, Object a1, Object a2) |
|
1927 |
{ return makeList(a0, a1, a2); } |
|
1928 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3) |
|
1929 |
{ return makeList(a0, a1, a2, a3); } |
|
1930 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
1931 |
Object a4) |
|
1932 |
{ return makeList(a0, a1, a2, a3, a4); } |
|
1933 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
1934 |
Object a4, Object a5) |
|
1935 |
{ return makeList(a0, a1, a2, a3, a4, a5); } |
|
1936 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
1937 |
Object a4, Object a5, Object a6) |
|
1938 |
{ return makeList(a0, a1, a2, a3, a4, a5, a6); } |
|
1939 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
1940 |
Object a4, Object a5, Object a6, Object a7) |
|
1941 |
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7); } |
|
1942 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
1943 |
Object a4, Object a5, Object a6, Object a7, |
|
1944 |
Object a8) |
|
1945 |
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); } |
|
1946 |
private static List<Object> list(Object a0, Object a1, Object a2, Object a3, |
|
1947 |
Object a4, Object a5, Object a6, Object a7, |
|
1948 |
Object a8, Object a9) |
|
1949 |
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } |
|
1950 |
static MethodHandle[] makeLists() { |
|
1951 |
ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>(); |
|
1952 |
MethodHandles.Lookup lookup = IMPL_LOOKUP; |
|
1953 |
for (;;) { |
|
1954 |
int nargs = arrays.size(); |
|
1955 |
MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class); |
|
1956 |
String name = "list"; |
|
1957 |
MethodHandle array = null; |
|
1958 |
try { |
|
1959 |
array = lookup.findStatic(ValueConversions.class, name, type); |
|
1960 |
} catch (NoAccessException ex) { |
|
1961 |
} |
|
1962 |
if (array == null) break; |
|
1963 |
arrays.add(array); |
|
1964 |
} |
|
1965 |
assert(arrays.size() == 11); // current number of methods |
|
1966 |
return arrays.toArray(new MethodHandle[0]); |
|
1967 |
} |
|
1968 |
static final MethodHandle[] LISTS = makeLists(); |
|
1969 |
||
1970 |
/** Return a method handle that takes the indicated number of Object |
|
1971 |
* arguments and returns List. |
|
1972 |
*/ |
|
1973 |
public static MethodHandle varargsList(int nargs) { |
|
1974 |
if (nargs < LISTS.length) |
|
1975 |
return LISTS[nargs]; |
|
1976 |
// else need to spin bytecode or do something else fancy |
|
1977 |
throw new UnsupportedOperationException("NYI"); |
|
1978 |
} |
|
4535 | 1979 |
} |
1980 |
// This guy tests access from outside the same package member, but inside |
|
1981 |
// the package itself. |
|
1982 |
class PackageSibling { |
|
1983 |
static Lookup lookup() { |
|
1984 |
return MethodHandles.lookup(); |
|
1985 |
} |
|
1986 |
} |