63 |
63 |
64 /** Tell the JVM that we need to change the target of a CallSite. */ |
64 /** Tell the JVM that we need to change the target of a CallSite. */ |
65 static native void setCallSiteTargetNormal(CallSite site, MethodHandle target); |
65 static native void setCallSiteTargetNormal(CallSite site, MethodHandle target); |
66 static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target); |
66 static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target); |
67 |
67 |
|
68 static native void copyOutBootstrapArguments(Class<?> caller, int[] indexInfo, |
|
69 int start, int end, |
|
70 Object[] buf, int pos, |
|
71 boolean resolve, |
|
72 Object ifNotAvailable); |
|
73 |
68 /** Represents a context to track nmethod dependencies on CallSite instance target. */ |
74 /** Represents a context to track nmethod dependencies on CallSite instance target. */ |
69 static class CallSiteContext implements Runnable { |
75 static class CallSiteContext implements Runnable { |
70 //@Injected JVM_nmethodBucket* vmdependencies; |
76 //@Injected JVM_nmethodBucket* vmdependencies; |
71 |
77 |
72 static CallSiteContext make(CallSite cs) { |
78 static CallSiteContext make(CallSite cs) { |
266 String name, MethodType type, |
273 String name, MethodType type, |
267 Object staticArguments, |
274 Object staticArguments, |
268 Object[] appendixResult) { |
275 Object[] appendixResult) { |
269 Object bsmReference = bootstrapMethod.internalMemberName(); |
276 Object bsmReference = bootstrapMethod.internalMemberName(); |
270 if (bsmReference == null) bsmReference = bootstrapMethod; |
277 if (bsmReference == null) bsmReference = bootstrapMethod; |
271 Object staticArglist = (staticArguments instanceof Object[] ? |
278 String staticArglist = staticArglistForTrace(staticArguments); |
272 java.util.Arrays.asList((Object[]) staticArguments) : |
|
273 staticArguments); |
|
274 System.out.println("linkCallSite "+caller.getName()+" "+ |
279 System.out.println("linkCallSite "+caller.getName()+" "+ |
275 bsmReference+" "+ |
280 bsmReference+" "+ |
276 name+type+"/"+staticArglist); |
281 name+type+"/"+staticArglist); |
277 try { |
282 try { |
278 MemberName res = linkCallSiteImpl(caller, bootstrapMethod, name, type, |
283 MemberName res = linkCallSiteImpl(caller, bootstrapMethod, name, type, |
279 staticArguments, appendixResult); |
284 staticArguments, appendixResult); |
280 System.out.println("linkCallSite => "+res+" + "+appendixResult[0]); |
285 System.out.println("linkCallSite => "+res+" + "+appendixResult[0]); |
281 return res; |
286 return res; |
282 } catch (Throwable ex) { |
287 } catch (Throwable ex) { |
|
288 ex.printStackTrace(); // print now in case exception is swallowed |
283 System.out.println("linkCallSite => throw "+ex); |
289 System.out.println("linkCallSite => throw "+ex); |
284 throw ex; |
290 throw ex; |
285 } |
291 } |
|
292 } |
|
293 |
|
294 // this implements the upcall from the JVM, MethodHandleNatives.linkDynamicConstant: |
|
295 static Object linkDynamicConstant(Object callerObj, |
|
296 int indexInCP, |
|
297 Object bootstrapMethodObj, |
|
298 Object nameObj, Object typeObj, |
|
299 Object staticArguments) { |
|
300 MethodHandle bootstrapMethod = (MethodHandle)bootstrapMethodObj; |
|
301 Class<?> caller = (Class<?>)callerObj; |
|
302 String name = nameObj.toString().intern(); |
|
303 Class<?> type = (Class<?>)typeObj; |
|
304 if (!TRACE_METHOD_LINKAGE) |
|
305 return linkDynamicConstantImpl(caller, bootstrapMethod, name, type, staticArguments); |
|
306 return linkDynamicConstantTracing(caller, bootstrapMethod, name, type, staticArguments); |
|
307 } |
|
308 |
|
309 static Object linkDynamicConstantImpl(Class<?> caller, |
|
310 MethodHandle bootstrapMethod, |
|
311 String name, Class<?> type, |
|
312 Object staticArguments) { |
|
313 return DynamicConstant.makeConstant(bootstrapMethod, name, type, staticArguments, caller); |
|
314 } |
|
315 |
|
316 private static String staticArglistForTrace(Object staticArguments) { |
|
317 if (staticArguments instanceof Object[]) |
|
318 return "BSA="+java.util.Arrays.asList((Object[]) staticArguments); |
|
319 if (staticArguments instanceof int[]) |
|
320 return "BSA@"+java.util.Arrays.toString((int[]) staticArguments); |
|
321 if (staticArguments == null) |
|
322 return "BSA0=null"; |
|
323 return "BSA1="+staticArguments; |
|
324 } |
|
325 |
|
326 // Tracing logic: |
|
327 static Object linkDynamicConstantTracing(Class<?> caller, |
|
328 MethodHandle bootstrapMethod, |
|
329 String name, Class<?> type, |
|
330 Object staticArguments) { |
|
331 Object bsmReference = bootstrapMethod.internalMemberName(); |
|
332 if (bsmReference == null) bsmReference = bootstrapMethod; |
|
333 String staticArglist = staticArglistForTrace(staticArguments); |
|
334 System.out.println("linkDynamicConstant "+caller.getName()+" "+ |
|
335 bsmReference+" "+ |
|
336 name+type+"/"+staticArglist); |
|
337 try { |
|
338 Object res = linkDynamicConstantImpl(caller, bootstrapMethod, name, type, staticArguments); |
|
339 System.out.println("linkDynamicConstantImpl => "+res); |
|
340 return res; |
|
341 } catch (Throwable ex) { |
|
342 ex.printStackTrace(); // print now in case exception is swallowed |
|
343 System.out.println("linkDynamicConstant => throw "+ex); |
|
344 throw ex; |
|
345 } |
|
346 } |
|
347 |
|
348 /** The JVM is requesting pull-mode bootstrap when it provides |
|
349 * a tuple of the form int[]{ argc, vmindex }. |
|
350 * The BSM is expected to call back to the JVM using the caller |
|
351 * class and vmindex to resolve the static arguments. |
|
352 */ |
|
353 static boolean staticArgumentsPulled(Object staticArguments) { |
|
354 return staticArguments instanceof int[]; |
|
355 } |
|
356 |
|
357 /** A BSM runs in pull-mode if and only if its sole arguments |
|
358 * are (Lookup, BootstrapCallInfo), or can be converted pairwise |
|
359 * to those types, and it is not of variable arity. |
|
360 * Excluding error cases, we can just test that the arity is a constant 2. |
|
361 * |
|
362 * NOTE: This method currently returns false, since pulling is not currently |
|
363 * exposed to a BSM. When pull mode is supported the method block will be |
|
364 * replaced with currently commented out code. |
|
365 */ |
|
366 static boolean isPullModeBSM(MethodHandle bsm) { |
|
367 return false; |
|
368 // return bsm.type().parameterCount() == 2 && !bsm.isVarargsCollector(); |
286 } |
369 } |
287 |
370 |
288 /** |
371 /** |
289 * The JVM wants a pointer to a MethodType. Oblige it by finding or creating one. |
372 * The JVM wants a pointer to a MethodType. Oblige it by finding or creating one. |
290 */ |
373 */ |
504 Class<?> defc, String name, Object type) { |
587 Class<?> defc, String name, Object type) { |
505 try { |
588 try { |
506 Lookup lookup = IMPL_LOOKUP.in(callerClass); |
589 Lookup lookup = IMPL_LOOKUP.in(callerClass); |
507 assert(refKindIsValid(refKind)); |
590 assert(refKindIsValid(refKind)); |
508 return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type); |
591 return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type); |
509 } catch (IllegalAccessException ex) { |
592 } catch (ReflectiveOperationException ex) { |
|
593 throw mapLookupExceptionToError(ex); |
|
594 } |
|
595 } |
|
596 |
|
597 /** |
|
598 * Map a reflective exception to a linkage error. |
|
599 */ |
|
600 static LinkageError mapLookupExceptionToError(ReflectiveOperationException ex) { |
|
601 LinkageError err; |
|
602 if (ex instanceof IllegalAccessException) { |
510 Throwable cause = ex.getCause(); |
603 Throwable cause = ex.getCause(); |
511 if (cause instanceof AbstractMethodError) { |
604 if (cause instanceof AbstractMethodError) { |
512 throw (AbstractMethodError) cause; |
605 return (AbstractMethodError) cause; |
513 } else { |
606 } else { |
514 Error err = new IllegalAccessError(ex.getMessage()); |
607 err = new IllegalAccessError(ex.getMessage()); |
515 throw initCauseFrom(err, ex); |
|
516 } |
608 } |
517 } catch (NoSuchMethodException ex) { |
609 } else if (ex instanceof NoSuchMethodException) { |
518 Error err = new NoSuchMethodError(ex.getMessage()); |
610 err = new NoSuchMethodError(ex.getMessage()); |
519 throw initCauseFrom(err, ex); |
611 } else if (ex instanceof NoSuchFieldException) { |
520 } catch (NoSuchFieldException ex) { |
612 err = new NoSuchFieldError(ex.getMessage()); |
521 Error err = new NoSuchFieldError(ex.getMessage()); |
613 } else { |
522 throw initCauseFrom(err, ex); |
614 err = new IncompatibleClassChangeError(); |
523 } catch (ReflectiveOperationException ex) { |
615 } |
524 Error err = new IncompatibleClassChangeError(); |
616 return initCauseFrom(err, ex); |
525 throw initCauseFrom(err, ex); |
|
526 } |
|
527 } |
617 } |
528 |
618 |
529 /** |
619 /** |
530 * Use best possible cause for err.initCause(), substituting the |
620 * Use best possible cause for err.initCause(), substituting the |
531 * cause for err itself if the cause has the same (or better) type. |
621 * cause for err itself if the cause has the same (or better) type. |
532 */ |
622 */ |
533 private static Error initCauseFrom(Error err, Exception ex) { |
623 static <E extends Error> E initCauseFrom(E err, Exception ex) { |
534 Throwable th = ex.getCause(); |
624 Throwable th = ex.getCause(); |
535 if (err.getClass().isInstance(th)) |
625 @SuppressWarnings("unchecked") |
536 return (Error) th; |
626 final Class<E> Eclass = (Class<E>) err.getClass(); |
|
627 if (Eclass.isInstance(th)) |
|
628 return Eclass.cast(th); |
537 err.initCause(th == null ? ex : th); |
629 err.initCause(th == null ? ex : th); |
538 return err; |
630 return err; |
539 } |
631 } |
540 |
632 |
541 /** |
633 /** |