Skip to content

Commit 9f90eb0

Browse files
committedSep 21, 2022
8294062: Improve parsing performance of j.l.c.MethodTypeDesc
Reviewed-by: psandoz
1 parent c6be2cd commit 9f90eb0

File tree

1 file changed

+22
-31
lines changed

1 file changed

+22
-31
lines changed
 

‎src/java.base/share/classes/java/lang/constant/ConstantUtils.java

+22-31
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ static String dropFirstAndLastChar(String s) {
137137
static List<String> parseMethodDescriptor(String descriptor) {
138138
int cur = 0, end = descriptor.length();
139139
ArrayList<String> ptypes = new ArrayList<>();
140+
ptypes.add(null); //placeholder for return type
140141

141142
if (cur >= end || descriptor.charAt(cur) != '(')
142143
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
@@ -156,7 +157,7 @@ static List<String> parseMethodDescriptor(String descriptor) {
156157
int rLen = skipOverFieldSignature(descriptor, cur, end, true);
157158
if (rLen == 0 || cur + rLen != end)
158159
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
159-
ptypes.add(0, descriptor.substring(cur, cur + rLen));
160+
ptypes.set(0, descriptor.substring(cur, cur + rLen));
160161
return ptypes;
161162
}
162163

@@ -203,16 +204,27 @@ static int skipOverFieldSignature(String descriptor, int start, int end, boolean
203204
case JVM_SIGNATURE_DOUBLE:
204205
return index - start + 1;
205206
case JVM_SIGNATURE_CLASS:
206-
// Skip leading 'L' and ignore first appearance of ';'
207-
index++;
208-
int indexOfSemi = descriptor.indexOf(';', index);
209-
if (indexOfSemi != -1) {
210-
String unqualifiedName = descriptor.substring(index, indexOfSemi);
211-
boolean legal = verifyUnqualifiedClassName(unqualifiedName);
212-
if (!legal) {
213-
return 0;
207+
// state variable for detection of illegal states, such as:
208+
// empty unqualified name, '//', leading '/', or trailing '/'
209+
boolean legal = false;
210+
while (++index < end) {
211+
switch (descriptor.charAt(index)) {
212+
case ';' -> {
213+
// illegal state on parser exit indicates empty unqualified name or trailing '/'
214+
return legal ? index - start + 1 : 0;
215+
}
216+
case '.', '[' -> {
217+
// do not permit '.' or '['
218+
return 0;
219+
}
220+
case '/' -> {
221+
// illegal state when received '/' indicates '//' or leading '/'
222+
if (!legal) return 0;
223+
legal = false;
224+
}
225+
default ->
226+
legal = true;
214227
}
215-
return index - start + unqualifiedName.length() + 1;
216228
}
217229
return 0;
218230
case JVM_SIGNATURE_ARRAY:
@@ -231,25 +243,4 @@ static int skipOverFieldSignature(String descriptor, int start, int end, boolean
231243
}
232244
return 0;
233245
}
234-
235-
static boolean verifyUnqualifiedClassName(String name) {
236-
for (int index = 0; index < name.length(); index++) {
237-
char ch = name.charAt(index);
238-
if (ch < 128) {
239-
if (ch == '.' || ch == ';' || ch == '[' ) {
240-
return false; // do not permit '.', ';', or '['
241-
}
242-
if (ch == '/') {
243-
// check for '//' or leading or trailing '/' which are not legal
244-
// unqualified name must not be empty
245-
if (index == 0 || index + 1 >= name.length() || name.charAt(index + 1) == '/') {
246-
return false;
247-
}
248-
}
249-
} else {
250-
index ++;
251-
}
252-
}
253-
return true;
254-
}
255246
}

0 commit comments

Comments
 (0)
Please sign in to comment.