Beispiel #1
0
        // 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);
        }