Skip to content

Commit 25c2f48

Browse files
committed
8338544: Dedicated Array class descriptor implementation
Reviewed-by: redestad, mchung, jvernee
1 parent 158b93d commit 25c2f48

20 files changed

+618
-397
lines changed

src/java.base/share/classes/java/lang/constant/ClassDesc.java

Lines changed: 26 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,13 @@
2626

2727
import java.lang.invoke.MethodHandles;
2828
import java.lang.invoke.TypeDescriptor;
29-
import java.util.stream.Stream;
3029

30+
import jdk.internal.constant.ArrayClassDescImpl;
31+
import jdk.internal.constant.ConstantUtils;
3132
import jdk.internal.constant.PrimitiveClassDescImpl;
32-
import jdk.internal.constant.ReferenceClassDescImpl;
33-
import sun.invoke.util.Wrapper;
33+
import jdk.internal.constant.ClassOrInterfaceDescImpl;
3434

35-
import static java.util.stream.Collectors.joining;
36-
import static jdk.internal.constant.ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS;
37-
import static jdk.internal.constant.ConstantUtils.arrayDepth;
38-
import static jdk.internal.constant.ConstantUtils.binaryToInternal;
39-
import static jdk.internal.constant.ConstantUtils.concat;
40-
import static jdk.internal.constant.ConstantUtils.forPrimitiveType;
41-
import static jdk.internal.constant.ConstantUtils.internalToBinary;
42-
import static jdk.internal.constant.ConstantUtils.validateBinaryClassName;
43-
import static jdk.internal.constant.ConstantUtils.validateInternalClassName;
44-
import static jdk.internal.constant.ConstantUtils.validateMemberName;
35+
import static jdk.internal.constant.ConstantUtils.*;
4536

4637
/**
4738
* A <a href="package-summary.html#nominal">nominal descriptor</a> for a
@@ -64,7 +55,8 @@ public sealed interface ClassDesc
6455
extends ConstantDesc,
6556
TypeDescriptor.OfField<ClassDesc>
6657
permits PrimitiveClassDescImpl,
67-
ReferenceClassDescImpl {
58+
ClassOrInterfaceDescImpl,
59+
ArrayClassDescImpl {
6860

6961
/**
7062
* Returns a {@linkplain ClassDesc} for a class or interface type,
@@ -84,7 +76,7 @@ public sealed interface ClassDesc
8476
*/
8577
static ClassDesc of(String name) {
8678
validateBinaryClassName(name);
87-
return ClassDesc.ofDescriptor(concat("L", binaryToInternal(name), ";"));
79+
return ConstantUtils.binaryNameToDesc(name);
8880
}
8981

9082
/**
@@ -110,7 +102,7 @@ static ClassDesc of(String name) {
110102
*/
111103
static ClassDesc ofInternalName(String name) {
112104
validateInternalClassName(name);
113-
return ClassDesc.ofDescriptor(concat("L", name, ";"));
105+
return ConstantUtils.internalNameToDesc(name);
114106
}
115107

