--- old/src/share/classes/java/lang/invoke/CallSite.java 2013-09-11 17:58:26.885722951 +0400 +++ new/src/share/classes/java/lang/invoke/CallSite.java 2013-09-11 17:58:26.717722943 +0400 @@ -261,35 +261,40 @@ Object info, // Caller information: Class callerClass) { - Object caller = IMPL_LOOKUP.in(callerClass); - CallSite site; + MethodHandles.Lookup caller = IMPL_LOOKUP.in(callerClass); try { - Object binding; - info = maybeReBox(info); - if (info == null) { - binding = bootstrapMethod.invoke(caller, name, type); - } else if (!info.getClass().isArray()) { - binding = bootstrapMethod.invoke(caller, name, type, info); - } else { + CallSite site; + if(isLambdaMetafactory(bootstrapMethod, info)) { // LambdaMetafactory fastpath Object[] argv = (Object[]) info; - maybeReBoxElements(argv); - if (3 + argv.length > 255) - throw new BootstrapMethodError("too many bootstrap method arguments"); - MethodType bsmType = bootstrapMethod.type(); - if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class) - binding = bootstrapMethod.invoke(caller, name, type, argv); - else - binding = MethodHandles.spreadInvoker(bsmType, 3) - .invoke(bootstrapMethod, caller, name, type, argv); - } - //System.out.println("BSM for "+name+type+" => "+binding); - if (binding instanceof CallSite) { - site = (CallSite) binding; - } else { - throw new ClassCastException("bootstrap method failed to produce a CallSite"); + site = LambdaMetafactory.metafactory(caller, name, type, (MethodType)argv[0], (MethodHandle)argv[1], (MethodType)argv[2]); + } else { + Object binding; + info = maybeReBox(info); + if (info == null) { + binding = bootstrapMethod.invoke(caller, name, type); + } else if (!info.getClass().isArray()) { + binding = bootstrapMethod.invoke(caller, name, type, info); + } else { + Object[] argv = (Object[]) info; + maybeReBoxElements(argv); + if (3 + argv.length > 255) + throw new BootstrapMethodError("too many bootstrap method arguments"); + MethodType bsmType = bootstrapMethod.type(); + if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class) + binding = bootstrapMethod.invoke(caller, name, type, argv); + else + binding = MethodHandles.spreadInvoker(bsmType, 3) + .invoke(bootstrapMethod, caller, name, type, argv); + } + if (binding instanceof CallSite) { + site = (CallSite) binding; + } else { + throw new ClassCastException("bootstrap method failed to produce a CallSite"); + } } if (!site.getTarget().type().equals(type)) throw new WrongMethodTypeException("wrong type: "+site.getTarget()); + return site; } catch (Throwable ex) { BootstrapMethodError bex; if (ex instanceof BootstrapMethodError) @@ -298,7 +303,24 @@ bex = new BootstrapMethodError("call site initialization exception", ex); throw bex; } - return site; + + } + + private static boolean isLambdaMetafactory(MethodHandle mh, Object info) { + MemberName mn = mh.internalMemberName(); + if ((mn != null) && + (mn.getDeclaringClass().equals(LambdaMetafactory.class)) && + (mn.getName().equals("metafactory")) && + (mn.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeStatic) && + (info instanceof Object[])) { + Object[] argv = (Object[]) info; + // checks info inconsistency -> let's slowpath throws all exceptions + return (argv.length == 3) && + (argv[0] instanceof MethodType) && + (argv[1] instanceof MethodHandle) && + (argv[2] instanceof MethodType); + } + return false; } private static Object maybeReBox(Object x) {