Skip to content

Commit 55312e1

Browse files
wenshaoliach
authored andcommitted
8338937: Optimize the string concatenation of ClassDesc
Reviewed-by: liach
1 parent d4dfa01 commit 55312e1

File tree

7 files changed

+53
-18
lines changed

7 files changed

+53
-18
lines changed

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4647,7 +4647,7 @@ public String descriptorString() {
46474647
return Wrapper.forPrimitiveType(this).basicTypeString();
46484648

46494649
if (isArray()) {
4650-
return "[" + componentType.descriptorString();
4650+
return "[".concat(componentType.descriptorString());
46514651
} else if (isHidden()) {
46524652
String name = getName();
46534653
int index = name.indexOf('/');
@@ -4660,11 +4660,7 @@ public String descriptorString() {
46604660
.toString();
46614661
} else {
46624662
String name = getName().replace('.', '/');
4663-
return new StringBuilder(name.length() + 2)
4664-
.append('L')
4665-
.append(name)
4666-
.append(';')
4667-
.toString();
4663+
return StringConcatHelper.concat("L", name, ";");
46684664
}
46694665
}
46704666

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,4 +783,20 @@ static int checkOverflow(int value) {
783783
}
784784
throw new OutOfMemoryError("Overflow: String length out of range");
785785
}
786+
787+
@ForceInline
788+
private static String concat0(String prefix, String str, String suffix) {
789+
byte coder = (byte) (prefix.coder() | str.coder() | suffix.coder());
790+
int len = prefix.length() + str.length();
791+
byte[] buf = newArrayWithSuffix(suffix, len, coder);
792+
prepend(len, coder, buf, str, prefix);
793+
return new String(buf, coder);
794+
}
795+
796+
@ForceInline
797+
static String concat(String prefix, Object value, String suffix) {
798+
if (prefix == null) prefix = "null";
799+
if (suffix == null) suffix = "null";
800+
return concat0(prefix, stringOf(value), suffix);
801+
}
786802
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,6 +2650,10 @@ public String join(String prefix, String suffix, String delimiter, String[] elem
26502650
return String.join(prefix, suffix, delimiter, elements, size);
26512651
}
26522652

2653+
public String concat(String prefix, Object value, String suffix) {
2654+
return StringConcatHelper.concat(prefix, value, suffix);
2655+
}
2656+
26532657
public Object classData(Class<?> c) {
26542658
return c.getClassData();
26552659
}

src/java.base/share/classes/java/lang/constant/ClassDesc.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import static jdk.internal.constant.ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS;
3737
import static jdk.internal.constant.ConstantUtils.arrayDepth;
3838
import static jdk.internal.constant.ConstantUtils.binaryToInternal;
39+
import static jdk.internal.constant.ConstantUtils.concat;
3940
import static jdk.internal.constant.ConstantUtils.forPrimitiveType;
4041
import static jdk.internal.constant.ConstantUtils.internalToBinary;
4142
import static jdk.internal.constant.ConstantUtils.validateBinaryClassName;
@@ -83,7 +84,7 @@ public sealed interface ClassDesc
8384
*/
8485
static ClassDesc of(String name) {
8586
validateBinaryClassName(name);
86-
return ClassDesc.ofDescriptor("L" + binaryToInternal(name) + ";");
87+
return ClassDesc.ofDescriptor(concat("L", binaryToInternal(name), ";"));
8788
}
8889

8990
/**
@@ -109,7 +110,7 @@ static ClassDesc of(String name) {
109110
*/
110111
static ClassDesc ofInternalName(String name) {
111112
validateInternalClassName(name);
112-
return ClassDesc.ofDescriptor("L" + name + ";");
113+
return ClassDesc.ofDescriptor(concat("L", name, ";"));
113114
}
114115

115116
/**
@@ -132,8 +133,8 @@ static ClassDesc of(String packageName, String className) {
132133
return of(className);
133134
}
134135
validateMemberName(className, false);
135-
return ofDescriptor("L" + binaryToInternal(packageName) +
136-
"/" + className + ";");
136+
return ofDescriptor('L' + binaryToInternal(packageName) +
137+
'/' + className + ';');
137138
}
138139

139140
/**
@@ -361,7 +362,7 @@ else if (isArray()) {
361362
ClassDesc c = this;
362363
for (int i=0; i<depth; i++)
363364
c = c.componentType();
364-
return c.displayName() + "[]".repeat(depth);
365+
return c.displayName().concat("[]".repeat(depth));
365366
}
366367
else
367368
throw new IllegalStateException(descriptorString());

src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize,
125125
name = makeDumpableClassName(name);
126126
}
127127
this.name = name;
128-
this.className = CLASS_PREFIX + name;
128+
this.className = CLASS_PREFIX.concat(name);
129129
this.classDesc = ClassDesc.ofInternalName(className);
130130
this.lambdaForm = lambdaForm;
131131
this.invokerName = invokerName;
@@ -180,11 +180,16 @@ private static String makeDumpableClassName(String className) {
180180
if (ctr == null) ctr = 0;
181181
DUMP_CLASS_FILES_COUNTERS.put(className, ctr+1);
182182
}
183-
String sfx = ctr.toString();
184-
while (sfx.length() < 3)
185-
sfx = "0" + sfx;
186-
className += sfx;
187-
return className;
183+
184+
var buf = new StringBuilder(className.length() + 3).append(className);
185+
int ctrVal = ctr;
186+
if (ctrVal < 10) {
187+
buf.repeat('0', 2);
188+
} else if (ctrVal < 100) {
189+
buf.append('0');
190+
}
191+
buf.append(ctrVal);
192+
return buf.toString();
188193
}
189194

190195
static class ClassData {

src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,11 @@ public interface JavaLangAccess {
457457
*/
458458
String join(String prefix, String suffix, String delimiter, String[] elements, int size);
459459

460+
/**
461+
* Concatenation of prefix and suffix characters to a String for early bootstrap
462+
*/
463+
String concat(String prefix, Object value, String suffix);
464+
460465
/*
461466
* Get the class data associated with the given class.
462467
* @param c the class

src/java.base/share/classes/jdk/internal/constant/ConstantUtils.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@
3535
import java.util.List;
3636
import java.util.Set;
3737

38+
import jdk.internal.access.JavaLangAccess;
39+
import jdk.internal.access.SharedSecrets;
3840
import static jdk.internal.constant.PrimitiveClassDescImpl.*;
3941

4042
/**
4143
* Helper methods for the implementation of {@code java.lang.constant}.
4244
*/
4345
public final class ConstantUtils {
46+
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
47+
4448
/** an empty constant descriptor */
4549
public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0];
4650
public static final ClassDesc[] EMPTY_CLASSDESC = new ClassDesc[0];
@@ -66,7 +70,7 @@ private ConstantUtils() {}
6670
* @param binaryName a binary name
6771
*/
6872
public static ClassDesc binaryNameToDesc(String binaryName) {
69-
return ReferenceClassDescImpl.ofValidated("L" + binaryToInternal(binaryName) + ";");
73+
return ReferenceClassDescImpl.ofValidated(concat("L", binaryToInternal(binaryName), ";"));
7074
}
7175

7276
/**
@@ -378,4 +382,8 @@ private static IllegalArgumentException maxArrayTypeDescDimensions() {
378382
"Cannot create an array type descriptor with more than %d dimensions",
379383
ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS));
380384
}
385+
386+
public static String concat(String prefix, Object value, String suffix) {
387+
return JLA.concat(prefix, value, suffix);
388+
}
381389
}

0 commit comments

Comments
 (0)