Re: RFR: 8288011: StringConcatFactory: Split application of stringifiers [v2]

2022-06-09 Thread Mandy Chung
On Thu, 9 Jun 2022 16:04:43 GMT, Claes Redestad  wrote:

>> To take optimal advantage of the pre-existing optimization for repeated 
>> filters we could split the application of different types of stringifiers.
>> 
>> The resulting difference in order of evaluation is not observable by 
>> conventional means since all reference type share the same object 
>> stringifier, and the others are filtering primitives (floats and doubles) 
>> which have been passed by value already. 
>> 
>> This change neutral on many concatenation expression shapes, but for any 
>> complex expressions with interleaving float/double and reference parameters 
>> it brings a straightforward reduction in rebinds and underlying LFs 
>> generated. For example on the 
>> [MixedStringCombinations.java](https://gist.github.com/cl4es/08fb581dece3a73e89bfa52337bc4248)
>>  test there's a modest 2% reduction in total classes loaded with this change 
>> (from 16209 to 15872)
>
> Claes Redestad has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Improve comments based on review feedback

Looks good to me.

Like Jorne's observation, it'd benefit everyone if this could generate just a 
single new lambda form multiple filters, not just for repeated filters if 
feasible.   Maybe something to explore more in the future with a tradeoff of 
complexity.

-

Marked as reviewed by mchung (Reviewer).

PR: https://git.openjdk.org/jdk/pull/9082


Re: RFR: 8288011: StringConcatFactory: Split application of stringifiers [v2]

2022-06-09 Thread Claes Redestad
> To take optimal advantage of the pre-existing optimization for repeated 
> filters we could split the application of different types of stringifiers.
> 
> The resulting difference in order of evaluation is not observable by 
> conventional means since all reference type share the same object 
> stringifier, and the others are filtering primitives (floats and doubles) 
> which have been passed by value already. 
> 
> This change neutral on many concatenation expression shapes, but for any 
> complex expressions with interleaving float/double and reference parameters 
> it brings a straightforward reduction in rebinds and underlying LFs 
> generated. For example on the 
> [MixedStringCombinations.java](https://gist.github.com/cl4es/08fb581dece3a73e89bfa52337bc4248)
>  test there's a modest 2% reduction in total classes loaded with this change 
> (from 16209 to 15872)

Claes Redestad has updated the pull request incrementally with one additional 
commit since the last revision:

  Improve comments based on review feedback

-

Changes:
  - all: https://git.openjdk.org/jdk/pull/9082/files
  - new: https://git.openjdk.org/jdk/pull/9082/files/51c841e8..4b7c696e

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=9082=01
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=9082=00-01

  Stats: 11 lines in 1 file changed: 7 ins; 2 del; 2 mod
  Patch: https://git.openjdk.org/jdk/pull/9082.diff
  Fetch: git fetch https://git.openjdk.org/jdk pull/9082/head:pull/9082

PR: https://git.openjdk.org/jdk/pull/9082


Re: RFR: 8288011: StringConcatFactory: Split application of stringifiers

2022-06-08 Thread Claes Redestad
On Wed, 8 Jun 2022 14:44:33 GMT, Jim Laskey  wrote:

>> To take optimal advantage of the pre-existing optimization for repeated 
>> filters we could split the application of different types of stringifiers.
>> 
>> The resulting difference in order of evaluation is not observable by 
>> conventional means since all reference type share the same object 
>> stringifier, and the others are filtering primitives (floats and doubles) 
>> which have been passed by value already. 
>> 
>> This change neutral on many concatenation expression shapes, but for any 
>> complex expressions with interleaving float/double and reference parameters 
>> it brings a straightforward reduction in rebinds and underlying LFs 
>> generated. For example on the 
>> [MixedStringCombinations.java](https://gist.github.com/cl4es/08fb581dece3a73e89bfa52337bc4248)
>>  test there's a modest 2% reduction in total classes loaded with this change 
>> (from 16209 to 15872)
>
> I make heavy use of the `mh = filterArgument(baseMH, 0, arrayOfFilters);` 
> pattern. I assumed it generated fewer LF than making individual calls. Am I 
> wrong?

@JimLaskey no, you're generally right to assume that bunching them up reduces 
the number of LFs created. There's a flaw in the `makeRepeatedFilterForm` 
transform that means the theoretical total amount of forms can surpass the 
baseline if you do _both_ one-by-one and all-at-once transforms from the same 
root MH. That's a very big if, but it's something I've felt slight unease about 
since I did that optimization.

-

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


Re: RFR: 8288011: StringConcatFactory: Split application of stringifiers

2022-06-08 Thread Jim Laskey
On Wed, 8 Jun 2022 10:20:37 GMT, Claes Redestad  wrote:

> To take optimal advantage of the pre-existing optimization for repeated 
> filters we could split the application of different types of stringifiers.
> 
> The resulting difference in order of evaluation is not observable by 
> conventional means since all reference type share the same object 
> stringifier, and the others are filtering primitives (floats and doubles) 
> which have been passed by value already. 
> 
> This change neutral on many concatenation expression shapes, but for any 
> complex expressions with interleaving float/double and reference parameters 
> it brings a straightforward reduction in rebinds and underlying LFs 
> generated. For example on the 
> [MixedStringCombinations.java](https://gist.github.com/cl4es/08fb581dece3a73e89bfa52337bc4248)
>  test there's a modest 2% reduction in total classes loaded with this change 
> (from 16209 to 15872)

I make heavy use of the `mh = filterArgument(baseMH, 0, arrayOfFilters);` 
pattern. I assumed it generated fewer LF than making individual calls. Am I 
wrong?

-

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


Re: RFR: 8288011: StringConcatFactory: Split application of stringifiers

2022-06-08 Thread Claes Redestad
On Wed, 8 Jun 2022 13:42:11 GMT, Jorn Vernee  wrote:

> Looking at the code in MethodHandles::filterArguments, and this optimization. 
> It seems that for multiple filters we could potentially always generate just 
> a single new lambda form if we wanted, not just for repeated filters.
> 
> It would be similar to `LambdaFormEditor::makeRepeatedFilterForm`. Just need 
> to extend the species data with one new `L_TYPE` field for each unique 
> filter, generate a new getCombiner `Name` for each unique combiner, pass in 
> an array of combiner types instead of just a single one, and pass in an 
> additional array of ints that marks the combiner used by each argument 
> position. Then do similar wiring up as we do now, but calling the 
> corresponding combiner for each argument pos. Right?
> 
> (If I'm right about that, maybe that's even a more interesting direction to 
> explore, since it would benefit everyone, and the code in StringConcatFactory 
> could stay the same)

You're right, but I think such a transform would add quite a bit of complexity. 

Back when I added the `makeRepeatedFilterForm` optimization (for the benefit of 
`StringConcatFactory`  ) I sought to strike a balance between the simple 
repeatedly-create-`filterArgumentForm`s transform we would do before and more 
complex forms that would remove more intermediates. I was also a bit concerned 
that such "shortcutting" transforms could mean we eliminate sharing, and the 
more complex we make things the harder it gets to reason about. Example:


...
mh1 = filterArgument(baseMH, 0, filter);
mh1 = filterArgument(mh1, 0, filter);

mh2 = filterArgument(baseMH, 0, filter, filter);

mh1.form() == mh2.form(); // false


The two different pathways end up with two different LFs, since 
`makeRepeatedFilterForm` shortcuts. In practice this might be a non-issue, but 
I figured it'd be nice if we could have a reasonable pathway to resolve 
mh1.form() and mh2.form() to the same thing in the future.

-

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


Re: RFR: 8288011: StringConcatFactory: Split application of stringifiers

2022-06-08 Thread Jorn Vernee
On Wed, 8 Jun 2022 10:20:37 GMT, Claes Redestad  wrote:

> To take optimal advantage of the pre-existing optimization for repeated 
> filters we could split the application of different types of stringifiers.
> 
> The resulting difference in order of evaluation is not observable by 
> conventional means since all reference type share the same object 
> stringifier, and the others are filtering primitives (floats and doubles) 
> which have been passed by value already. 
> 
> This change neutral on many concatenation expression shapes, but for any 
> complex expressions with interleaving float/double and reference parameters 
> it brings a straightforward reduction in rebinds and underlying LFs 
> generated. For example on the 
> [MixedStringCombinations.java](https://gist.github.com/cl4es/08fb581dece3a73e89bfa52337bc4248)
>  test there's a modest 2% reduction in total classes loaded with this change 
> (from 16209 to 15872)

This looks good to me, but...

Looking at the code in MethodHandles::filterArguments, and this optimization. 
It seems that for multiple filters we could potentially always generate just a 
single new lambda form if we wanted, not just for repeated filters.

It would be similar to `LambdaFormEditor::makeRepeatedFilterForm`. Just need to 
extend the species data with one new `L_TYPE` field for each unique filter, 
generate a new getCombiner `Name` for each unique combiner, pass in an array of 
combiner types instead of just a single one, and pass in an additional array of 
ints that marks the combiner used by each argument position. Then do similar 
wiring up as we do now, but calling the corresponding combiner for each 
argument pos. Right?

(If I'm right about that, maybe that's even a more interesting direction to 
explore, since it would benefit everyone, and the code in StringConcatFactory 
could stay the same)

-

Marked as reviewed by jvernee (Reviewer).

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


Re: RFR: 8288011: StringConcatFactory: Split application of stringifiers

2022-06-08 Thread Claes Redestad
On Wed, 8 Jun 2022 12:11:30 GMT, Сергей Цыпанов  wrote:

>> To take optimal advantage of the pre-existing optimization for repeated 
>> filters we could split the application of different types of stringifiers.
>> 
>> The resulting difference in order of evaluation is not observable by 
>> conventional means since all reference type share the same object 
>> stringifier, and the others are filtering primitives (floats and doubles) 
>> which have been passed by value already. 
>> 
>> This change neutral on many concatenation expression shapes, but for any 
>> complex expressions with interleaving float/double and reference parameters 
>> it brings a straightforward reduction in rebinds and underlying LFs 
>> generated. For example on the 
>> [MixedStringCombinations.java](https://gist.github.com/cl4es/08fb581dece3a73e89bfa52337bc4248)
>>  test there's a modest 2% reduction in total classes loaded with this change 
>> (from 16209 to 15872)
>
> src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java line 
> 509:
> 
>> 507: doubleFilters = new MethodHandle[ptypes.length];
>> 508: }
>> 509: doubleFilters[i] = doubleStringifier();
> 
> Why do we have `ptypes[i] = int.class` for `int` and `short`, `ptypes[i] = 
> String.class` for `float`, `double` and `Object` and none for `boolean` and 
> `char`? 類

`Object`, `float` and `double` arguments are all eagerly transformed to 
`String` (this is what the "stringifiers" do). Since we apply these as filters 
as a last step (which means that's the first thing that will run) we then must 
change the internal type to `String`. Ultimately means we have fewer types to 
worry about in the combinator.

We also widen integral subword types to `int` (`short` and `byte`). This 
doesn't need to be adapted by filtering but can lean on implicit conversion 
(subword primitives are widened to int anyhow, what we care about is matching 
the correct logic). This mainly matters insofar that the same direct method 
handle will be used for these three types, as it can (and will) be adapted 
without modification by the `viewAsType` call that ensures the `MH` returned 
from the BSM has the exact type asked for. 

`boolean` and `char` types can't use the `int` mixers/prependers and instead 
have specialized methods that will be adapted into the concat MH tree. This 
means the parameter type stays `boolean` and `char` throughout, respectively.

-

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


Re: RFR: 8288011: StringConcatFactory: Split application of stringifiers

2022-06-08 Thread Сергей Цыпанов
On Wed, 8 Jun 2022 10:20:37 GMT, Claes Redestad  wrote:

> To take optimal advantage of the pre-existing optimization for repeated 
> filters we could split the application of different types of stringifiers.
> 
> The resulting difference in order of evaluation is not observable by 
> conventional means since all reference type share the same object 
> stringifier, and the others are filtering primitives (floats and doubles) 
> which have been passed by value already. 
> 
> This change neutral on many concatenation expression shapes, but for any 
> complex expressions with interleaving float/double and reference parameters 
> it brings a straightforward reduction in rebinds and underlying LFs 
> generated. For example on the 
> [MixedStringCombinations.java](https://gist.github.com/cl4es/08fb581dece3a73e89bfa52337bc4248)
>  test there's a modest 2% reduction in total classes loaded with this change 
> (from 16209 to 15872)

src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java line 509:

> 507: doubleFilters = new MethodHandle[ptypes.length];
> 508: }
> 509: doubleFilters[i] = doubleStringifier();

Why do we have `ptypes[i] = int.class` for `int` and `short`, `ptypes[i] = 
String.class` for `float`, `double` and `Object` and none for `boolean` and 
`char`? 類

-

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