On Sat, 17 Aug 2024 12:16:03 GMT, Chen Liang <[email protected]> wrote:
>> The current implementation of ofDescriptor puts return type and parameter
>> types together in an ArrayList, and then splits them into return type and
>> array of parameter types. This ArrayList creation is unnecessary,
>> considering most descriptors only have few parameter types.
>>
>> By splitting return type and parameter types separately and scanning the
>> descriptor first to get the number of parameters, we can just allocate an
>> exact, trusted array for the resulting MethodTypeDesc without copy.
>
> src/java.base/share/classes/jdk/internal/constant/MethodTypeDescImpl.java
> line 113:
>
>> 111: || (rightBracket = (descriptor.charAt(1) == ')' ? 1 :
>> descriptor.lastIndexOf(')'))) <= 0
>> 112: || (len = descriptor.length() - rightBracket - 1) == 0
>> 113: || (len != 1 && len !=
>> ConstantUtils.skipOverFieldSignature(descriptor, rightBracket + 1,
>> descriptor.length()))
>
> Has this be tested against input values like `()A`? I would prefer to fail
> explicitly with `descriptor.charAt(rightBracket + 1) == 'V'` instead of using
> `len != 1` and relying on `Wrapper.forBasicType`.
I have tested that `()A` will report an error. If length == 1, rely on
Wrapper.forBasicType to detect illegal input.
> src/java.base/share/classes/jdk/internal/constant/MethodTypeDescImpl.java
> line 125:
>
>> 123: int paramCount = 0;
>> 124: for (int cur = start; cur < end; ) {
>> 125: int len = ConstantUtils.skipOverFieldSignature(descriptor,
>> cur, end, false);
>
> I recall skipping over signatures is the main reason descriptor parsing is
> slow. What is the benchmark result if you allocate a buffer array like
> `short[] offsets = new short[Math.min(end - start, 255)]` or a `BitSet
> offsets = new BitSet(end - start)`?
Allocating a buffer will slow down, so I used a long, with each 8 bits storing
a parameter length, which can improve performance when the number of parameters
is <= 8.
> src/java.base/share/classes/jdk/internal/constant/MethodTypeDescImpl.java
> line 158:
>
>> 156: }
>> 157: if (len == 0) {
>> 158: len = ConstantUtils.skipOverFieldSignature(descriptor,
>> cur, end);
>
> This can use a simpler version of skip that doesn't validate, like:
>
> int start = cur;
> while (descriptor.charAt(cur) == '[') {
> cur++;
> }
> if (descriptor.charAt(cur++) == 'L') {
> cur = descriptor.indexOf(';', cur) + 1;
> }
> paramTypes[paramIndex++] = ConstantUtils.resolveClassDesc(descriptor, start,
> cur - start);
Now this version merges the loops, your suggestion doesn't handle paramIndex >=
8, and it won't be faster, the current version of skipOverFieldSignature
performs well enough.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/20611#discussion_r1720769514
PR Review Comment: https://git.openjdk.org/jdk/pull/20611#discussion_r1720452515
PR Review Comment: https://git.openjdk.org/jdk/pull/20611#discussion_r1720768233