Looks good.
src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java:
+ LambdaForm bmhArrayForm(MethodType type,
BoundMethodHandle.SpeciesData speciesData) {
+ int size = type.parameterCount();
+ Transform key = Transform.of(Transform.BMH_AS_ARRAY, size);
+ LambdaForm form = getInCache(key);
+ if (form != null) {
+ return form;
+ }
Please, add an assert to ensure the cached LF has the same constraint as
requested (speciesData).
Best regards,
Vladimir Ivanov
On 9/20/16 3:53 PM, Michael Haupt wrote:
Dear all,
please review this change.
Bug: https://bugs.openjdk.java.net/browse/JDK-8161211
Webrev: http://cr.openjdk.java.net/~mhaupt/8161211/webrev.00/
The method handle loop combinators introduced with JEP 274 were originally not
intrinsified, leading to poor performance as compared to a pure-Java baseline,
but also to handwired method handle combinations. The intrinsics introduced
with 8143211 [1] improved on the situation somewhat, but still did not provide
good inlining opportunities for the JIT compiler. This change introduces a
usage of BoundMethodHandles as arrays to carry the various handles involved in
loop execution.
Extra credits to Vladimir Ivanov, who suggested the BMH-as-arrays approach in
the first place, and Claes Redestad, who suggested to use LambdaForm editing to
neatly enable caching. Thanks!
Performance improves considerably. The table below reports scores in ns/op. The
"unpatched" column contains results from before applying the patch for 8161211; the
"patched" column, from thereafter.
The create benchmarks measure the cost of loop handle creation. The baseline
and baselineMH benchmarks measure the cost of running a pure Java and handwired
method handle construct.
Relevant comparisons include loop combinator results versus baselines, and
versus unpatched loop combinator results. For the latter, there are significant
improvements, except for the creation benchmarks (creation has a more complex
workflow now). For the former, it can be seen that the BMH-array intrinsics
generally perform better than handwired handle constructs, and have moved much
closer to.
Thanks,
Michael
[1] https://bugs.openjdk.java.net/browse/JDK-8143211
Benchmark (iterations) unpatched
patched
MethodHandlesCountedLoop.Create.create3 N/A 16039.108
18400.405
MethodHandlesCountedLoop.Create.create4 N/A 15621.959
17924.696
MethodHandlesCountedLoop.Invoke.baseline3 0 2.858
2.839
MethodHandlesCountedLoop.Invoke.baseline3 1 5.125
5.164
MethodHandlesCountedLoop.Invoke.baseline3 10 11.887
11.924
MethodHandlesCountedLoop.Invoke.baseline3 100 67.441
67.281
MethodHandlesCountedLoop.Invoke.baseline4 0 2.855
2.838
MethodHandlesCountedLoop.Invoke.baseline4 1 5.120
5.179
MethodHandlesCountedLoop.Invoke.baseline4 10 11.875
11.906
MethodHandlesCountedLoop.Invoke.baseline4 100 67.607
67.374
MethodHandlesCountedLoop.Invoke.baselineMH3 0 9.734
9.606
MethodHandlesCountedLoop.Invoke.baselineMH3 1 15.689
15.674
MethodHandlesCountedLoop.Invoke.baselineMH3 10 68.912
69.303
MethodHandlesCountedLoop.Invoke.baselineMH3 100 605.666
606.432
MethodHandlesCountedLoop.Invoke.baselineMH4 0 14.561
13.234
MethodHandlesCountedLoop.Invoke.baselineMH4 1 19.543
19.773
MethodHandlesCountedLoop.Invoke.baselineMH4 10 71.977
72.466
MethodHandlesCountedLoop.Invoke.baselineMH4 100 596.842
602.469
MethodHandlesCountedLoop.Invoke.countedLoop3 0 49.339
5.810
MethodHandlesCountedLoop.Invoke.countedLoop3 1 95.444
7.441
MethodHandlesCountedLoop.Invoke.countedLoop3 10 508.746
21.002
MethodHandlesCountedLoop.Invoke.countedLoop3 100 4701.808
145.996
MethodHandlesCountedLoop.Invoke.countedLoop4 0 49.443
5.798
MethodHandlesCountedLoop.Invoke.countedLoop4 1 98.721
7.438
MethodHandlesCountedLoop.Invoke.countedLoop4 10 503.825
21.049
MethodHandlesCountedLoop.Invoke.countedLoop4 100 4681.803
147.020
MethodHandlesDoWhileLoop.Create.create N/A 7628.312
9100.332
MethodHandlesDoWhileLoop.Invoke.baseline 1 3.868
3.909
MethodHandlesDoWhileLoop.Invoke.baseline 10 16.480
16.461
MethodHandlesDoWhileLoop.Invoke.baseline 100 144.260
144.232
MethodHandlesDoWhileLoop.Invoke.baselineMH 1 14.434
14.494
MethodHandlesDoWhileLoop.Invoke.baselineMH 10 92.542
93.454
MethodHandlesDoWhileLoop.Invoke.baselineMH 100 877.480
880.496
MethodHandlesDoWhileLoop.Invoke.doWhileLoop 1 26.791
7.153
MethodHandlesDoWhileLoop.Invoke.doWhileLoop 10 158.985
16.990
MethodHandlesDoWhileLoop.Invoke.doWhileLoop 100 1391.746
130.946
MethodHandlesIteratedLoop.Create.create N/A 13547.499
15478.542
MethodHandlesIteratedLoop.Invoke.baseline 0 2.973
2.980
MethodHandlesIteratedLoop.Invoke.baseline 1 6.771
6.658
MethodHandlesIteratedLoop.Invoke.baseline 10 14.955
14.955
MethodHandlesIteratedLoop.Invoke.baseline 100 81.842
82.582
MethodHandlesIteratedLoop.Invoke.baselineMH 0 14.893
14.668
MethodHandlesIteratedLoop.Invoke.baselineMH 1 20.998
21.304
MethodHandlesIteratedLoop.Invoke.baselineMH 10 73.677
72.703
MethodHandlesIteratedLoop.Invoke.baselineMH 100 613.913
614.475
MethodHandlesIteratedLoop.Invoke.iteratedLoop 0 33.583
9.603
MethodHandlesIteratedLoop.Invoke.iteratedLoop 1 82.239
14.433
MethodHandlesIteratedLoop.Invoke.iteratedLoop 10 448.356
38.650
MethodHandlesIteratedLoop.Invoke.iteratedLoop 100 4189.034
279.779
MethodHandlesLoop.Create.create N/A 15505.970
17559.399
MethodHandlesLoop.Invoke0.baseline 1 3.179
3.181
MethodHandlesLoop.Invoke0.baseline 10 5.952
6.115
MethodHandlesLoop.Invoke0.baseline 100 50.942
50.943
MethodHandlesLoop.Invoke0.loop 1 46.454
5.353
MethodHandlesLoop.Invoke0.loop 10 514.230
8.487
MethodHandlesLoop.Invoke0.loop 100 5166.251
52.188
MethodHandlesLoop.Invoke1.loop 1 34.321
5.277
MethodHandlesLoop.Invoke1.loop 10 430.839
8.481
MethodHandlesLoop.Invoke1.loop 100 4095.302
52.206
MethodHandlesTryFinally.baselineExceptional N/A 3.005
3.002
MethodHandlesTryFinally.baselineMHExceptional N/A 166.316
166.087
MethodHandlesTryFinally.baselineMHNormal N/A 9.337
9.276
MethodHandlesTryFinally.baselineNormal N/A 2.696
2.683
MethodHandlesTryFinally.create N/A 406.255
406.594
MethodHandlesTryFinally.invokeTryFinallyExceptional N/A 154.121
154.692
MethodHandlesTryFinally.invokeTryFinallyNormal N/A 5.350
5.334
MethodHandlesWhileLoop.Create.create N/A 12214.383
14503.515
MethodHandlesWhileLoop.Invoke.baseline 0 3.886
3.888
MethodHandlesWhileLoop.Invoke.baseline 1 5.379
5.377
MethodHandlesWhileLoop.Invoke.baseline 10 16.000
16.201
MethodHandlesWhileLoop.Invoke.baseline 100 142.066
143.338
MethodHandlesWhileLoop.Invoke.baselineMH 0 11.028
11.012
MethodHandlesWhileLoop.Invoke.baselineMH 1 21.269
21.159
MethodHandlesWhileLoop.Invoke.baselineMH 10 97.493
97.656
MethodHandlesWhileLoop.Invoke.baselineMH 100 887.579
886.532
MethodHandlesWhileLoop.Invoke.whileLoop 0 24.829
7.108
MethodHandlesWhileLoop.Invoke.whileLoop 1 46.039
8.573
MethodHandlesWhileLoop.Invoke.whileLoop 10 240.963
21.088
MethodHandlesWhileLoop.Invoke.whileLoop 100 2092.671
159.016