RFR: 8264288: Performance issue with MethodHandle.asCollector [v3]

Jorn Vernee jvernee at openjdk.java.net
Mon Apr 5 12:03:08 UTC 2021


On Fri, 2 Apr 2021 13:23:07 GMT, Jorn Vernee <jvernee at openjdk.org> wrote:

>> That's an elegant solution.
>> 
>> At first i thought it might unduly perturb lambda form generation and caching. but you slotted a different lambda form implementation underneath the varargs implementation.
>
> I've addressed review comments, plus some other things:
> 
> - I realized that I was calling the uncached version of the store function factory. Fixed that.
> - I also realized that there's already an `ARRAY_STORE` intrinsic, which I'm now using to avoid generating a call.
> - I also realized that since we only have 1 array creation handle per lambda form, we can instead generate a direct call to `Array::newInstance` instead of going through the array constructor handle (which also avoids having to use a BoundMethodHandle).
> - Finally, I added an instrinsic, under the old `NEW_ARRAY` name, that intrinsifies a call to `Array::newInstance` if the component type argument is constant (which it is in this case).
> 
> As a result, the lambda form is now fully intrinsified (no more calls in the generated bytecode) e.g.:
> 
> static java.lang.Object collector001_LLLL_L(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object);
>     Code:
>        0: iconst_3
>        1: anewarray     #12                 // class java/lang/String
>        4: astore        4
>        6: aload         4
>        8: checkcast     #14                 // class "[Ljava/lang/String;"
>       11: dup
>       12: astore        4
>       14: iconst_0
>       15: aload_1
>       16: checkcast     #12                 // class java/lang/String
>       19: aastore
>       20: aload         4
>       22: iconst_1
>       23: aload_2
>       24: checkcast     #12                 // class java/lang/String
>       27: aastore
>       28: aload         4
>       30: iconst_2
>       31: aload_3
>       32: checkcast     #12                 // class java/lang/String
>       35: aastore
>       36: aload         4
>       38: areturn
> 
> Thanks,
> Jorn

Addressed latest review comments:
- Reverted back to using an injected constructor handle (to be able to take advantage of lambda form sharing)
- Added lambda form sharing for empty and reference arrays
- Added a test case for a custom class to VarargsArrayTest, which catches the illegal access error in the intrinsified case that Vlad pointed out (though the itrinsic itself is now removed).

I also had to switch back to the un-cached version for creating the array element setter, since the cached version casts the array to be a specific type, and if the lambda form is shared, this won't work (e.g. casting an Object[] to String[], depending on the order of creating the collectors). Adding caching there is left as a followup.

-------------

PR: https://git.openjdk.java.net/jdk/pull/3306


More information about the core-libs-dev mailing list