JDK-8078511 : Implement special invoker for MH.invokeWithArguments
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 9
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2015-04-23
  • Updated: 2017-01-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Related Reports
Relates :  
Consider implementing special invoker for MH.invokeWithArguments().

Right now, new invoker is created on every invocation. 

    public Object invokeWithArguments(Object... arguments) throws Throwable { 
        MethodType invocationType = MethodType.genericMethodType(arguments == null ? 0 : arguments.length); 
        return invocationType.invokers().spreadInvoker(0).invokeExact(asType(invocationType), arguments); 

It's still fast (only 5x slower than a direct call) because LambdaForm caching saves lots of work  in spreadInvoker(0) case. 
Maybe we need to extend the asType cache logic to cache a spreader also. Then we could inline through the spread adapter. This is how we make varargs calls go fast, at present. It would work for this case also. The challenge would be to overload the one-element cache on each MH. (And not build a second cache, unless we think the space is already allocated as frag. overhead.) The MH.type is a perfect key for this cache currently, and it could be overloaded with spreaders *if* the MH.type of the spreader is *never* a valid type for a MH.asType result. This is *often* true, but not *always* true, since, if a MH is untyped, a final Object argument might be an array to spread, or it might be a single non-spread trailing argument (and so on). Still, I think we can tweak something here.

No, there's no difference when replacing the invokeWithArguments implementation with the public API transformation I did in user code[1], the speedup comes from being able to do this in a setup step and cache the resulting MethodHandle in user code. Of course, a specialized invoker could remove the need for this trick. [1] return this.asSpreader(0, Object[].class, arguments.length).invoke(arguments);

Possibly related performance discussion: http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-January/010894.html The expressions `genericMethodType(arguments.length)` and `invocationType.invokers().spreadInvoker(0)` should not return different values for different, since they are designed to cache their results. Perhaps there is a failure to cache when the method handle `this` is adapted by the spread-invoker, during the course of the invocation of the spread-invoker.

There's no fundamental reason to specialize invoker for arguments array size, but perform arity check in invoker before calling a spreader.