8338937: Optimize the string concatenation of ClassDesc

Reviewed-by: liach
This commit is contained in:
Shaojin Wen 2024-09-04 22:45:17 +00:00 committed by Chen Liang
parent d4dfa0127f
commit 55312e1549
7 changed files with 53 additions and 18 deletions

View File

@ -4647,7 +4647,7 @@ public final class Class<T> implements java.io.Serializable,
return Wrapper.forPrimitiveType(this).basicTypeString();
if (isArray()) {
return "[" + componentType.descriptorString();
return "[".concat(componentType.descriptorString());
} else if (isHidden()) {
String name = getName();
int index = name.indexOf('/');
@ -4660,11 +4660,7 @@ public final class Class<T> implements java.io.Serializable,
.toString();
} else {
String name = getName().replace('.', '/');
return new StringBuilder(name.length() + 2)
.append('L')
.append(name)
.append(';')
.toString();
return StringConcatHelper.concat("L", name, ";");
}
}

View File

@ -783,4 +783,20 @@ final class StringConcatHelper {
}
throw new OutOfMemoryError("Overflow: String length out of range");
}
@ForceInline
private static String concat0(String prefix, String str, String suffix) {
byte coder = (byte) (prefix.coder() | str.coder() | suffix.coder());
int len = prefix.length() + str.length();
byte[] buf = newArrayWithSuffix(suffix, len, coder);
prepend(len, coder, buf, str, prefix);
return new String(buf, coder);
}
@ForceInline
static String concat(String prefix, Object value, String suffix) {
if (prefix == null) prefix = "null";
if (suffix == null) suffix = "null";
return concat0(prefix, stringOf(value), suffix);
}
}

View File

@ -2650,6 +2650,10 @@ public final class System {
return String.join(prefix, suffix, delimiter, elements, size);
}
public String concat(String prefix, Object value, String suffix) {
return StringConcatHelper.concat(prefix, value, suffix);
}
public Object classData(Class<?> c) {
return c.getClassData();
}

View File

@ -36,6 +36,7 @@ import static java.util.stream.Collectors.joining;
import static jdk.internal.constant.ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS;
import static jdk.internal.constant.ConstantUtils.arrayDepth;
import static jdk.internal.constant.ConstantUtils.binaryToInternal;
import static jdk.internal.constant.ConstantUtils.concat;
import static jdk.internal.constant.ConstantUtils.forPrimitiveType;
import static jdk.internal.constant.ConstantUtils.internalToBinary;
import static jdk.internal.constant.ConstantUtils.validateBinaryClassName;
@ -83,7 +84,7 @@ public sealed interface ClassDesc
*/
static ClassDesc of(String name) {
validateBinaryClassName(name);
return ClassDesc.ofDescriptor("L" + binaryToInternal(name) + ";");
return ClassDesc.ofDescriptor(concat("L", binaryToInternal(name), ";"));
}
/**
@ -109,7 +110,7 @@ public sealed interface ClassDesc
*/
static ClassDesc ofInternalName(String name) {
validateInternalClassName(name);
return ClassDesc.ofDescriptor("L" + name + ";");
return ClassDesc.ofDescriptor(concat("L", name, ";"));
}
/**
@ -132,8 +133,8 @@ public sealed interface ClassDesc
return of(className);
}
validateMemberName(className, false);
return ofDescriptor("L" + binaryToInternal(packageName) +
"/" + className + ";");
return ofDescriptor('L' + binaryToInternal(packageName) +
'/' + className + ';');
}
/**
@ -361,7 +362,7 @@ public sealed interface ClassDesc
ClassDesc c = this;
for (int i=0; i<depth; i++)
c = c.componentType();
return c.displayName() + "[]".repeat(depth);
return c.displayName().concat("[]".repeat(depth));
}
else
throw new IllegalStateException(descriptorString());

View File

@ -125,7 +125,7 @@ class InvokerBytecodeGenerator {
name = makeDumpableClassName(name);
}
this.name = name;
this.className = CLASS_PREFIX + name;
this.className = CLASS_PREFIX.concat(name);
this.classDesc = ClassDesc.ofInternalName(className);
this.lambdaForm = lambdaForm;
this.invokerName = invokerName;
@ -180,11 +180,16 @@ class InvokerBytecodeGenerator {
if (ctr == null) ctr = 0;
DUMP_CLASS_FILES_COUNTERS.put(className, ctr+1);
}
String sfx = ctr.toString();
while (sfx.length() < 3)
sfx = "0" + sfx;
className += sfx;
return className;
var buf = new StringBuilder(className.length() + 3).append(className);
int ctrVal = ctr;
if (ctrVal < 10) {
buf.repeat('0', 2);
} else if (ctrVal < 100) {
buf.append('0');
}
buf.append(ctrVal);
return buf.toString();
}
static class ClassData {

View File

@ -457,6 +457,11 @@ public interface JavaLangAccess {
*/
String join(String prefix, String suffix, String delimiter, String[] elements, int size);
/**
* Concatenation of prefix and suffix characters to a String for early bootstrap
*/
String concat(String prefix, Object value, String suffix);
/*
* Get the class data associated with the given class.
* @param c the class

View File

@ -35,12 +35,16 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import static jdk.internal.constant.PrimitiveClassDescImpl.*;
/**
* Helper methods for the implementation of {@code java.lang.constant}.
*/
public final class ConstantUtils {
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
/** an empty constant descriptor */
public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0];
public static final ClassDesc[] EMPTY_CLASSDESC = new ClassDesc[0];
@ -66,7 +70,7 @@ public final class ConstantUtils {
* @param binaryName a binary name
*/
public static ClassDesc binaryNameToDesc(String binaryName) {
return ReferenceClassDescImpl.ofValidated("L" + binaryToInternal(binaryName) + ";");
return ReferenceClassDescImpl.ofValidated(concat("L", binaryToInternal(binaryName), ";"));
}
/**
@ -378,4 +382,8 @@ public final class ConstantUtils {
"Cannot create an array type descriptor with more than %d dimensions",
ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS));
}
public static String concat(String prefix, Object value, String suffix) {
return JLA.concat(prefix, value, suffix);
}
}