8331187: Optimize MethodTypeDesc and ClassDesc.ofDescriptor for primitive types

Reviewed-by: jvernee, liach
This commit is contained in:
Claes Redestad 2024-04-26 14:06:53 +00:00
parent 5e2ced4b9e
commit 8bbd7251a5
6 changed files with 121 additions and 53 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -158,19 +158,10 @@ public sealed interface ClassDesc
* @see ClassDesc#ofInternalName(String)
*/
static ClassDesc ofDescriptor(String descriptor) {
requireNonNull(descriptor);
if (descriptor.isEmpty()) {
throw new IllegalArgumentException(
"not a valid reference type descriptor: " + descriptor);
}
int depth = ConstantUtils.arrayDepth(descriptor);
if (depth > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
throw new IllegalArgumentException(
"Cannot create an array type descriptor with more than " +
ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS + " dimensions");
}
// implicit null-check
return (descriptor.length() == 1)
? new PrimitiveClassDescImpl(descriptor)
? Wrapper.forPrimitiveType(descriptor.charAt(0)).primitiveClassDescriptor()
// will throw IAE on descriptor.length == 0 or if array dimensions too long
: new ReferenceClassDescImpl(descriptor);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -236,31 +236,31 @@ public final class ConstantDescs {
CD_Object, CD_Object);
/** {@link ClassDesc} representing the primitive type {@code int} */
public static final ClassDesc CD_int = ClassDesc.ofDescriptor("I");
public static final ClassDesc CD_int = new PrimitiveClassDescImpl("I");
/** {@link ClassDesc} representing the primitive type {@code long} */
public static final ClassDesc CD_long = ClassDesc.ofDescriptor("J");
public static final ClassDesc CD_long = new PrimitiveClassDescImpl("J");
/** {@link ClassDesc} representing the primitive type {@code float} */
public static final ClassDesc CD_float = ClassDesc.ofDescriptor("F");
public static final ClassDesc CD_float = new PrimitiveClassDescImpl("F");
/** {@link ClassDesc} representing the primitive type {@code double} */
public static final ClassDesc CD_double = ClassDesc.ofDescriptor("D");
public static final ClassDesc CD_double = new PrimitiveClassDescImpl("D");
/** {@link ClassDesc} representing the primitive type {@code short} */
public static final ClassDesc CD_short = ClassDesc.ofDescriptor("S");
public static final ClassDesc CD_short = new PrimitiveClassDescImpl("S");
/** {@link ClassDesc} representing the primitive type {@code byte} */
public static final ClassDesc CD_byte = ClassDesc.ofDescriptor("B");
public static final ClassDesc CD_byte = new PrimitiveClassDescImpl("B");
/** {@link ClassDesc} representing the primitive type {@code char} */
public static final ClassDesc CD_char = ClassDesc.ofDescriptor("C");
public static final ClassDesc CD_char = new PrimitiveClassDescImpl("C");
/** {@link ClassDesc} representing the primitive type {@code boolean} */
public static final ClassDesc CD_boolean = ClassDesc.ofDescriptor("Z");
public static final ClassDesc CD_boolean = new PrimitiveClassDescImpl("Z");
/** {@link ClassDesc} representing the primitive type {@code void} */
public static final ClassDesc CD_void = ClassDesc.ofDescriptor("V");
public static final ClassDesc CD_void = new PrimitiveClassDescImpl("V");
/**
* {@link MethodHandleDesc} representing {@link MethodHandles#classData(Lookup, String, Class) MethodHandles.classData}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,8 @@
*/
package java.lang.constant;
import sun.invoke.util.Wrapper;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@ -195,10 +197,10 @@ class ConstantUtils {
* @return the list of types
* @throws IllegalArgumentException if the descriptor string is not valid
*/
static List<String> parseMethodDescriptor(String descriptor) {
static List<ClassDesc> parseMethodDescriptor(String descriptor) {
int cur = 0, end = descriptor.length();
ArrayList<String> ptypes = new ArrayList<>();
ptypes.add(null); //placeholder for return type
ArrayList<ClassDesc> ptypes = new ArrayList<>();
ptypes.add(null); // placeholder for return type
if (cur >= end || descriptor.charAt(cur) != '(')
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
@ -208,7 +210,7 @@ class ConstantUtils {
int len = skipOverFieldSignature(descriptor, cur, end, false);
if (len == 0)
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
ptypes.add(descriptor.substring(cur, cur + len));
ptypes.add(resolveClassDesc(descriptor, cur, len));
cur += len;
}
if (cur >= end)
@ -218,10 +220,17 @@ class ConstantUtils {
int rLen = skipOverFieldSignature(descriptor, cur, end, true);
if (rLen == 0 || cur + rLen != end)
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
ptypes.set(0, descriptor.substring(cur, cur + rLen));
ptypes.set(0, resolveClassDesc(descriptor, cur, rLen));
return ptypes;
}
private static ClassDesc resolveClassDesc(String descriptor, int start, int len) {
if (len == 1) {
return Wrapper.forBasicType(descriptor.charAt(start)).primitiveClassDescriptor();
}
return ClassDesc.ofDescriptor(descriptor.substring(start, start + len));
}
private static final char JVM_SIGNATURE_ARRAY = '[';
private static final char JVM_SIGNATURE_BYTE = 'B';
private static final char JVM_SIGNATURE_CHAR = 'C';

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -88,21 +88,19 @@ final class MethodTypeDescImpl implements MethodTypeDesc {
* @jvms 4.3.3 Method Descriptors
*/
static MethodTypeDescImpl ofDescriptor(String descriptor) {
requireNonNull(descriptor);
// Implicit null-check of descriptor
List<ClassDesc> ptypes = ConstantUtils.parseMethodDescriptor(descriptor);
int args = ptypes.size() - 1;
ClassDesc[] paramTypes = args > 0
? ptypes.subList(1, args + 1).toArray(ConstantUtils.EMPTY_CLASSDESC)
: ConstantUtils.EMPTY_CLASSDESC;
List<String> types = ConstantUtils.parseMethodDescriptor(descriptor);
int paramCount = types.size() - 1;
var paramTypes = paramCount > 0 ? new ClassDesc[paramCount] : ConstantUtils.EMPTY_CLASSDESC;
for (int i = 0; i < paramCount; i++) {
paramTypes[i] = ClassDesc.ofDescriptor(types.get(i + 1));
}
MethodTypeDescImpl result = ofTrusted(ClassDesc.ofDescriptor(types.getFirst()), paramTypes);
MethodTypeDescImpl result = ofTrusted(ptypes.get(0), paramTypes);
result.cachedDescriptorString = descriptor;
return result;
}
@Override
public ClassDesc returnType() {
return returnType;