RFR(L): 8161211: better inlining support for loop bytecode intrinsics

John Rose john.r.rose at oracle.com
Tue Sep 20 19:54:43 UTC 2016


There should also be an assert in the new LF constructor, which ensures that the two
arguments are congruent.  Better yet, just supply one argument (the speciesData),
and derive the MT.  These new LFs are pretty confusing, and it's best to nail down
unused degrees of freedom.

— John

P.S.  I would have expected this problem to be solved by having the MHI.toArray function
return a box object with a single @Stable array field.  Did that approach fail?

I.e., this wrapper emulates a frozen array (until that happy day when we have real
frozen arrays):

class ArrayConstant<T> {
  private final @Stable T[] values;
  public ArrayConstant(T[] values) {
    for (T v : values)  Objects.requireNonNull(v);
    this.values = values.clone();
  }
  public T get(int i) { return values[i]; }
  //public int length() { return values.length; }
}

The JIT should be able to constant fold through ac.get(i) whenever ac and i are constants.

On Sep 20, 2016, at 8:17 AM, Vladimir Ivanov <vladimir.x.ivanov at oracle.com> wrote:
> 
> 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
>> 
>> 
>> 



More information about the core-libs-dev mailing list