1
1
/*
2
- * Copyright (c) 2018, 2021 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2018, 2023 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
24
24
*/
25
25
package java .lang .constant ;
26
26
27
+ import jdk .internal .vm .annotation .Stable ;
28
+
27
29
import java .lang .invoke .MethodHandles ;
28
30
import java .lang .invoke .MethodType ;
29
31
import java .security .AccessController ;
30
32
import java .security .PrivilegedAction ;
31
33
import java .util .Arrays ;
32
34
import java .util .List ;
33
35
import java .util .Objects ;
36
+ import java .util .StringJoiner ;
34
37
35
38
import static java .util .Objects .requireNonNull ;
36
39
41
44
*/
42
45
final class MethodTypeDescImpl implements MethodTypeDesc {
43
46
private final ClassDesc returnType ;
44
- private final ClassDesc [] argTypes ;
47
+ private final @ Stable ClassDesc [] argTypes ;
48
+ private @ Stable String cachedDescriptorString ;
45
49
46
50
/**
47
51
* Constructs a {@linkplain MethodTypeDesc} with the specified return type
48
- * and parameter types
52
+ * and a trusted and already-validated parameter types array.
49
53
*
50
54
* @param returnType a {@link ClassDesc} describing the return type
51
- * @param argTypes {@link ClassDesc}s describing the parameter types
55
+ * @param validatedArgTypes {@link ClassDesc}s describing the trusted and validated parameter types
52
56
*/
53
- MethodTypeDescImpl (ClassDesc returnType , ClassDesc [] argTypes ) {
57
+ private MethodTypeDescImpl (ClassDesc returnType , ClassDesc [] validatedArgTypes ) {
54
58
this .returnType = requireNonNull (returnType );
55
- this .argTypes = requireNonNull (argTypes );
59
+ this .argTypes = requireNonNull (validatedArgTypes );
60
+ }
61
+
62
+ /**
63
+ * Constructs a {@linkplain MethodTypeDesc} with the specified return type
64
+ * and a trusted parameter types array, which will be validated.
65
+ *
66
+ * @param returnType a {@link ClassDesc} describing the return type
67
+ * @param trustedArgTypes {@link ClassDesc}s describing the trusted parameter types
68
+ */
69
+ static MethodTypeDescImpl ofTrusted (ClassDesc returnType , ClassDesc [] trustedArgTypes ) {
70
+ Objects .requireNonNull (returnType );
71
+ if (trustedArgTypes .length == 0 ) // implicit null check
72
+ return new MethodTypeDescImpl (returnType , ConstantUtils .EMPTY_CLASSDESC );
56
73
57
- for (ClassDesc cr : argTypes )
58
- if (cr .isPrimitive () && cr .descriptorString ().equals ( "V" ))
74
+ for (ClassDesc cd : trustedArgTypes )
75
+ if (cd .isPrimitive () && cd .descriptorString ().charAt ( 0 ) == 'V' ) // implicit null check
59
76
throw new IllegalArgumentException ("Void parameters not permitted" );
77
+
78
+ return new MethodTypeDescImpl (returnType , trustedArgTypes );
60
79
}
61
80
62
81
/**
@@ -70,9 +89,18 @@ final class MethodTypeDescImpl implements MethodTypeDesc {
70
89
*/
71
90
static MethodTypeDescImpl ofDescriptor (String descriptor ) {
72
91
requireNonNull (descriptor );
92
+
73
93
List <String > types = ConstantUtils .parseMethodDescriptor (descriptor );
74
- ClassDesc [] paramTypes = types .stream ().skip (1 ).map (ClassDesc ::ofDescriptor ).toArray (ClassDesc []::new );
75
- return new MethodTypeDescImpl (ClassDesc .ofDescriptor (types .get (0 )), paramTypes );
94
+
95
+ int paramCount = types .size () - 1 ;
96
+ var paramTypes = paramCount > 0 ? new ClassDesc [paramCount ] : ConstantUtils .EMPTY_CLASSDESC ;
97
+ for (int i = 0 ; i < paramCount ; i ++) {
98
+ paramTypes [i ] = ClassDesc .ofDescriptor (types .get (i + 1 ));
99
+ }
100
+
101
+ MethodTypeDescImpl result = ofTrusted (ClassDesc .ofDescriptor (types .getFirst ()), paramTypes );
102
+ result .cachedDescriptorString = descriptor ;
103
+ return result ;
76
104
}
77
105
78
106
@ Override
@@ -102,14 +130,14 @@ public ClassDesc[] parameterArray() {
102
130
103
131
@ Override
104
132
public MethodTypeDesc changeReturnType (ClassDesc returnType ) {
105
- return MethodTypeDesc . of (returnType , argTypes );
133
+ return new MethodTypeDescImpl (returnType , argTypes );
106
134
}
107
135
108
136
@ Override
109
137
public MethodTypeDesc changeParameterType (int index , ClassDesc paramType ) {
110
138
ClassDesc [] newArgs = argTypes .clone ();
111
139
newArgs [index ] = paramType ;
112
- return MethodTypeDesc . of (returnType , newArgs );
140
+ return ofTrusted (returnType , newArgs );
113
141
}
114
142
115
143
@ Override
@@ -120,18 +148,33 @@ public MethodTypeDesc dropParameterTypes(int start, int end) {
120
148
ClassDesc [] newArgs = new ClassDesc [argTypes .length - (end - start )];
121
149
System .arraycopy (argTypes , 0 , newArgs , 0 , start );
122
150
System .arraycopy (argTypes , end , newArgs , start , argTypes .length - end );
123
- return MethodTypeDesc . of (returnType , newArgs );
151
+ return ofTrusted (returnType , newArgs );
124
152
}
125
153
126
154
@ Override
127
155
public MethodTypeDesc insertParameterTypes (int pos , ClassDesc ... paramTypes ) {
128
156
if (pos < 0 || pos > argTypes .length )
129
157
throw new IndexOutOfBoundsException (pos );
158
+
130
159
ClassDesc [] newArgs = new ClassDesc [argTypes .length + paramTypes .length ];
131
160
System .arraycopy (argTypes , 0 , newArgs , 0 , pos );
132
161
System .arraycopy (paramTypes , 0 , newArgs , pos , paramTypes .length );
133
162
System .arraycopy (argTypes , pos , newArgs , pos +paramTypes .length , argTypes .length - pos );
134
- return MethodTypeDesc .of (returnType , newArgs );
163
+
164
+ return ofTrusted (returnType , newArgs );
165
+ }
166
+
167
+ @ Override
168
+ public String descriptorString () {
169
+ var desc = this .cachedDescriptorString ;
170
+ if (desc != null )
171
+ return desc ;
172
+
173
+ var sj = new StringJoiner ("" , "(" , ")" + returnType ().descriptorString ());
174
+ for (int i = 0 ; i < parameterCount (); i ++) {
175
+ sj .add (parameterType (i ).descriptorString ());
176
+ }
177
+ return cachedDescriptorString = sj .toString ();
135
178
}
136
179
137
180
@ Override
0 commit comments