Skip to content

Commit 618c5eb

Browse files
committed
8349183: [BACKOUT] Optimization for StringBuilder append boolean & null
8349239: [BACKOUT] Reuse StringLatin1::putCharsAt and StringUTF16::putCharsAt Reviewed-by: redestad, liach
1 parent bb837d2 commit 618c5eb

File tree

6 files changed

+90
-123
lines changed

6 files changed

+90
-123
lines changed

src/java.base/share/classes/java/lang/AbstractStringBuilder.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -640,11 +640,14 @@ private AbstractStringBuilder appendNull() {
640640
int count = this.count;
641641
byte[] val = this.value;
642642
if (isLatin1()) {
643-
StringLatin1.putCharsAt(val, count, 'n', 'u', 'l', 'l');
643+
val[count++] = 'n';
644+
val[count++] = 'u';
645+
val[count++] = 'l';
646+
val[count++] = 'l';
644647
} else {
645-
StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
648+
count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
646649
}
647-
this.count = count + 4;
650+
this.count = count;
648651
return this;
649652
}
650653

@@ -769,18 +772,25 @@ public AbstractStringBuilder append(boolean b) {
769772
byte[] val = this.value;
770773
if (isLatin1()) {
771774
if (b) {
772-
StringLatin1.putCharsAt(val, count, 't', 'r', 'u', 'e');
775+
val[count++] = 't';
776+
val[count++] = 'r';
777+
val[count++] = 'u';
778+
val[count++] = 'e';
773779
} else {
774-
StringLatin1.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
780+
val[count++] = 'f';
781+
val[count++] = 'a';
782+
val[count++] = 'l';
783+
val[count++] = 's';
784+
val[count++] = 'e';
775785
}
776786
} else {
777787
if (b) {
778-
StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
788+
count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
779789
} else {
780-
StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
790+
count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
781791
}
782792
}
783-
this.count = count + (b ? 4 : 5);
793+
this.count = count;
784794
return this;
785795
}
786796

