Skip to content

Commit

Permalink
8294062: Improve parsing performance of j.l.c.MethodTypeDesc
Browse files Browse the repository at this point in the history
Reviewed-by: psandoz
  • Loading branch information
asotona committed Sep 21, 2022
1 parent c6be2cd commit 9f90eb0
Showing 1 changed file with 22 additions and 31 deletions.
53 changes: 22 additions & 31 deletions src/java.base/share/classes/java/lang/constant/ConstantUtils.java
Expand Up @@ -137,6 +137,7 @@ static String dropFirstAndLastChar(String s) {
static List<String> parseMethodDescriptor(String descriptor) {
int cur = 0, end = descriptor.length();
ArrayList<String> ptypes = new ArrayList<>();
ptypes.add(null); //placeholder for return type

if (cur >= end || descriptor.charAt(cur) != '(')
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
Expand All @@ -156,7 +157,7 @@ static List<String> parseMethodDescriptor(String descriptor) {
int rLen = skipOverFieldSignature(descriptor, cur, end, true);
if (rLen == 0 || cur + rLen != end)
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
ptypes.add(0, descriptor.substring(cur, cur + rLen));
ptypes.set(0, descriptor.substring(cur, cur + rLen));
return ptypes;
}

Expand Down Expand Up @@ -203,16 +204,27 @@ static int skipOverFieldSignature(String descriptor, int start, int end, boolean
case JVM_SIGNATURE_DOUBLE:
return index - start + 1;
case JVM_SIGNATURE_CLASS:
// Skip leading 'L' and ignore first appearance of ';'
index++;
int indexOfSemi = descriptor.indexOf(';', index);
if (indexOfSemi != -1) {
String unqualifiedName = descriptor.substring(index, indexOfSemi);
boolean legal = verifyUnqualifiedClassName(unqualifiedName);
if (!legal) {
return 0;
// state variable for detection of illegal states, such as:
// empty unqualified name, '//', leading '/', or trailing '/'
boolean legal = false;
while (++index < end) {
switch (descriptor.charAt(index)) {
case ';' -> {
// illegal state on parser exit indicates empty unqualified name or trailing '/'
return legal ? index - start + 1 : 0;
}
case '.', '[' -> {
// do not permit '.' or '['
return 0;
}
case '/' -> {
// illegal state when received '/' indicates '//' or leading '/'
if (!legal) return 0;
legal = false;
}
default ->
legal = true;
}
return index - start + unqualifiedName.length() + 1;
}
return 0;
case JVM_SIGNATURE_ARRAY:
Expand All @@ -231,25 +243,4 @@ static int skipOverFieldSignature(String descriptor, int start, int end, boolean
}
return 0;
}

static boolean verifyUnqualifiedClassName(String name) {
for (int index = 0; index < name.length(); index++) {
char ch = name.charAt(index);
if (ch < 128) {
if (ch == '.' || ch == ';' || ch == '[' ) {
return false; // do not permit '.', ';', or '['
}
if (ch == '/') {
// check for '//' or leading or trailing '/' which are not legal
// unqualified name must not be empty
if (index == 0 || index + 1 >= name.length() || name.charAt(index + 1) == '/') {
return false;
}
}
} else {
index ++;
}
}
return true;
}
}

0 comments on commit 9f90eb0

Please sign in to comment.