Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/lang/invoke/RicochetTest.java
47216 views
1
/*
2
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/* @test
25
* @summary unit tests for recursive method handles
26
* @run junit/othervm/timeout=3600 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -DRicochetTest.MAX_ARITY=10 test.java.lang.invoke.RicochetTest
27
*/
28
/*
29
* @ignore The following test creates an unreasonable number of adapters in -Xcomp mode (7049122)
30
* @run junit/othervm -DRicochetTest.MAX_ARITY=255 test.java.lang.invoke.RicochetTest
31
*/
32
33
package test.java.lang.invoke;
34
35
import java.lang.invoke.*;
36
import java.util.*;
37
import org.junit.*;
38
import static java.lang.invoke.MethodType.*;
39
import static java.lang.invoke.MethodHandles.*;
40
import static org.junit.Assert.*;
41
42
43
/**
44
*
45
* @author jrose
46
*/
47
public class RicochetTest {
48
private static final Class<?> CLASS = RicochetTest.class;
49
private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40);
50
51
public static void main(String... av) throws Throwable {
52
RicochetTest test = new RicochetTest();
53
if (av.length > 0) test.testOnly = Arrays.asList(av).toString();
54
if (REPEAT == 1 || test.testOnly != null) {
55
test.testAll();
56
if (test.testOnlyTests == null) throw new RuntimeException("no matching test: "+test.testOnly);
57
} else if (REPEAT == 0) {
58
org.junit.runner.JUnitCore.runClasses(RicochetTest.class);
59
} else {
60
verbose(1, "REPEAT="+REPEAT);
61
for (int i = 0; i < REPEAT; i++) {
62
test.testRepetition = (i+1);
63
verbose(0, "[#"+test.testRepetition+"]");
64
test.testAll();
65
}
66
}
67
}
68
int testRepetition;
69
70
public void testAll() throws Throwable {
71
testNull();
72
testBoxInteger();
73
testFilterReturnValue();
74
testFilterObject();
75
testBoxLong();
76
testFilterInteger();
77
testIntSpreads();
78
testByteSpreads();
79
testLongSpreads();
80
testIntCollects();
81
testReturns();
82
testRecursion();
83
}
84
85
@Test
86
public void testNull() throws Throwable {
87
if (testRepetition > (1+REPEAT/100)) return; // trivial test
88
if (!startTest("testNull")) return;
89
assertEquals(opI(37), opI.invokeWithArguments(37));
90
assertEqualFunction(opI, opI);
91
}
92
93
@Test
94
public void testBoxInteger() throws Throwable {
95
if (!startTest("testBoxInteger")) return;
96
assertEqualFunction(opI, opI.asType(opL_I.type()).asType(opI.type()));
97
}
98
99
@Test
100
public void testFilterReturnValue() throws Throwable {
101
if (!startTest("testFilterReturnValue")) return;
102
int[] ints = { 12, 23, 34, 45, 56, 67, 78, 89 };
103
Object res = list8ints.invokeExact(ints[0], ints[1], ints[2], ints[3], ints[4], ints[5], ints[6], ints[7]);
104
assertEquals(Arrays.toString(ints), res.toString());
105
MethodHandle idreturn = filterReturnValue(list8ints, identity(Object.class));
106
res = idreturn.invokeExact(ints[0], ints[1], ints[2], ints[3], ints[4], ints[5], ints[6], ints[7]);
107
assertEquals(Arrays.toString(ints), res.toString());
108
MethodHandle add0 = addL.bindTo(0);
109
assertEqualFunction(filterReturnValue(opL2, add0), opL2);
110
}
111
112
@Test
113
public void testFilterObject() throws Throwable {
114
if (!startTest("testFilterObject")) return;
115
MethodHandle add0 = addL.bindTo(0);
116
assertEqualFunction(sequence(opL2, add0), opL2);
117
int bump13 = -13; // value near 20 works as long as test values are near [-80..80]
118
MethodHandle add13 = addL.bindTo(bump13);
119
MethodHandle add13_0 = addL.bindTo(opI2(bump13, 0));
120
MethodHandle add13_1 = addL.bindTo(opI2(0, bump13));
121
assertEqualFunction(sequence(opL2, add13_0),
122
filterArguments(opL2, 0, add13));
123
assertEqualFunction(sequence(opL2, add13_1),
124
filterArguments(opL2, 1, add13));
125
System.out.println("[testFilterObject done]");
126
}
127
128
@Test
129
public void testBoxLong() throws Throwable {
130
if (!startTest("testBoxLong")) return;
131
assertEqualFunction(opJ, opJ.asType(opL_J.type()).asType(opJ.type()));
132
}
133
134
@Test
135
public void testFilterInteger() throws Throwable {
136
if (!startTest("testFilterInteger")) return;
137
assertEqualFunction(opI, sequence(convI_L, opL_I));
138
}
139
140
@Test
141
public void testIntSpreads() throws Throwable {
142
if (!startTest("testIntSpreads")) return;
143
MethodHandle id = identity(int[].class);
144
final int MAX = MAX_ARITY-2; // 253+1 would cause parameter overflow with 'this' added
145
for (int nargs = 0; nargs <= MAX; nargs++) {
146
if (nargs > 30 && nargs < MAX-20) nargs += 10;
147
int[] args = new int[nargs];
148
for (int j = 0; j < args.length; j++) args[j] = j + 11;
149
//System.out.println("testIntSpreads "+Arrays.toString(args));
150
int[] args1 = (int[]) id.invokeExact(args);
151
assertArrayEquals(args, args1);
152
MethodHandle coll = id.asCollector(int[].class, nargs);
153
int[] args2 = args;
154
switch (nargs) {
155
case 0: args2 = (int[]) coll.invokeExact(); break;
156
case 1: args2 = (int[]) coll.invokeExact(args[0]); break;
157
case 2: args2 = (int[]) coll.invokeExact(args[0], args[1]); break;
158
case 3: args2 = (int[]) coll.invokeExact(args[0], args[1], args[2]); break;
159
case 4: args2 = (int[]) coll.invokeExact(args[0], args[1], args[2], args[3]); break;
160
case 5: args2 = (int[]) coll.invokeExact(args[0], args[1], args[2], args[3], args[4]); break;
161
}
162
assertArrayEquals(args, args2);
163
MethodHandle mh = coll.asSpreader(int[].class, nargs);
164
int[] args3 = (int[]) mh.invokeExact(args);
165
assertArrayEquals(args, args3);
166
}
167
}
168
169
@Test
170
public void testByteSpreads() throws Throwable {
171
if (!startTest("testByteSpreads")) return;
172
MethodHandle id = identity(byte[].class);
173
final int MAX = MAX_ARITY-2; // 253+1 would cause parameter overflow with 'this' added
174
for (int nargs = 0; nargs <= MAX; nargs++) {
175
if (nargs > 30 && nargs < MAX-20) nargs += 10;
176
byte[] args = new byte[nargs];
177
for (int j = 0; j < args.length; j++) args[j] = (byte)(j + 11);
178
//System.out.println("testByteSpreads "+Arrays.toString(args));
179
byte[] args1 = (byte[]) id.invokeExact(args);
180
assertArrayEquals(args, args1);
181
MethodHandle coll = id.asCollector(byte[].class, nargs);
182
byte[] args2 = args;
183
switch (nargs) {
184
case 0: args2 = (byte[]) coll.invokeExact(); break;
185
case 1: args2 = (byte[]) coll.invokeExact(args[0]); break;
186
case 2: args2 = (byte[]) coll.invokeExact(args[0], args[1]); break;
187
case 3: args2 = (byte[]) coll.invokeExact(args[0], args[1], args[2]); break;
188
case 4: args2 = (byte[]) coll.invokeExact(args[0], args[1], args[2], args[3]); break;
189
case 5: args2 = (byte[]) coll.invokeExact(args[0], args[1], args[2], args[3], args[4]); break;
190
}
191
assertArrayEquals(args, args2);
192
MethodHandle mh = coll.asSpreader(byte[].class, nargs);
193
byte[] args3 = (byte[]) mh.invokeExact(args);
194
assertArrayEquals(args, args3);
195
}
196
}
197
198
@Test
199
public void testLongSpreads() throws Throwable {
200
if (!startTest("testLongSpreads")) return;
201
MethodHandle id = identity(long[].class);
202
final int MAX = (MAX_ARITY - 2) / 2; // 253/2+1 would cause parameter overflow with 'this' added
203
for (int nargs = 0; nargs <= MAX; nargs++) {
204
if (nargs > 30 && nargs < MAX-20) nargs += 10;
205
long[] args = new long[nargs];
206
for (int j = 0; j < args.length; j++) args[j] = (long)(j + 11);
207
//System.out.println("testLongSpreads "+Arrays.toString(args));
208
long[] args1 = (long[]) id.invokeExact(args);
209
assertArrayEquals(args, args1);
210
MethodHandle coll = id.asCollector(long[].class, nargs);
211
long[] args2 = args;
212
switch (nargs) {
213
case 0: args2 = (long[]) coll.invokeExact(); break;
214
case 1: args2 = (long[]) coll.invokeExact(args[0]); break;
215
case 2: args2 = (long[]) coll.invokeExact(args[0], args[1]); break;
216
case 3: args2 = (long[]) coll.invokeExact(args[0], args[1], args[2]); break;
217
case 4: args2 = (long[]) coll.invokeExact(args[0], args[1], args[2], args[3]); break;
218
case 5: args2 = (long[]) coll.invokeExact(args[0], args[1], args[2], args[3], args[4]); break;
219
}
220
assertArrayEquals(args, args2);
221
MethodHandle mh = coll.asSpreader(long[].class, nargs);
222
long[] args3 = (long[]) mh.invokeExact(args);
223
assertArrayEquals(args, args3);
224
}
225
}
226
227
@Test
228
public void testIntCollects() throws Throwable {
229
if (!startTest("testIntCollects")) return;
230
for (MethodHandle lister : INT_LISTERS) {
231
int outputs = lister.type().parameterCount();
232
for (int collects = 0; collects <= Math.min(outputs, INT_COLLECTORS.length-1); collects++) {
233
int inputs = outputs - 1 + collects;
234
if (inputs < 0) continue;
235
for (int pos = 0; pos + collects <= inputs; pos++) {
236
MethodHandle collector = INT_COLLECTORS[collects];
237
int[] args = new int[inputs];
238
int ap = 0, arg = 31;
239
for (int i = 0; i < pos; i++)
240
args[ap++] = arg++ + 0;
241
for (int i = 0; i < collects; i++)
242
args[ap++] = arg++ + 10;
243
while (ap < args.length)
244
args[ap++] = arg++ + 20;
245
// calculate piecemeal:
246
//System.out.println("testIntCollects "+Arrays.asList(lister, pos, collector)+" on "+Arrays.toString(args));
247
int[] collargs = Arrays.copyOfRange(args, pos, pos+collects);
248
int coll = (int) collector.asSpreader(int[].class, collargs.length).invokeExact(collargs);
249
int[] listargs = Arrays.copyOfRange(args, 0, outputs);
250
System.arraycopy(args, pos+collects, listargs, pos+1, outputs - (pos+1));
251
listargs[pos] = coll;
252
//System.out.println(" coll="+coll+" listargs="+Arrays.toString(listargs));
253
Object expect = lister.asSpreader(int[].class, listargs.length).invokeExact(listargs);
254
//System.out.println(" expect="+expect);
255
256
// now use the combined MH, and test the output:
257
MethodHandle mh = collectArguments(lister, pos, int[].class, INT_COLLECTORS[collects]);
258
if (mh == null) continue; // no infix collection, yet
259
assert(mh.type().parameterCount() == inputs);
260
Object observe = mh.asSpreader(int[].class, args.length).invokeExact(args);
261
assertEquals(expect, observe);
262
}
263
}
264
}
265
}
266
267
@Test
268
public void testByteCollects() throws Throwable {
269
if (!startTest("testByteCollects")) return;
270
for (MethodHandle lister : BYTE_LISTERS) {
271
int outputs = lister.type().parameterCount();
272
for (int collects = 0; collects <= Math.min(outputs, BYTE_COLLECTORS.length-1); collects++) {
273
int inputs = outputs - 1 + collects;
274
if (inputs < 0) continue;
275
for (int pos = 0; pos + collects <= inputs; pos++) {
276
MethodHandle collector = BYTE_COLLECTORS[collects];
277
byte[] args = new byte[inputs];
278
int ap = 0, arg = 31;
279
for (int i = 0; i < pos; i++)
280
args[ap++] = (byte)(arg++ + 0);
281
for (int i = 0; i < collects; i++)
282
args[ap++] = (byte)(arg++ + 10);
283
while (ap < args.length)
284
args[ap++] = (byte)(arg++ + 20);
285
// calculate piecemeal:
286
//System.out.println("testIntCollects "+Arrays.asList(lister, pos, collector)+" on "+Arrays.toString(args));
287
byte[] collargs = Arrays.copyOfRange(args, pos, pos+collects);
288
byte coll = (byte) collector.asSpreader(byte[].class, collargs.length).invokeExact(collargs);
289
byte[] listargs = Arrays.copyOfRange(args, 0, outputs);
290
System.arraycopy(args, pos+collects, listargs, pos+1, outputs - (pos+1));
291
listargs[pos] = coll;
292
//System.out.println(" coll="+coll+" listargs="+Arrays.toString(listargs));
293
Object expect = lister.asSpreader(byte[].class, listargs.length).invokeExact(listargs);
294
//System.out.println(" expect="+expect);
295
296
// now use the combined MH, and test the output:
297
MethodHandle mh = collectArguments(lister, pos, byte[].class, BYTE_COLLECTORS[collects]);
298
if (mh == null) continue; // no infix collection, yet
299
assert(mh.type().parameterCount() == inputs);
300
Object observe = mh.asSpreader(byte[].class, args.length).invokeExact(args);
301
assertEquals(expect, observe);
302
}
303
}
304
}
305
}
306
307
private static MethodHandle collectArguments(MethodHandle lister, int pos, Class<?> array, MethodHandle collector) {
308
int collects = collector.type().parameterCount();
309
int outputs = lister.type().parameterCount();
310
if (pos == outputs - 1)
311
return MethodHandles.filterArguments(lister, pos,
312
collector.asSpreader(array, collects))
313
.asCollector(array, collects);
314
//return MethodHandles.collectArguments(lister, pos, collector); //no such animal
315
return null;
316
}
317
318
private static final Class<?>[] RETURN_TYPES = {
319
Object.class, String.class, Integer.class,
320
int.class, long.class,
321
boolean.class, byte.class, char.class, short.class,
322
float.class, double.class,
323
void.class,
324
};
325
326
@Test
327
public void testReturns() throws Throwable {
328
if (!startTest("testReturns")) return;
329
// fault injection:
330
int faultCount = 0; // total of 1296 tests
331
faultCount = Integer.getInteger("testReturns.faultCount", 0);
332
for (Class<?> ret : RETURN_TYPES) {
333
// make a complicated identity function and pass something through it
334
System.out.println(ret.getSimpleName());
335
Class<?> vret = (ret == void.class) ? Void.class : ret;
336
MethodHandle id = // (vret)->ret
337
identity(vret).asType(methodType(ret, vret));
338
final int LENGTH = 4;
339
int[] index = {0};
340
Object vals = java.lang.reflect.Array.newInstance(vret, LENGTH);
341
MethodHandle indexGetter = //()->int
342
insertArguments(arrayElementGetter(index.getClass()), 0, index, 0);
343
MethodHandle valSelector = // (int)->vret
344
arrayElementGetter(vals.getClass()).bindTo(vals);
345
MethodHandle valGetter = // ()->vret
346
foldArguments(valSelector, indexGetter);
347
if (ret != void.class) {
348
for (int i = 0; i < LENGTH; i++) {
349
Object val = (i + 50);
350
if (ret == boolean.class) val = (i % 3 == 0);
351
if (ret == String.class) val = "#"+i;
352
if (ret == char.class) val = (char)('a'+i);
353
if (ret == byte.class) val = (byte)~i;
354
if (ret == short.class) val = (short)(1<<i);
355
java.lang.reflect.Array.set(vals, i, val);
356
}
357
}
358
for (int i = 0; i < LENGTH; i++) {
359
Object val = java.lang.reflect.Array.get(vals, i);
360
System.out.println(i+" => "+val);
361
index[0] = i;
362
if (--faultCount == 0) index[0] ^= 1;
363
Object x = valGetter.invokeWithArguments();
364
assertEquals(val, x);
365
// make a return-filter call: x = id(valGetter())
366
if (--faultCount == 0) index[0] ^= 1;
367
x = filterReturnValue(valGetter, id).invokeWithArguments();
368
assertEquals(val, x);
369
// make a filter call: x = id(*,valGetter(),*)
370
for (int len = 1; len <= 4; len++) {
371
for (int pos = 0; pos < len; pos++) {
372
MethodHandle proj = id; // lambda(..., vret x,...){x}
373
for (int j = 0; j < len; j++) {
374
if (j == pos) continue;
375
proj = dropArguments(proj, j, Object.class);
376
}
377
assert(proj.type().parameterCount() == len);
378
// proj: (Object*, pos: vret, Object*)->ret
379
assertEquals(vret, proj.type().parameterType(pos));
380
MethodHandle vgFilter = dropArguments(valGetter, 0, Object.class);
381
if (--faultCount == 0) index[0] ^= 1;
382
x = filterArguments(proj, pos, vgFilter).invokeWithArguments(new Object[len]);
383
assertEquals(val, x);
384
}
385
}
386
// make a fold call:
387
for (int len = 0; len <= 4; len++) {
388
for (int fold = 0; fold <= len; fold++) {
389
MethodHandle proj = id; // lambda(ret x, ...){x}
390
if (ret == void.class) proj = constant(Object.class, null);
391
int arg0 = (ret == void.class ? 0 : 1);
392
for (int j = 0; j < len; j++) {
393
proj = dropArguments(proj, arg0, Object.class);
394
}
395
assert(proj.type().parameterCount() == arg0 + len);
396
// proj: (Object*, pos: vret, Object*)->ret
397
if (arg0 != 0) assertEquals(vret, proj.type().parameterType(0));
398
MethodHandle vgFilter = valGetter.asType(methodType(ret));
399
for (int j = 0; j < fold; j++) {
400
vgFilter = dropArguments(vgFilter, j, Object.class);
401
}
402
x = foldArguments(proj, vgFilter).invokeWithArguments(new Object[len]);
403
if (--faultCount == 0) index[0] ^= 1;
404
assertEquals(val, x);
405
}
406
}
407
}
408
}
409
//System.out.println("faultCount="+faultCount);
410
}
411
412
@Test
413
public void testRecursion() throws Throwable {
414
if (!startTest("testRecursion")) return;
415
final int LIMIT = 10;
416
for (int i = 0; i < LIMIT; i++) {
417
RFCB rfcb = new RFCB(i);
418
Object x = "x", y = "y";
419
Object result = rfcb.recursiveFunction(x, y);
420
verbose(1, result);
421
}
422
}
423
/** Recursive Function Control Block */
424
private static class RFCB {
425
java.util.Random random;
426
final MethodHandle[] fns;
427
int depth;
428
@SuppressWarnings("LeakingThisInConstructor")
429
RFCB(int seed) throws Throwable {
430
this.random = new java.util.Random(seed);
431
this.fns = new MethodHandle[Math.max(29, (1 << MAX_DEPTH-2)/3)];
432
java.util.Arrays.fill(fns, lookup().bind(this, "recursiveFunction", genericMethodType(2)));
433
for (int i = 5; i < fns.length; i++) {
434
switch (i % 4) {
435
case 0: fns[i] = filterArguments(fns[i - 5], 0, insertArguments(fns[i - 4], 1, ".")); break;
436
case 1: fns[i] = filterArguments(fns[i - 5], 1, insertArguments(fns[i - 3], 1, ".")); break;
437
case 2: fns[i] = filterReturnValue(fns[i - 5], insertArguments(fns[i - 2], 1, ".")); break;
438
}
439
}
440
}
441
Object recursiveFunction(Object x, Object y) throws Throwable {
442
depth++;
443
try {
444
final int ACTION_COUNT = 11;
445
switch (random.nextInt(ACTION_COUNT)) {
446
case 1:
447
Throwable ex = new RuntimeException();
448
ex.fillInStackTrace();
449
if (VERBOSITY >= 2) ex.printStackTrace(System.out);
450
x = "ST; " + x;
451
break;
452
case 2:
453
System.gc();
454
x = "GC; " + x;
455
break;
456
}
457
boolean isLeaf = (depth >= MAX_DEPTH);
458
if (isLeaf) {
459
return Arrays.asList(x, y).toString();
460
}
461
return fns[random.nextInt(fns.length)].invokeExact(x, y);
462
} finally {
463
depth--;
464
}
465
}
466
}
467
468
private static MethodHandle sequence(MethodHandle mh1, MethodHandle... mhs) {
469
MethodHandle res = mh1;
470
for (MethodHandle mh2 : mhs)
471
res = filterReturnValue(res, mh2);
472
return res;
473
}
474
private static void assertEqualFunction(MethodHandle x, MethodHandle y) throws Throwable {
475
assertEquals(x.type(), y.type()); //??
476
MethodType t = x.type();
477
if (t.parameterCount() == 0) {
478
assertEqualFunctionAt(null, x, y);
479
return;
480
}
481
Class<?> ptype = t.parameterType(0);
482
if (ptype == long.class || ptype == Long.class) {
483
for (long i = -10; i <= 10; i++) {
484
assertEqualFunctionAt(i, x, y);
485
}
486
} else {
487
for (int i = -10; i <= 10; i++) {
488
assertEqualFunctionAt(i, x, y);
489
}
490
}
491
}
492
private static void assertEqualFunctionAt(Object v, MethodHandle x, MethodHandle y) throws Throwable {
493
Object[] args = new Object[x.type().parameterCount()];
494
Arrays.fill(args, v);
495
Object xval = invokeWithCatch(x, args);
496
Object yval = invokeWithCatch(y, args);
497
String msg = "ok";
498
if (!Objects.equals(xval, yval)) {
499
msg = ("applying "+x+" & "+y+" to "+v);
500
}
501
assertEquals(msg, xval, yval);
502
}
503
private static Object invokeWithCatch(MethodHandle mh, Object... args) throws Throwable {
504
try {
505
return mh.invokeWithArguments(args);
506
} catch (Throwable ex) {
507
System.out.println("threw: "+mh+Arrays.asList(args));
508
ex.printStackTrace(System.out);
509
return ex;
510
}
511
}
512
513
private static final Lookup LOOKUP = lookup();
514
private static MethodHandle findStatic(String name,
515
Class<?> rtype,
516
Class<?>... ptypes) {
517
try {
518
return LOOKUP.findStatic(LOOKUP.lookupClass(), name, methodType(rtype, ptypes));
519
} catch (ReflectiveOperationException ex) {
520
throw new RuntimeException(ex);
521
}
522
}
523
private static MethodHandle findStatic(String name,
524
Class<?> rtype,
525
List<?> ptypes) {
526
return findStatic(name, rtype, ptypes.toArray(new Class<?>[ptypes.size()]));
527
}
528
static int getProperty(String name, int dflt) {
529
String qual = LOOKUP.lookupClass().getName();
530
String prop = System.getProperty(qual+"."+name);
531
if (prop == null) prop = System.getProperty(name);
532
if (prop == null) return dflt;
533
return Integer.parseInt(prop);
534
}
535
536
private static int opI(int... xs) {
537
stress();
538
int base = 100;
539
int z = 0;
540
for (int x : xs) {
541
z = (z * base) + (x % base);
542
}
543
verbose("opI", xs.length, xs, z);
544
return z;
545
}
546
private static int opI2(int x, int y) { return opI(x, y); } // x*100 + y%100
547
private static int opI3(int x, int y, int z) { return opI(x, y, z); }
548
private static int opI4(int w, int x, int y, int z) { return opI(w, x, y, z); }
549
private static int opI(int x) { return opI2(x, 37); }
550
private static Object opI_L(int x) { return (Object) opI(x); }
551
private static long opJ3(long x, long y, long z) { return (long) opI3((int)x, (int)y, (int)z); }
552
private static long opJ2(long x, long y) { return (long) opI2((int)x, (int)y); }
553
private static long opJ(long x) { return (long) opI((int)x); }
554
private static Object opL2(Object x, Object y) { return (Object) opI2((int)x, (int)y); }
555
private static Object opL(Object x) { return (Object) opI((int)x); }
556
private static int opL2_I(Object x, Object y) { return opI2((int)x, (int)y); }
557
private static int opL_I(Object x) { return opI((int)x); }
558
private static long opL_J(Object x) { return (long) opI((int)x); }
559
private static final MethodHandle opI, opI2, opI3, opI4, opI_L, opJ, opJ2, opJ3, opL2, opL, opL2_I, opL_I, opL_J;
560
static {
561
opI4 = findStatic("opI4", int.class, int.class, int.class, int.class, int.class);
562
opI3 = findStatic("opI3", int.class, int.class, int.class, int.class);
563
opI2 = findStatic("opI2", int.class, int.class, int.class);
564
opI = findStatic("opI", int.class, int.class);
565
opI_L = findStatic("opI_L", Object.class, int.class);
566
opJ = findStatic("opJ", long.class, long.class);
567
opJ2 = findStatic("opJ2", long.class, long.class, long.class);
568
opJ3 = findStatic("opJ3", long.class, long.class, long.class, long.class);
569
opL2 = findStatic("opL2", Object.class, Object.class, Object.class);
570
opL = findStatic("opL", Object.class, Object.class);
571
opL2_I = findStatic("opL2_I", int.class, Object.class, Object.class);
572
opL_I = findStatic("opL_I", int.class, Object.class);
573
opL_J = findStatic("opL_J", long.class, Object.class);
574
}
575
private static final MethodHandle[] INT_COLLECTORS = {
576
constant(int.class, 42), opI, opI2, opI3, opI4
577
};
578
private static final MethodHandle[] BYTE_COLLECTORS = {
579
constant(byte.class, (byte)42), i2b(opI), i2b(opI2), i2b(opI3), i2b(opI4)
580
};
581
private static final MethodHandle[] LONG_COLLECTORS = {
582
constant(long.class, 42), opJ, opJ2, opJ3
583
};
584
585
private static int addI(int x, int y) { stress(); return x+y; }
586
private static Object addL(Object x, Object y) { return addI((int)x, (int)y); }
587
private static final MethodHandle addI, addL;
588
static {
589
addI = findStatic("addI", int.class, int.class, int.class);
590
addL = findStatic("addL", Object.class, Object.class, Object.class);
591
}
592
593
private static Object list8ints(int a, int b, int c, int d, int e, int f, int g, int h) {
594
return Arrays.asList(a, b, c, d, e, f, g, h);
595
}
596
private static Object list8longs(long a, long b, long c, long d, long e, long f, long g, long h) {
597
return Arrays.asList(a, b, c, d, e, f, g, h);
598
}
599
private static final MethodHandle list8ints = findStatic("list8ints", Object.class,
600
Collections.nCopies(8, int.class));
601
private static final MethodHandle list8longs = findStatic("list8longs", Object.class,
602
Collections.nCopies(8, long.class));
603
private static final MethodHandle[] INT_LISTERS, LONG_LISTERS, BYTE_LISTERS;
604
static {
605
int listerCount = list8ints.type().parameterCount() + 1;
606
INT_LISTERS = new MethodHandle[listerCount];
607
LONG_LISTERS = new MethodHandle[listerCount];
608
BYTE_LISTERS = new MethodHandle[listerCount];
609
MethodHandle lister = list8ints;
610
MethodHandle llister = list8longs;
611
for (int i = listerCount - 1; ; i--) {
612
INT_LISTERS[i] = lister;
613
LONG_LISTERS[i] = llister;
614
BYTE_LISTERS[i] = i2b(lister);
615
if (i == 0) break;
616
lister = insertArguments(lister, i-1, 0);
617
llister = insertArguments(llister, i-1, 0L);
618
}
619
}
620
private static MethodHandle i2b(MethodHandle mh) {
621
return MethodHandles.explicitCastArguments(mh, subst(mh.type(), int.class, byte.class));
622
}
623
private static MethodType subst(MethodType mt, Class<?> from, Class<?> to) {
624
for (int i = 0; i < mt.parameterCount(); i++) {
625
if (mt.parameterType(i) == from)
626
mt = mt.changeParameterType(i, to);
627
}
628
if (mt.returnType() == from)
629
mt = mt.changeReturnType(to);
630
return mt;
631
}
632
633
634
private static Object convI_L(int x) { stress(); return (Object) x; }
635
private static int convL_I(Object x) { stress(); return (int) x; }
636
private static Object convJ_L(long x) { stress(); return (Object) x; }
637
private static long convL_J(Object x) { stress(); return (long) x; }
638
private static int convJ_I(long x) { stress(); return (int) x; }
639
private static long convI_J(int x) { stress(); return (long) x; }
640
private static final MethodHandle convI_L, convL_I, convJ_L, convL_J, convJ_I, convI_J;
641
static {
642
convI_L = findStatic("convI_L", Object.class, int.class);
643
convL_I = findStatic("convL_I", int.class, Object.class);
644
convJ_L = findStatic("convJ_L", Object.class, long.class);
645
convL_J = findStatic("convL_J", long.class, Object.class);
646
convJ_I = findStatic("convJ_I", int.class, long.class);
647
convI_J = findStatic("convI_J", long.class, int.class);
648
}
649
650
// stress modes:
651
private static final int MAX_DEPTH = getProperty("MAX_DEPTH", 5);
652
private static final int REPEAT = getProperty("REPEAT", 0);
653
private static final int STRESS = getProperty("STRESS", 0);
654
private static /*v*/ int STRESS_COUNT;
655
private static final Object[] SINK = new Object[4];
656
private static void stress() {
657
if (STRESS <= 0) return;
658
int count = STRESS + (STRESS_COUNT++ & 0x1); // non-constant value
659
for (int i = 0; i < count; i++) {
660
SINK[i % SINK.length] = new Object[STRESS + i % (SINK.length + 1)];
661
}
662
}
663
664
// verbosity:
665
private static final int VERBOSITY = getProperty("VERBOSITY", 0) + (REPEAT == 0 ? 0 : -1);
666
private static void verbose(Object a, Object b, Object c, Object d) {
667
if (VERBOSITY <= 0) return;
668
verbose(1, a, b, c, d);
669
}
670
private static void verbose(Object a, Object b, Object c) {
671
if (VERBOSITY <= 0) return;
672
verbose(1, a, b, c);
673
}
674
private static void verbose(int level, Object a, Object... bcd) {
675
if (level > VERBOSITY) return;
676
String m = a.toString();
677
if (bcd != null && bcd.length > 0) {
678
List<Object> l = new ArrayList<>(bcd.length);
679
for (Object x : bcd) {
680
if (x instanceof Object[]) x = Arrays.asList((Object[])x);
681
if (x instanceof int[]) x = Arrays.toString((int[])x);
682
if (x instanceof long[]) x = Arrays.toString((long[])x);
683
l.add(x);
684
}
685
m = m+Arrays.asList(bcd);
686
}
687
System.out.println(m);
688
}
689
String testOnly;
690
String testOnlyTests;
691
private boolean startTest(String name) {
692
if (testOnly != null && !testOnly.contains(name))
693
return false;
694
verbose(0, "["+name+"]");
695
testOnlyTests = (testOnlyTests == null) ? name : testOnlyTests+" "+name;
696
return true;
697
}
698
699
}
700
701