/// <summary> /// The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help. /// It will make an up-call to this method. (Do not change the name or signature.) /// The type argument is a Class for field requests and a MethodType for non-fields. /// <para> /// Recent versions of the JVM may also pass a resolved MemberName for the type. /// In that case, the name is ignored and may be null. /// </para> /// </summary> internal static MethodHandle LinkMethodHandleConstant(Class callerClass, int refKind, Class defc, String name, Object type) { try { Lookup lookup = IMPL_LOOKUP.@in(callerClass); assert(RefKindIsValid(refKind)); return(lookup.linkMethodHandleConstant((sbyte)refKind, defc, name, type)); } catch (IllegalAccessException ex) { Throwable cause = ex.InnerException; if (cause is AbstractMethodError) { throw (AbstractMethodError)cause; } else { Error err = new IllegalAccessError(ex.Message); throw InitCauseFrom(err, ex); } } catch (NoSuchMethodException ex) { Error err = new NoSuchMethodError(ex.Message); throw InitCauseFrom(err, ex); } catch (NoSuchFieldException ex) { Error err = new NoSuchFieldError(ex.Message); throw InitCauseFrom(err, ex); } catch (ReflectiveOperationException ex) { Error err = new IncompatibleClassChangeError(); throw InitCauseFrom(err, ex); } }
// this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite: internal static CallSite MakeSite(MethodHandle bootstrapMethod, String name, MethodType type, Object info, Class callerClass) // Callee information: // Extra arguments for BSM, if any: // Caller information: { MethodHandles.Lookup caller = IMPL_LOOKUP.@in(callerClass); CallSite site; try { Object binding; info = MaybeReBox(info); if (info == null) { binding = bootstrapMethod.invoke(caller, name, type); } else if (!info.GetType().IsArray) { binding = bootstrapMethod.invoke(caller, name, type, info); } else { Object[] argv = (Object[])info; MaybeReBoxElements(argv); switch (argv.Length) { case 0: binding = bootstrapMethod.invoke(caller, name, type); break; case 1: binding = bootstrapMethod.invoke(caller, name, type, argv[0]); break; case 2: binding = bootstrapMethod.invoke(caller, name, type, argv[0], argv[1]); break; case 3: binding = bootstrapMethod.invoke(caller, name, type, argv[0], argv[1], argv[2]); break; case 4: binding = bootstrapMethod.invoke(caller, name, type, argv[0], argv[1], argv[2], argv[3]); break; case 5: binding = bootstrapMethod.invoke(caller, name, type, argv[0], argv[1], argv[2], argv[3], argv[4]); break; case 6: binding = bootstrapMethod.invoke(caller, name, type, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); break; default: const int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type) if (NON_SPREAD_ARG_COUNT + argv.Length > MethodType.MAX_MH_ARITY) { throw new BootstrapMethodError("too many bootstrap method arguments"); } MethodType bsmType = bootstrapMethod.Type(); MethodType invocationType = MethodType.GenericMethodType(NON_SPREAD_ARG_COUNT + argv.Length); MethodHandle typedBSM = bootstrapMethod.AsType(invocationType); MethodHandle spreader = invocationType.Invokers().SpreadInvoker(NON_SPREAD_ARG_COUNT); binding = spreader.invokeExact(typedBSM, (Object)caller, (Object)name, (Object)type, argv); break; } } //System.out.println("BSM for "+name+type+" => "+binding); if (binding is CallSite) { site = (CallSite)binding; } else { throw new ClassCastException("bootstrap method failed to produce a CallSite"); } if (!site.Target.Type().Equals(type)) { throw WrongTargetType(site.Target, type); } } catch (Throwable ex) { BootstrapMethodError bex; if (ex is BootstrapMethodError) { bex = (BootstrapMethodError)ex; } else { bex = new BootstrapMethodError("call site initialization exception", ex); } throw bex; } return(site); }