Skip to content

Commit

Permalink
8336831: Optimize StringConcatHelper.simpleConcat
Browse files Browse the repository at this point in the history
Reviewed-by: liach, redestad, rriggs
  • Loading branch information
wenshao authored and liach committed Jul 23, 2024
1 parent e40128d commit 285c7e8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/java.base/share/classes/java/lang/String.java
Original file line number Diff line number Diff line change
Expand Up @@ -2987,7 +2987,7 @@ public String concat(String str) {
if (str.isEmpty()) {
return this;
}
return StringConcatHelper.simpleConcat(this, str);
return StringConcatHelper.doConcat(this, str);
}

/**
Expand Down
47 changes: 32 additions & 15 deletions src/java.base/share/classes/java/lang/StringConcatHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -321,15 +321,24 @@ static String simpleConcat(Object first, Object second) {
// newly created string required, see JLS 15.18.1
return new String(s1);
}
// start "mixing" in length and coder or arguments, order is not
// important
long indexCoder = mix(initialCoder(), s1);
indexCoder = mix(indexCoder, s2);
byte[] buf = newArray(indexCoder);
// prepend each argument in reverse order, since we prepending
// from the end of the byte array
indexCoder = prepend(indexCoder, buf, s2, s1);
return newString(buf, indexCoder);
return doConcat(s1, s2);
}

/**
* Perform a simple concatenation between two non-empty strings.
*
* @param s1 first argument
* @param s2 second argument
* @return String resulting string
*/
@ForceInline
static String doConcat(String s1, String s2) {
byte coder = (byte) (s1.coder() | s2.coder());
int newLength = (s1.length() + s2.length()) << coder;
byte[] buf = newArray(newLength);
s1.getBytes(buf, 0, coder);
s2.getBytes(buf, s1.length(), coder);
return new String(buf, coder);
}

/**
Expand Down Expand Up @@ -395,14 +404,22 @@ static byte[] newArrayWithSuffix(String suffix, long indexCoder) {
*/
@ForceInline
static byte[] newArray(long indexCoder) {
int index = (int)indexCoder;
if (indexCoder >= UTF16) {
index <<= 1;
}
if (index < 0) {
byte coder = (byte)(indexCoder >> 32);
int index = ((int)indexCoder) << coder;
return newArray(index);
}

/**
* Allocates an uninitialized byte array based on the length
* @param length
* @return the newly allocated byte array
*/
@ForceInline
static byte[] newArray(int length) {
if (length < 0) {
throw new OutOfMemoryError("Overflow: String length out of range");
}
return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index);
return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, length);
}

/**
Expand Down

0 comments on commit 285c7e8

Please sign in to comment.