8338936: StringConcatFactory optimize the construction of MethodType and MethodTypeDesc

Reviewed-by: redestad, liach
This commit is contained in:
Shaojin Wen 2024-08-26 20:26:17 +00:00 committed by Chen Liang
parent 0c744ea7e7
commit 5ecbecfbca

View File

@ -29,6 +29,8 @@ package java.lang.invoke;
import jdk.internal.access.JavaLangAccess; import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets; import jdk.internal.access.SharedSecrets;
import jdk.internal.constant.ConstantUtils; import jdk.internal.constant.ConstantUtils;
import jdk.internal.constant.MethodTypeDescImpl;
import jdk.internal.constant.ReferenceClassDescImpl;
import jdk.internal.misc.VM; import jdk.internal.misc.VM;
import jdk.internal.util.ClassFileDumper; import jdk.internal.util.ClassFileDumper;
import jdk.internal.util.ReferenceKey; import jdk.internal.util.ReferenceKey;
@ -1085,32 +1087,32 @@ public final class StringConcatFactory {
static final MethodHandles.Lookup STR_LOOKUP = new MethodHandles.Lookup(String.class); static final MethodHandles.Lookup STR_LOOKUP = new MethodHandles.Lookup(String.class);
static final ClassDesc CD_CONCAT = ConstantUtils.binaryNameToDesc(CLASS_NAME); static final ClassDesc CD_CONCAT = ConstantUtils.binaryNameToDesc(CLASS_NAME);
static final ClassDesc CD_StringConcatHelper = ClassDesc.ofDescriptor("Ljava/lang/StringConcatHelper;"); static final ClassDesc CD_StringConcatHelper = ReferenceClassDescImpl.ofValidated("Ljava/lang/StringConcatHelper;");
static final ClassDesc CD_StringConcatBase = ClassDesc.ofDescriptor("Ljava/lang/StringConcatHelper$StringConcatBase;"); static final ClassDesc CD_StringConcatBase = ReferenceClassDescImpl.ofValidated("Ljava/lang/StringConcatHelper$StringConcatBase;");
static final ClassDesc CD_Array_byte = ClassDesc.ofDescriptor("[B"); static final ClassDesc CD_Array_byte = ReferenceClassDescImpl.ofValidated("[B");
static final ClassDesc CD_Array_String = ClassDesc.ofDescriptor("[Ljava/lang/String;"); static final ClassDesc CD_Array_String = ReferenceClassDescImpl.ofValidated("[Ljava/lang/String;");
static final MethodTypeDesc MTD_byte_char = MethodTypeDesc.of(CD_byte, CD_char); static final MethodTypeDesc MTD_byte_char = MethodTypeDescImpl.ofValidated(CD_byte, CD_char);
static final MethodTypeDesc MTD_byte = MethodTypeDesc.of(CD_byte); static final MethodTypeDesc MTD_byte = MethodTypeDescImpl.ofValidated(CD_byte);
static final MethodTypeDesc MTD_int = MethodTypeDesc.of(CD_int); static final MethodTypeDesc MTD_int = MethodTypeDescImpl.ofValidated(CD_int);
static final MethodTypeDesc MTD_int_int_boolean = MethodTypeDesc.of(CD_int, CD_int, CD_boolean); static final MethodTypeDesc MTD_int_int_boolean = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_boolean);
static final MethodTypeDesc MTD_int_int_char = MethodTypeDesc.of(CD_int, CD_int, CD_char); static final MethodTypeDesc MTD_int_int_char = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_char);
static final MethodTypeDesc MTD_int_int_int = MethodTypeDesc.of(CD_int, CD_int, CD_int); static final MethodTypeDesc MTD_int_int_int = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_int);
static final MethodTypeDesc MTD_int_int_long = MethodTypeDesc.of(CD_int, CD_int, CD_long); static final MethodTypeDesc MTD_int_int_long = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_long);
static final MethodTypeDesc MTD_int_int_String = MethodTypeDesc.of(CD_int, CD_int, CD_String); static final MethodTypeDesc MTD_int_int_String = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_String);
static final MethodTypeDesc MTD_String_float = MethodTypeDesc.of(CD_String, CD_float); static final MethodTypeDesc MTD_String_float = MethodTypeDescImpl.ofValidated(CD_String, CD_float);
static final MethodTypeDesc MTD_String_double = MethodTypeDesc.of(CD_String, CD_double); static final MethodTypeDesc MTD_String_double = MethodTypeDescImpl.ofValidated(CD_String, CD_double);
static final MethodTypeDesc MTD_String_Object = MethodTypeDesc.of(CD_String, CD_Object); static final MethodTypeDesc MTD_String_Object = MethodTypeDescImpl.ofValidated(CD_String, CD_Object);
static final MethodTypeDesc MTD_INIT = MethodTypeDesc.of(CD_void, CD_Array_String); static final MethodTypeDesc MTD_INIT = MethodTypeDescImpl.ofValidated(CD_void, CD_Array_String);
static final MethodTypeDesc MTD_NEW_ARRAY_SUFFIX = MethodTypeDesc.of(CD_Array_byte, CD_String, CD_int, CD_byte); static final MethodTypeDesc MTD_NEW_ARRAY_SUFFIX = MethodTypeDescImpl.ofValidated(CD_Array_byte, CD_String, CD_int, CD_byte);
static final MethodTypeDesc MTD_STRING_INIT = MethodTypeDesc.of(CD_void, CD_Array_byte, CD_byte); static final MethodTypeDesc MTD_STRING_INIT = MethodTypeDescImpl.ofValidated(CD_void, CD_Array_byte, CD_byte);
static final MethodTypeDesc PREPEND_int = MethodTypeDesc.of(CD_int, CD_int, CD_byte, CD_Array_byte, CD_int, CD_String); static final MethodTypeDesc PREPEND_int = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_byte, CD_Array_byte, CD_int, CD_String);
static final MethodTypeDesc PREPEND_long = MethodTypeDesc.of(CD_int, CD_int, CD_byte, CD_Array_byte, CD_long, CD_String); static final MethodTypeDesc PREPEND_long = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_byte, CD_Array_byte, CD_long, CD_String);
static final MethodTypeDesc PREPEND_boolean = MethodTypeDesc.of(CD_int, CD_int, CD_byte, CD_Array_byte, CD_boolean, CD_String); static final MethodTypeDesc PREPEND_boolean = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_byte, CD_Array_byte, CD_boolean, CD_String);
static final MethodTypeDesc PREPEND_char = MethodTypeDesc.of(CD_int, CD_int, CD_byte, CD_Array_byte, CD_char, CD_String); static final MethodTypeDesc PREPEND_char = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_byte, CD_Array_byte, CD_char, CD_String);
static final MethodTypeDesc PREPEND_String = MethodTypeDesc.of(CD_int, CD_int, CD_byte, CD_Array_byte, CD_String, CD_String); static final MethodTypeDesc PREPEND_String = MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_byte, CD_Array_byte, CD_String, CD_String);
static final RuntimeVisibleAnnotationsAttribute FORCE_INLINE = RuntimeVisibleAnnotationsAttribute.of(Annotation.of(ClassDesc.ofDescriptor("Ljdk/internal/vm/annotation/ForceInline;"))); static final RuntimeVisibleAnnotationsAttribute FORCE_INLINE = RuntimeVisibleAnnotationsAttribute.of(Annotation.of(ClassDesc.ofDescriptor("Ljdk/internal/vm/annotation/ForceInline;")));
@ -1166,7 +1168,7 @@ public final class StringConcatFactory {
} }
paramTypes[i] = cl; paramTypes[i] = cl;
} }
return changed ? MethodType.methodType(args.returnType(), paramTypes) : args; return changed ? MethodType.methodType(args.returnType(), paramTypes, true) : args;
} }
/** /**
@ -1191,24 +1193,36 @@ public final class StringConcatFactory {
var cl = concatArgs.parameterType(i); var cl = concatArgs.parameterType(i);
paramTypes[i + 4] = needStringOf(cl) ? CD_String : ConstantUtils.classDesc(cl); paramTypes[i + 4] = needStringOf(cl) ? CD_String : ConstantUtils.classDesc(cl);
} }
return MethodTypeDesc.of(CD_int, paramTypes); return MethodTypeDescImpl.ofValidated(CD_int, paramTypes);
} }
/** /**
* Construct the MethodType of the coder method, * Construct the MethodType of the coder method. The first parameter is the initialized coder.
* The first parameter is the initialized coder, Only parameter types that can be UTF16 are added. * Only parameter types which can be UTF16 are added. Returns null if no such parameter exists.
*/ */
private static MethodTypeDesc coderArgs(MethodType concatArgs) { private static MethodTypeDesc coderArgsIfMaybeUTF16(MethodType concatArgs) {
int parameterCount = concatArgs.parameterCount(); int parameterCount = concatArgs.parameterCount();
List<ClassDesc> paramTypes = new ArrayList<>();
paramTypes.add(CD_int); // init coder int maybeUTF16Count = 0;
for (int i = 0; i < parameterCount; i++) { for (int i = 0; i < parameterCount; i++) {
var cl = concatArgs.parameterType(i); if (maybeUTF16(concatArgs.parameterType(i))) {
if (maybeUTF16(cl)) { maybeUTF16Count++;
paramTypes.add(cl == char.class ? CD_char : CD_String);
} }
} }
return MethodTypeDesc.of(CD_int, paramTypes);
if (maybeUTF16Count == 0) {
return null;
}
var paramTypes = new ClassDesc[maybeUTF16Count + 1];
paramTypes[0] = CD_int; // init coder
for (int i = 0, paramIndex = 1; i < parameterCount; i++) {
var cl = concatArgs.parameterType(i);
if (maybeUTF16(cl)) {
paramTypes[paramIndex++] = cl == char.class ? CD_char : CD_String;
}
}
return MethodTypeDescImpl.ofValidated(CD_int, paramTypes);
} }
/** /**
@ -1223,7 +1237,7 @@ public final class StringConcatFactory {
var cl = concatArgs.parameterType(i); var cl = concatArgs.parameterType(i);
paramTypes[i + 1] = needStringOf(cl) ? CD_String : ConstantUtils.classDesc(cl); paramTypes[i + 1] = needStringOf(cl) ? CD_String : ConstantUtils.classDesc(cl);
} }
return MethodTypeDesc.of(CD_int, paramTypes); return MethodTypeDescImpl.ofValidated(CD_int, paramTypes);
} }
private static MethodHandle generate(Lookup lookup, MethodType args, String[] constants) throws Exception { private static MethodHandle generate(Lookup lookup, MethodType args, String[] constants) throws Exception {
@ -1250,7 +1264,7 @@ public final class StringConcatFactory {
} }
} }
MethodTypeDesc lengthArgs = lengthArgs(concatArgs), MethodTypeDesc lengthArgs = lengthArgs(concatArgs),
coderArgs = parameterMaybeUTF16(concatArgs) ? coderArgs(concatArgs) : null, coderArgs = coderArgsIfMaybeUTF16(concatArgs),
prependArgs = prependArgs(concatArgs); prependArgs = prependArgs(concatArgs);
byte[] classBytes = ClassFile.of().build(CD_CONCAT, byte[] classBytes = ClassFile.of().build(CD_CONCAT,
@ -1478,7 +1492,7 @@ public final class StringConcatFactory {
/* /*
* String[] constants = this.constants; * String[] constants = this.constants;
* suffix = constants[paranCount]; * suffix = constants[paramCount];
* length -= suffix.length(); * length -= suffix.length();
*/ */
cb.aload(thisSlot) cb.aload(thisSlot)
@ -1692,14 +1706,5 @@ public final class StringConcatFactory {
static boolean maybeUTF16(Class<?> cl) { static boolean maybeUTF16(Class<?> cl) {
return cl == char.class || !cl.isPrimitive(); return cl == char.class || !cl.isPrimitive();
} }
static boolean parameterMaybeUTF16(MethodType args) {
for (int i = 0; i < args.parameterCount(); i++) {
if (maybeUTF16(args.parameterType(i))) {
return true;
}
}
return false;
}
} }
} }