8333893: Optimization for StringBuilder append boolean & null
Reviewed-by: liach
This commit is contained in:
parent
c33a8f52b6
commit
5890d9438b
@ -640,14 +640,11 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
|
||||
int count = this.count;
|
||||
byte[] val = this.value;
|
||||
if (isLatin1()) {
|
||||
val[count++] = 'n';
|
||||
val[count++] = 'u';
|
||||
val[count++] = 'l';
|
||||
val[count++] = 'l';
|
||||
StringLatin1.putCharsAt(val, count, 'n', 'u', 'l', 'l');
|
||||
} else {
|
||||
count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
|
||||
StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
|
||||
}
|
||||
this.count = count;
|
||||
this.count = count + 4;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -772,25 +769,18 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
|
||||
byte[] val = this.value;
|
||||
if (isLatin1()) {
|
||||
if (b) {
|
||||
val[count++] = 't';
|
||||
val[count++] = 'r';
|
||||
val[count++] = 'u';
|
||||
val[count++] = 'e';
|
||||
StringLatin1.putCharsAt(val, count, 't', 'r', 'u', 'e');
|
||||
} else {
|
||||
val[count++] = 'f';
|
||||
val[count++] = 'a';
|
||||
val[count++] = 'l';
|
||||
val[count++] = 's';
|
||||
val[count++] = 'e';
|
||||
StringLatin1.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
|
||||
}
|
||||
} else {
|
||||
if (b) {
|
||||
count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
|
||||
StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
|
||||
} else {
|
||||
count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
|
||||
StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
|
||||
}
|
||||
}
|
||||
this.count = count;
|
||||
this.count = count + (b ? 4 : 5);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
import jdk.internal.util.DecimalDigits;
|
||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
@ -42,6 +43,8 @@ import static java.lang.String.checkIndex;
|
||||
import static java.lang.String.checkOffset;
|
||||
|
||||
final class StringLatin1 {
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
|
||||
public static char charAt(byte[] value, int index) {
|
||||
checkIndex(index, value.length);
|
||||
return (char)(value[index] & 0xff);
|
||||
@ -824,6 +827,27 @@ final class StringLatin1 {
|
||||
return StreamSupport.stream(LinesSpliterator.spliterator(value), false);
|
||||
}
|
||||
|
||||
static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4) {
|
||||
assert index >= 0 && index + 3 < length(val) : "Trusted caller missed bounds check";
|
||||
// Don't use the putChar method, Its instrinsic will cause C2 unable to combining values into larger stores.
|
||||
long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + index;
|
||||
UNSAFE.putByte(val, address , (byte)(c1));
|
||||
UNSAFE.putByte(val, address + 1, (byte)(c2));
|
||||
UNSAFE.putByte(val, address + 2, (byte)(c3));
|
||||
UNSAFE.putByte(val, address + 3, (byte)(c4));
|
||||
}
|
||||
|
||||
static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4, int c5) {
|
||||
assert index >= 0 && index + 4 < length(val) : "Trusted caller missed bounds check";
|
||||
// Don't use the putChar method, Its instrinsic will cause C2 unable to combining values into larger stores.
|
||||
long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + index;
|
||||
UNSAFE.putByte(val, address , (byte)(c1));
|
||||
UNSAFE.putByte(val, address + 1, (byte)(c2));
|
||||
UNSAFE.putByte(val, address + 2, (byte)(c3));
|
||||
UNSAFE.putByte(val, address + 3, (byte)(c4));
|
||||
UNSAFE.putByte(val, address + 4, (byte)(c5));
|
||||
}
|
||||
|
||||
public static void putChar(byte[] val, int index, int c) {
|
||||
//assert (canEncode(c));
|
||||
val[index] = (byte)(c);
|
||||
|
@ -43,7 +43,6 @@ import static java.lang.String.UTF16;
|
||||
import static java.lang.String.LATIN1;
|
||||
|
||||
final class StringUTF16 {
|
||||
|
||||
// Return a new byte array for a UTF16-coded string for len chars
|
||||
// Throw an exception if out of range
|
||||
public static byte[] newBytesFor(int len) {
|
||||
@ -1548,27 +1547,20 @@ final class StringUTF16 {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) {
|
||||
int end = i + 4;
|
||||
checkBoundsBeginEnd(i, end, value);
|
||||
putChar(value, i++, c1);
|
||||
putChar(value, i++, c2);
|
||||
putChar(value, i++, c3);
|
||||
putChar(value, i++, c4);
|
||||
assert(i == end);
|
||||
return end;
|
||||
static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4) {
|
||||
assert index >= 0 && index + 3 < length(val) : "Trusted caller missed bounds check";
|
||||
putChar(val, index , c1);
|
||||
putChar(val, index + 1, c2);
|
||||
putChar(val, index + 2, c3);
|
||||
putChar(val, index + 3, c4);
|
||||
}
|
||||
|
||||
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) {
|
||||
int end = i + 5;
|
||||
checkBoundsBeginEnd(i, end, value);
|
||||
putChar(value, i++, c1);
|
||||
putChar(value, i++, c2);
|
||||
putChar(value, i++, c3);
|
||||
putChar(value, i++, c4);
|
||||
putChar(value, i++, c5);
|
||||
assert(i == end);
|
||||
return end;
|
||||
static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4, int c5) {
|
||||
putChar(val, index , c1);
|
||||
putChar(val, index + 1, c2);
|
||||
putChar(val, index + 2, c3);
|
||||
putChar(val, index + 3, c4);
|
||||
putChar(val, index + 4, c5);
|
||||
}
|
||||
|
||||
public static char charAt(byte[] value, int index) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -133,11 +133,17 @@ public class Helper {
|
||||
}
|
||||
|
||||
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) {
|
||||
return StringUTF16.putCharsAt(value, i, c1, c2, c3, c4);
|
||||
int end = i + 4;
|
||||
StringUTF16.checkBoundsBeginEnd(i, end, value);
|
||||
StringUTF16.putCharsAt(value, i, c1, c2, c3, c4);
|
||||
return end;
|
||||
}
|
||||
|
||||
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) {
|
||||
return StringUTF16.putCharsAt(value, i, c1, c2, c3, c4, c5);
|
||||
int end = i + 5;
|
||||
StringUTF16.checkBoundsBeginEnd(i, end, value);
|
||||
StringUTF16.putCharsAt(value, i, c1, c2, c3, c4, c5);
|
||||
return end;
|
||||
}
|
||||
|
||||
public static char charAt(byte[] value, int index) {
|
||||
|
@ -226,17 +226,66 @@ public class StringBuilders {
|
||||
|
||||
|
||||
@Benchmark
|
||||
public String toStringCharWithBool8() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append(true);
|
||||
result.append(false);
|
||||
result.append(true);
|
||||
result.append(true);
|
||||
result.append(false);
|
||||
result.append(true);
|
||||
result.append(false);
|
||||
result.append(false);
|
||||
return result.toString();
|
||||
public int appendWithBool8Latin1() {
|
||||
StringBuilder buf = sbLatin1;
|
||||
buf.setLength(0);
|
||||
buf.append(true);
|
||||
buf.append(false);
|
||||
buf.append(true);
|
||||
buf.append(true);
|
||||
buf.append(false);
|
||||
buf.append(true);
|
||||
buf.append(false);
|
||||
buf.append(false);
|
||||
return buf.length();
|
||||
}
|
||||
|
||||
|
||||
@Benchmark
|
||||
public int appendWithBool8Utf16() {
|
||||
StringBuilder buf = sbUtf16;
|
||||
buf.setLength(0);
|
||||
buf.append(true);
|
||||
buf.append(false);
|
||||
buf.append(true);
|
||||
buf.append(true);
|
||||
buf.append(false);
|
||||
buf.append(true);
|
||||
buf.append(false);
|
||||
buf.append(false);
|
||||
return buf.length();
|
||||
}
|
||||
|
||||
|
||||
@Benchmark
|
||||
public int appendWithNull8Latin1() {
|
||||
StringBuilder buf = sbLatin1;
|
||||
buf.setLength(0);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
return buf.length();
|
||||
}
|
||||
|
||||
|
||||
@Benchmark
|
||||
public int appendWithNull8Utf16() {
|
||||
StringBuilder buf = sbUtf16;
|
||||
buf.setLength(0);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
buf.append((String) null);
|
||||
return buf.length();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user