On Sat, 17 Aug 2024 12:16:03 GMT, Chen Liang <li...@openjdk.org> 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

Reply via email to