8212597: Optimize String concatenation setup when using primitive operands
Reviewed-by: shade
This commit is contained in:
parent
da989adeb7
commit
b3b41df70f
@ -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")));
|
||||
|
||||
|
@ -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!
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user