116108
/**
@@ -129,11 +121,11 @@ static ClassDesc ofInternalName(String name) {
129121
*/
130122
static ClassDesc of(String packageName, String className) {
131123
validateBinaryClassName(packageName);
124+
validateMemberName(className, false);
132125
if (packageName.isEmpty()) {
133-
return of(className);
126+
return internalNameToDesc(className);
134127
}
135-
validateMemberName(className, false);
136-
return ofDescriptor('L' + binaryToInternal(packageName) +
128+
return ClassOrInterfaceDescImpl.ofValidated('L' + binaryToInternal(packageName) +
137129
'/' + className + ';');
138130
}
139131

@@ -168,7 +160,7 @@ static ClassDesc ofDescriptor(String descriptor) {
168160
return (descriptor.length() == 1)
169161
? forPrimitiveType(descriptor, 0)
170162
// will throw IAE on descriptor.length == 0 or if array dimensions too long
171-
: ReferenceClassDescImpl.of(descriptor);
163+
: parseReferenceTypeDesc(descriptor);
172164
}
173165

174166
/**
@@ -180,20 +172,7 @@ static ClassDesc ofDescriptor(String descriptor) {
180172
* ClassDesc} would have an array rank of greater than 255
181173
* @jvms 4.4.1 The CONSTANT_Class_info Structure
182174
*/
183-
default ClassDesc arrayType() {
184-
String desc = descriptorString();
185-
int depth = arrayDepth(desc);
186-
if (depth >= MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
187-
throw new IllegalStateException(
188-
"Cannot create an array type descriptor with more than " +
189-
MAX_ARRAY_TYPE_DESC_DIMENSIONS + " dimensions");
190-
}
191-
String newDesc = "[".concat(desc);
192-
if (desc.length() == 1 && desc.charAt(0) == 'V') {
193-
throw new IllegalArgumentException("not a valid reference type descriptor: " + newDesc);
194-
}
195-
return ReferenceClassDescImpl.ofValidated(newDesc);
196-
}
175+
ClassDesc arrayType();
197176

198177
/**
199178
* Returns a {@linkplain ClassDesc} for an array type of the specified rank,
@@ -206,24 +185,7 @@ default ClassDesc arrayType() {
206185
* greater than 255
207186
* @jvms 4.4.1 The CONSTANT_Class_info Structure
208187
*/
209-
default ClassDesc arrayType(int rank) {
210-
if (rank <= 0) {
211-
throw new IllegalArgumentException("rank " + rank + " is not a positive value");
212-
}
213-
String desc = descriptorString();
214-
long currentDepth = arrayDepth(desc);
215-
long netRank = currentDepth + rank;
216-
if (netRank > MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
217-
throw new IllegalArgumentException("rank: " + netRank +
218-
" exceeds maximum supported dimension of " +
219-
MAX_ARRAY_TYPE_DESC_DIMENSIONS);
220-
}
221-
String newDesc = new StringBuilder(desc.length() + rank).repeat('[', rank).append(desc).toString();
222-
if (desc.length() == 1 && desc.charAt(0) == 'V') {
223-
throw new IllegalArgumentException("not a valid reference type descriptor: " + newDesc);
224-
}
225-
return ReferenceClassDescImpl.ofValidated(newDesc);
226-
}
188+
ClassDesc arrayType(int rank);
227189

228190
/**
229191
* Returns a {@linkplain ClassDesc} for a nested class of the class or
@@ -243,13 +205,7 @@ default ClassDesc arrayType(int rank) {
243205
* @throws IllegalArgumentException if the nested class name is invalid
244206
*/
245207
default ClassDesc nested(String nestedName) {
246-
validateMemberName(nestedName, false);
247-
if (!isClassOrInterface())
248-
throw new IllegalStateException("Outer class is not a class or interface type");
249-
String desc = descriptorString();
250-
StringBuilder sb = new StringBuilder(desc.length() + nestedName.length() + 1);
251-
sb.append(desc, 0, desc.length() - 1).append('$').append(nestedName).append(';');
252-
return ReferenceClassDescImpl.ofValidated(sb.toString());
208+
throw new IllegalStateException("Outer class is not a class or interface type");
253209
}
254210

255211
/**
@@ -266,16 +222,7 @@ default ClassDesc nested(String nestedName) {
266222
* @throws IllegalArgumentException if the nested class name is invalid
267223
*/
268224
default ClassDesc nested(String firstNestedName, String... moreNestedNames) {
269-
if (!isClassOrInterface())
270-
throw new IllegalStateException("Outer class is not a class or interface type");
271-
validateMemberName(firstNestedName, false);
272-
// implicit null-check
273-
for (String addNestedNames : moreNestedNames) {
274-
validateMemberName(addNestedNames, false);
275-
}
276-
return moreNestedNames.length == 0
277-
? nested(firstNestedName)
278-
: nested(firstNestedName + Stream.of(moreNestedNames).collect(joining("$", "$", "")));
225+
throw new IllegalStateException("Outer class is not a class or interface type");
279226
}
280227

281228
/**
@@ -284,7 +231,7 @@ default ClassDesc nested(String firstNestedName, String... moreNestedNames) {
284231
* @return whether this {@linkplain ClassDesc} describes an array type
285232
*/
286233
default boolean isArray() {
287-
return descriptorString().charAt(0) == '[';
234+
return false;
288235
}
289236

290237
/**
@@ -293,7 +240,7 @@ default boolean isArray() {
293240
* @return whether this {@linkplain ClassDesc} describes a primitive type
294241
*/
295242
default boolean isPrimitive() {
296-
return descriptorString().length() == 1;
243+
return false;
297244
}
298245

299246
/**
@@ -302,7 +249,7 @@ default boolean isPrimitive() {
302249
* @return whether this {@linkplain ClassDesc} describes a class or interface type
303250
*/
304251
default boolean isClassOrInterface() {
305-
return descriptorString().charAt(0) == 'L';
252+
return false;
306253
}
307254

308255
/**
@@ -313,14 +260,6 @@ default boolean isClassOrInterface() {
313260
* if this descriptor does not describe an array type
314261
*/
315262
default ClassDesc componentType() {
316-
if (isArray()) {
317-
String desc = descriptorString();
318-
if (desc.length() == 2) {
319-
return Wrapper.forBasicType(desc.charAt(1)).basicClassDescriptor();
320-
} else {
321-
return ReferenceClassDescImpl.ofValidated(desc.substring(1));
322-
}
323-
}
324263
return null;
325264
}
326265

@@ -332,41 +271,17 @@ default ClassDesc componentType() {
332271
* default package, or this {@linkplain ClassDesc} does not describe a class or interface type
333272
*/
334273
default String packageName() {
335-
if (!isClassOrInterface())
336-
return "";
337-
String desc = descriptorString();
338-
int index = desc.lastIndexOf('/');
339-
return (index == -1) ? "" : internalToBinary(desc.substring(1, index));
274+
return "";
340275
}
341276

342277
/**
343-
* Returns a human-readable name for the type described by this descriptor.
344-
*
345-
* @implSpec
346-
* <p>The default implementation returns the simple name
347-
* (e.g., {@code int}) for primitive types, the unqualified class name
348-
* for class or interface types, or the display name of the component type
349-
* suffixed with the appropriate number of {@code []} pairs for array types.
350-
*
351-
* @return the human-readable name
278+
* {@return a human-readable name for this {@code ClassDesc}}
279+
* For primitive types, this method returns the simple name (such as {@code int}).
280+
* For class or interface types, this method returns the unqualified class name.
281+
* For array types, this method returns the human-readable name of the component
282+
* type suffixed with the appropriate number of {@code []} pairs.
352283
*/
353-
default String displayName() {
354-
if (isPrimitive())
355-
return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveSimpleName();
356-
else if (isClassOrInterface()) {
357-
String desc = descriptorString();
358-
return desc.substring(Math.max(1, desc.lastIndexOf('/') + 1), desc.length() - 1);
359-
}
360-
else if (isArray()) {
361-
int depth = arrayDepth(descriptorString());
362-
ClassDesc c = this;
363-
for (int i=0; i<depth; i++)
364-
c = c.componentType();
365-
return c.displayName().concat("[]".repeat(depth));
366-
}
367-
else
368-
throw new IllegalStateException(descriptorString());
369-
}
284+
String displayName();
370285

371286
/**
372287
* Returns a field type descriptor string for this type

0 commit comments

Comments
 (0)