311 if (TRACE_METHOD_LINKAGE) |
313 if (TRACE_METHOD_LINKAGE) |
312 System.out.println("pull-mode BSM gets pushed arguments from fake BSCI"); |
314 System.out.println("pull-mode BSM gets pushed arguments from fake BSCI"); |
313 return pullModeBSM.invoke(lookup, bsci); |
315 return pullModeBSM.invoke(lookup, bsci); |
314 } |
316 } |
315 |
317 |
316 // skeleton for pull-mode BSM which wraps a push-mode BSM: |
|
317 static Object pullFromBootstrapMethod(MethodHandle pushModeBSM, |
|
318 MethodHandles.Lookup lookup, BootstrapCallInfo<?> bsci) |
|
319 throws Throwable { |
|
320 int argc = bsci.size(); |
|
321 Object arguments[] = new Object[3 + argc]; |
|
322 arguments[0] = lookup; |
|
323 arguments[1] = bsci.invocationName(); |
|
324 arguments[2] = bsci.invocationType(); |
|
325 bsci.copyConstants(0, argc, arguments, 3); |
|
326 if (TRACE_METHOD_LINKAGE) |
|
327 System.out.println("pulled arguments from VM for push-mode BSM"); |
|
328 return pushModeBSM.invokeWithArguments(arguments); |
|
329 } |
|
330 static final MethodHandle MH_pushToBootstrapMethod; |
318 static final MethodHandle MH_pushToBootstrapMethod; |
331 static final MethodHandle MH_pullFromBootstrapMethod; |
|
332 static { |
319 static { |
333 final Class<?> THIS_CLASS = Adapters.class; |
320 final Class<?> THIS_CLASS = PushAdapter.class; |
334 try { |
321 try { |
335 MH_pushToBootstrapMethod = IMPL_LOOKUP |
322 MH_pushToBootstrapMethod = IMPL_LOOKUP |
336 .findStatic(THIS_CLASS, "pushToBootstrapMethod", |
323 .findStatic(THIS_CLASS, "pushToBootstrapMethod", |
337 MethodType.methodType(Object.class, MethodHandle.class, |
324 MethodType.methodType(Object.class, MethodHandle.class, |
338 Lookup.class, String.class, Object.class, Object[].class)); |
325 Lookup.class, String.class, Object.class, Object[].class)); |
|
326 } catch (Throwable ex) { |
|
327 throw new InternalError(ex); |
|
328 } |
|
329 } |
|
330 } |
|
331 |
|
332 /*non-public*/ static final |
|
333 class PullAdapter { |
|
334 // skeleton for pull-mode BSM which wraps a push-mode BSM: |
|
335 static Object pullFromBootstrapMethod(MethodHandle pushModeBSM, |
|
336 MethodHandles.Lookup lookup, |
|
337 BootstrapCallInfo<?> bsci) |
|
338 throws Throwable { |
|
339 int argc = bsci.size(); |
|
340 switch (argc) { |
|
341 case 0: |
|
342 return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType()); |
|
343 case 1: |
|
344 return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(), |
|
345 bsci.get(0)); |
|
346 case 2: |
|
347 return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(), |
|
348 bsci.get(0), bsci.get(1)); |
|
349 case 3: |
|
350 return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(), |
|
351 bsci.get(0), bsci.get(1), bsci.get(2)); |
|
352 case 4: |
|
353 return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(), |
|
354 bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3)); |
|
355 case 5: |
|
356 return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(), |
|
357 bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3), bsci.get(4)); |
|
358 case 6: |
|
359 return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(), |
|
360 bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3), bsci.get(4), bsci.get(5)); |
|
361 default: |
|
362 final int NON_SPREAD_ARG_COUNT = 3; // (lookup, name, type) |
|
363 final int MAX_SAFE_SIZE = MethodType.MAX_MH_ARITY / 2 - NON_SPREAD_ARG_COUNT; |
|
364 if (argc >= MAX_SAFE_SIZE) { |
|
365 // to be on the safe side, use invokeWithArguments which handles jumbo lists |
|
366 Object[] newargv = new Object[NON_SPREAD_ARG_COUNT + argc]; |
|
367 newargv[0] = lookup; |
|
368 newargv[1] = bsci.invocationName(); |
|
369 newargv[2] = bsci.invocationType(); |
|
370 bsci.copyConstants(0, argc, newargv, NON_SPREAD_ARG_COUNT); |
|
371 return pushModeBSM.invokeWithArguments(newargv); |
|
372 } |
|
373 MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argc); |
|
374 MethodHandle typedBSM = pushModeBSM.asType(invocationType); |
|
375 MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT); |
|
376 Object[] argv = new Object[argc]; |
|
377 bsci.copyConstants(0, argc, argv, 0); |
|
378 return spreader.invokeExact(typedBSM, (Object) lookup, (Object) bsci.invocationName(), bsci.invocationType(), argv); |
|
379 } |
|
380 } |
|
381 |
|
382 static final MethodHandle MH_pullFromBootstrapMethod; |
|
383 |
|
384 static { |
|
385 final Class<?> THIS_CLASS = PullAdapter.class; |
|
386 try { |
339 MH_pullFromBootstrapMethod = IMPL_LOOKUP |
387 MH_pullFromBootstrapMethod = IMPL_LOOKUP |
340 .findStatic(THIS_CLASS, "pullFromBootstrapMethod", |
388 .findStatic(THIS_CLASS, "pullFromBootstrapMethod", |
341 MethodType.methodType(Object.class, MethodHandle.class, |
389 MethodType.methodType(Object.class, MethodHandle.class, |
342 Lookup.class, BootstrapCallInfo.class)); |
390 Lookup.class, BootstrapCallInfo.class)); |
343 } catch (Throwable ex) { |
391 } catch (Throwable ex) { |
344 throw new InternalError(ex); |
392 throw new InternalError(ex); |
345 } |
393 } |
346 } |
394 } |
347 |
395 } |
348 /** Given a push-mode BSM (taking one argument) convert it to a |
396 |
349 * pull-mode BSM (taking N pre-resolved arguments). |
397 /** Given a push-mode BSM (taking one argument) convert it to a |
350 * This method is used when, in fact, the JVM is passing up |
398 * pull-mode BSM (taking N pre-resolved arguments). |
351 * pre-resolved arguments, but the BSM is expecting lazy stuff. |
399 * This method is used when, in fact, the JVM is passing up |
352 * Or, when goToPushMode is true, do the reverse transform. |
400 * pre-resolved arguments, but the BSM is expecting lazy stuff. |
353 * (The two transforms are exactly inverse.) |
401 * Or, when goToPushMode is true, do the reverse transform. |
354 */ |
402 * (The two transforms are exactly inverse.) |
355 static MethodHandle pushMePullYou(MethodHandle bsm, boolean goToPushMode) { |
403 */ |
356 if (TRACE_METHOD_LINKAGE) |
404 static MethodHandle pushMePullYou(MethodHandle bsm, boolean goToPushMode) { |
357 System.out.println("converting BSM to "+(goToPushMode ? "push mode" : "pull mode")); |
405 if (TRACE_METHOD_LINKAGE) { |
358 assert(isPullModeBSM(bsm) == goToPushMode); //there must be a change |
406 System.out.println("converting BSM of type " + bsm.type() + " to " |
359 if (goToPushMode) { |
407 + (goToPushMode ? "push mode" : "pull mode")); |
360 return Adapters.MH_pushToBootstrapMethod.bindTo(bsm).withVarargs(true); |
408 } |
361 } else { |
409 assert(isPullModeBSM(bsm) == goToPushMode); // there must be a change |
362 return Adapters.MH_pullFromBootstrapMethod.bindTo(bsm).withVarargs(false); |
410 if (goToPushMode) { |
363 } |
411 return PushAdapter.MH_pushToBootstrapMethod.bindTo(bsm).withVarargs(true); |
|
412 } else { |
|
413 return PullAdapter.MH_pullFromBootstrapMethod.bindTo(bsm).withVarargs(false); |
364 } |
414 } |
365 } |
415 } |
366 } |
416 } |