src/java.base/share/classes/java/lang/StringConcatHelper.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -236,21 +236,35 @@ static long prepend(long indexCoder, byte[] buf, boolean value, String prefix) {
236236
if (indexCoder < UTF16) {
237237
if (value) {
238238
index -= 4;
239-
StringLatin1.putCharsAt(buf, index, 't', 'r', 'u', 'e');
239+
buf[index] = 't';
240+
buf[index + 1] = 'r';
241+
buf[index + 2] = 'u';
242+
buf[index + 3] = 'e';
240243
} else {
241244
index -= 5;
242-
StringLatin1.putCharsAt(buf, index, 'f', 'a', 'l', 's', 'e');
245+
buf[index] = 'f';
246+
buf[index + 1] = 'a';
247+
buf[index + 2] = 'l';
248+
buf[index + 3] = 's';
249+
buf[index + 4] = 'e';
243250
}
244251
index -= prefix.length();
245252
prefix.getBytes(buf, index, String.LATIN1);
246253
return index;
247254
} else {
248255
if (value) {
249256
index -= 4;
250-
StringUTF16.putCharsAt(buf, index, 't', 'r', 'u', 'e');
257+
StringUTF16.putChar(buf, index, 't');
258+
StringUTF16.putChar(buf, index + 1, 'r');
259+
StringUTF16.putChar(buf, index + 2, 'u');
260+
StringUTF16.putChar(buf, index + 3, 'e');
251261
} else {
252262
index -= 5;
253-
StringUTF16.putCharsAt(buf, index, 'f', 'a', 'l', 's', 'e');
263+
StringUTF16.putChar(buf, index, 'f');
264+
StringUTF16.putChar(buf, index + 1, 'a');
265+
StringUTF16.putChar(buf, index + 2, 'l');
266+
StringUTF16.putChar(buf, index + 3, 's');
267+
StringUTF16.putChar(buf, index + 4, 'e');
254268
}
255269
index -= prefix.length();
256270
prefix.getBytes(buf, index, String.UTF16);
@@ -624,20 +638,34 @@ static int prepend(int index, byte coder, byte[] buf, boolean value, String pref
624638
if (coder == String.LATIN1) {
625639
if (value) {
626640
index -= 4;
627-
StringLatin1.putCharsAt(buf, index, 't', 'r', 'u', 'e');
641+
buf[index] = 't';
642+
buf[index + 1] = 'r';
643+
buf[index + 2] = 'u';
644+
buf[index + 3] = 'e';
628645
} else {
629646
index -= 5;
630-
StringLatin1.putCharsAt(buf, index, 'f', 'a', 'l', 's', 'e');
647+
buf[index] = 'f';
648+
buf[index + 1] = 'a';
649+
buf[index + 2] = 'l';
650+
buf[index + 3] = 's';
651+
buf[index + 4] = 'e';
631652
}
632653
index -= prefix.length();
633654
prefix.getBytes(buf, index, String.LATIN1);
634655
} else {
635656
if (value) {
636657
index -= 4;
637-
StringUTF16.putCharsAt(buf, index, 't', 'r', 'u', 'e');
658+
StringUTF16.putChar(buf, index, 't');
659+
StringUTF16.putChar(buf, index + 1, 'r');
660+
StringUTF16.putChar(buf, index + 2, 'u');
661+
StringUTF16.putChar(buf, index + 3, 'e');
638662
} else {
639663
index -= 5;
640-
StringUTF16.putCharsAt(buf, index, 'f', 'a', 'l', 's', 'e');
664+
StringUTF16.putChar(buf, index, 'f');
665+
StringUTF16.putChar(buf, index + 1, 'a');
666+
StringUTF16.putChar(buf, index + 2, 'l');
667+
StringUTF16.putChar(buf, index + 3, 's');
668+
StringUTF16.putChar(buf, index + 4, 'e');
641669
}
642670
index -= prefix.length();
643671
prefix.getBytes(buf, index, String.UTF16);

src/java.base/share/classes/java/lang/StringLatin1.java

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import java.util.function.IntConsumer;
3333
import java.util.stream.Stream;
3434
import java.util.stream.StreamSupport;
35-
import jdk.internal.misc.Unsafe;
3635
import jdk.internal.util.ArraysSupport;
3736
import jdk.internal.vm.annotation.IntrinsicCandidate;
3837

@@ -42,8 +41,6 @@
4241
import static java.lang.String.checkOffset;
4342

4443
final class StringLatin1 {
45-
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
46-
4744
public static char charAt(byte[] value, int index) {
4845
checkIndex(index, value.length);
4946
return (char)(value[index] & 0xff);
@@ -712,27 +709,6 @@ static Stream<String> lines(byte[] value) {
712709
return StreamSupport.stream(LinesSpliterator.spliterator(value), false);
713710
}
714711

715-
static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4) {
716-
assert index >= 0 && index + 3 < length(val) : "Trusted caller missed bounds check";
717-
// Don't use the putChar method, Its instrinsic will cause C2 unable to combining values into larger stores.
718-
long offset = Unsafe.ARRAY_BYTE_BASE_OFFSET + index;
719-
UNSAFE.putByte(val, offset , (byte)(c1));
720-
UNSAFE.putByte(val, offset + 1, (byte)(c2));
721-
UNSAFE.putByte(val, offset + 2, (byte)(c3));
722-
UNSAFE.putByte(val, offset + 3, (byte)(c4));
723-
}
724-
725-
static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4, int c5) {
726-
assert index >= 0 && index + 4 < length(val) : "Trusted caller missed bounds check";
727-
// Don't use the putChar method, Its instrinsic will cause C2 unable to combining values into larger stores.
728-
long offset = Unsafe.ARRAY_BYTE_BASE_OFFSET + index;
729-
UNSAFE.putByte(val, offset , (byte)(c1));
730-
UNSAFE.putByte(val, offset + 1, (byte)(c2));
731-
UNSAFE.putByte(val, offset + 2, (byte)(c3));
732-
UNSAFE.putByte(val, offset + 3, (byte)(c4));
733-
UNSAFE.putByte(val, offset + 4, (byte)(c5));
734-
}
735-
736712
public static void putChar(byte[] val, int index, int c) {
737713
//assert (canEncode(c));
738714
val[index] = (byte)(c);

src/java.base/share/classes/java/lang/StringUTF16.java

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import static java.lang.String.LATIN1;
4343

4444
final class StringUTF16 {
45+
4546
// Return a new byte array for a UTF16-coded string for len chars
4647
// Throw an exception if out of range
4748
public static byte[] newBytesFor(int len) {
@@ -1532,20 +1533,27 @@ public static boolean contentEquals(byte[] value, CharSequence cs, int len) {
15321533
return true;
15331534
}
15341535

1535-
static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4) {
1536-
assert index >= 0 && index + 3 < length(val) : "Trusted caller missed bounds check";
1537-
putChar(val, index , c1);
1538-
putChar(val, index + 1, c2);
1539-
putChar(val, index + 2, c3);
1540-
putChar(val, index + 3, c4);
1541-
}
1542-
1543-
static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4, int c5) {
1544-
putChar(val, index , c1);
1545-
putChar(val, index + 1, c2);
1546-
putChar(val, index + 2, c3);
1547-
putChar(val, index + 3, c4);
1548-
putChar(val, index + 4, c5);
1536+
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) {
1537+
int end = i + 4;
1538+
checkBoundsBeginEnd(i, end, value);
1539+
putChar(value, i++, c1);
1540+
putChar(value, i++, c2);
1541+
putChar(value, i++, c3);
1542+
putChar(value, i++, c4);
1543+
assert(i == end);
1544+
return end;
1545+
}
1546+
1547+
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) {
1548+
int end = i + 5;
1549+
checkBoundsBeginEnd(i, end, value);
1550+
putChar(value, i++, c1);
1551+
putChar(value, i++, c2);
1552+
putChar(value, i++, c3);
1553+
putChar(value, i++, c4);
1554+
putChar(value, i++, c5);
1555+
assert(i == end);
1556+
return end;
15491557
}
15501558

15511559
public static char charAt(byte[] value, int index) {

test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -141,17 +141,11 @@ public static boolean contentEquals(byte[] value, CharSequence cs, int len) {
141141
}
142142

143143
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) {
144-
int end = i + 4;
145-
StringUTF16.checkBoundsBeginEnd(i, end, value);
146-
StringUTF16.putCharsAt(value, i, c1, c2, c3, c4);
147-
return end;
144+
return StringUTF16.putCharsAt(value, i, c1, c2, c3, c4);
148145
}
149146

150147
public static int putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) {
151-
int end = i + 5;
152-
StringUTF16.checkBoundsBeginEnd(i, end, value);
153-
StringUTF16.putCharsAt(value, i, c1, c2, c3, c4, c5);
154-
return end;
148+
return StringUTF16.putCharsAt(value, i, c1, c2, c3, c4, c5);
155149
}
156150

157151
public static char charAt(byte[] value, int index) {

test/micro/org/openjdk/bench/java/lang/StringBuilders.java

Lines changed: 11 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -274,66 +274,17 @@ public int appendWithLongUtf16() {
274274
}
275275

276276
@Benchmark
277-
public int appendWithBool8Latin1() {
278-
StringBuilder buf = sbLatin1;
279-
buf.setLength(0);
280-
buf.append(true);
281-
buf.append(false);
282-
buf.append(true);
283-
buf.append(true);
284-
buf.append(false);
285-
buf.append(true);
286-
buf.append(false);
287-
buf.append(false);
288-
return buf.length();
289-
}
290-
291-
292-
@Benchmark
293-
public int appendWithBool8Utf16() {
294-
StringBuilder buf = sbUtf16;
295-
buf.setLength(0);
296-
buf.append(true);
297-
buf.append(false);
298-
buf.append(true);
299-
buf.append(true);
300-
buf.append(false);
301-
buf.append(true);
302-
buf.append(false);
303-
buf.append(false);
304-
return buf.length();
305-
}
306-
307-
308-
@Benchmark
309-
public int appendWithNull8Latin1() {
310-
StringBuilder buf = sbLatin1;
311-
buf.setLength(0);
312-
buf.append((String) null);
313-
buf.append((String) null);
314-
buf.append((String) null);
315-
buf.append((String) null);
316-
buf.append((String) null);
317-
buf.append((String) null);
318-
buf.append((String) null);
319-
buf.append((String) null);
320-
return buf.length();
321-
}
322-
323-
324-
@Benchmark
325-
public int appendWithNull8Utf16() {
326-
StringBuilder buf = sbUtf16;
327-
buf.setLength(0);
328-
buf.append((String) null);
329-
buf.append((String) null);
330-
buf.append((String) null);
331-
buf.append((String) null);
332-
buf.append((String) null);
333-
buf.append((String) null);
334-
buf.append((String) null);
335-
buf.append((String) null);
336-
return buf.length();
277+
public String toStringCharWithBool8() {
278+
StringBuilder result = new StringBuilder();
279+
result.append(true);
280+
result.append(false);
281+
result.append(true);
282+
result.append(true);
283+
result.append(false);
284+
result.append(true);
285+
result.append(false);
286+
result.append(false);
287+
return result.toString();
337288
}
338289

339290

0 commit comments

Comments
 (0)