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