8212597: Optimize String concatenation setup when using primitive operands

Reviewed-by: shade
This commit is contained in:
Claes Redestad 2018-10-17 17:35:26 +02:00
parent da989adeb7
commit b3b41df70f
3 changed files with 45 additions and 72 deletions

View File

@ -66,6 +66,15 @@ public class HelloClasslist {
Stream.of(helloWorld.split(","))
.forEach(System.out::println);
// Common concatenation patterns
String const_I = "string" + args.length;
String const_S = "string" + String.valueOf(args.length);
String S_const = String.valueOf(args.length) + "string";
String S_S = String.valueOf(args.length) + String.valueOf(args.length);
String const_J = "string" + System.currentTimeMillis();
String I_const = args.length + "string";
String J_const = System.currentTimeMillis() + "string";
String newDate = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(
LocalDateTime.now(ZoneId.of("GMT")));

View File

@ -138,61 +138,6 @@ final class StringConcatHelper {
return (byte)(current | value.coder());
}
/**
* Mix coder into current coder
* @param current current coder
* @param value value to mix in
* @return new coder
*/
static byte mixCoder(byte current, boolean value) {
// Booleans are represented with Latin1
return current;
}
/**
* Mix coder into current coder
* @param current current coder
* @param value value to mix in
* @return new coder
*/
static byte mixCoder(byte current, byte value) {
// Bytes are represented with Latin1
return current;
}
/**
* Mix coder into current coder
* @param current current coder
* @param value value to mix in
* @return new coder
*/
static byte mixCoder(byte current, short value) {
// Shorts are represented with Latin1
return current;
}
/**
* Mix coder into current coder
* @param current current coder
* @param value value to mix in
* @return new coder
*/
static byte mixCoder(byte current, int value) {
// Ints are represented with Latin1
return current;
}
/**
* Mix coder into current coder
* @param current current coder
* @param value value to mix in
* @return new coder
*/
static byte mixCoder(byte current, long value) {
// Longs are represented with Latin1
return current;
}
/**
* Prepends the stringly representation of boolean value into buffer,
* given the coder and final index. Index is measured in chars, not in bytes!

View File

@ -1588,28 +1588,47 @@ public final class StringConcatFactory {
Class<?> argClass = ptypes[ac];
MethodHandle lm = lengthMixer(argClass);
MethodHandle cm = coderMixer(argClass);
// Read this bottom up:
// Read these bottom up:
// 4. Drop old index and coder, producing ("new-index", "new-coder", <args>)
mh = MethodHandles.dropArguments(mh, 2, int.class, byte.class);
if (argClass.isPrimitive() && argClass != char.class) {
// 3. Compute "new-index", producing ("new-index", "new-coder", "old-index", "old-coder", <args>)
// Length mixer needs old index, plus the appropriate argument
mh = MethodHandles.foldArguments(mh, 0, lm,
2, // old-index
4 + ac // selected argument
);
// 3. Drop old index, producing ("new-index", "coder", <args>)
mh = MethodHandles.dropArguments(mh, 1, int.class);
// 2. Compute "new-coder", producing ("new-coder", "old-index", "old-coder", <args>)
// Coder mixer needs old coder, plus the appropriate argument.
mh = MethodHandles.foldArguments(mh, 0, cm,
2, // old-coder
3 + ac // selected argument
);
// 2. Compute "new-index", producing ("new-index", "old-index", "coder", <args>)
// Length mixer needs old index, plus the appropriate argument
mh = MethodHandles.foldArguments(mh, 0, lm,
1, // old-index
3 + ac // selected argument
);
// 1. The mh shape here is ("old-index", "coder", <args>); we don't need to recalculate
// the coder for non-char primitive arguments
} else {
MethodHandle cm = coderMixer(argClass);
// 4. Drop old index and coder, producing ("new-index", "new-coder", <args>)
mh = MethodHandles.dropArguments(mh, 2, int.class, byte.class);
// 3. Compute "new-index", producing ("new-index", "new-coder", "old-index", "old-coder", <args>)
// Length mixer needs old index, plus the appropriate argument
mh = MethodHandles.foldArguments(mh, 0, lm,
2, // old-index
4 + ac // selected argument
);
// 2. Compute "new-coder", producing ("new-coder", "old-index", "old-coder", <args>)
// Coder mixer needs old coder, plus the appropriate argument.
mh = MethodHandles.foldArguments(mh, 0, cm,
2, // old-coder
3 + ac // selected argument
);
// 1. The mh shape here is ("old-index", "old-coder", <args>)
}
// 1. The mh shape here is ("old-index", "old-coder", <args>)
break;
default:
throw new StringConcatException("Unhandled tag: " + el.getTag());