# HG changeset patch # User redestad # Date 1557415707 -7200 # Node ID 04f603ebb6c21d3229d447aef684d8cf2365fbfe # Parent b77bf7f216f45ad37169c4f8d003feef5ca20a60 8223454: Reduce String concatenation shapes by folding initialLengthCoder into last mixer Reviewed-by: jlaskey diff -r b77bf7f216f4 -r 04f603ebb6c2 src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java --- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Fri May 03 14:38:58 2019 +0200 +++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Thu May 09 17:28:27 2019 +0200 @@ -1666,25 +1666,33 @@ // and deduce the coder from there. Arguments would be either converted to Strings // during the initial filtering, or handled by specializations in MIXERS. // - // The method handle shape before and after all mixers are combined in is: + // The method handle shape before all mixers are combined in is: // (long, )String = ("indexCoder", ) + // + // We will bind the initialLengthCoder value to the last mixer (the one that will be + // executed first), then fold that in. This leaves the shape after all mixers are + // combined in as: + // ()String = () + int ac = -1; + MethodHandle mix = null; for (RecipeElement el : recipe.getElements()) { switch (el.getTag()) { case TAG_CONST: // Constants already handled in the code above break; case TAG_ARG: - int ac = el.getArgPos(); - - Class argClass = ptypes[ac]; - MethodHandle mix = mixer(argClass); + if (ac >= 0) { + // Compute new "index" in-place using old value plus the appropriate argument. + mh = MethodHandles.filterArgumentsWithCombiner(mh, 0, mix, + 0, // old-index + 1 + ac // selected argument + ); + } - // Compute new "index" in-place using old value plus the appropriate argument. - mh = MethodHandles.filterArgumentsWithCombiner(mh, 0, mix, - 0, // old-index - 1 + ac // selected argument - ); + ac = el.getArgPos(); + Class argClass = ptypes[ac]; + mix = mixer(argClass); break; default: @@ -1692,9 +1700,19 @@ } } - // Insert initial length and coder value here. + // Insert the initialLengthCoder value into the final mixer, then + // fold that into the base method handle + if (ac >= 0) { + mix = MethodHandles.insertArguments(mix, 0, initialLengthCoder); + mh = MethodHandles.foldArgumentsWithCombiner(mh, 0, mix, + 1 + ac // selected argument + ); + } else { + // No mixer (constants only concat), insert initialLengthCoder directly + mh = MethodHandles.insertArguments(mh, 0, initialLengthCoder); + } + // The method handle shape here is (). - mh = MethodHandles.insertArguments(mh, 0, initialLengthCoder); // Apply filters, converting the arguments: if (filters != null) {