30 import java.lang.ref.Reference; |
30 import java.lang.ref.Reference; |
31 import java.lang.ref.ReferenceQueue; |
31 import java.lang.ref.ReferenceQueue; |
32 import java.util.Arrays; |
32 import java.util.Arrays; |
33 import java.util.Collections; |
33 import java.util.Collections; |
34 import java.util.List; |
34 import java.util.List; |
|
35 import java.util.Objects; |
35 import java.util.concurrent.ConcurrentMap; |
36 import java.util.concurrent.ConcurrentMap; |
36 import java.util.concurrent.ConcurrentHashMap; |
37 import java.util.concurrent.ConcurrentHashMap; |
37 import sun.invoke.util.BytecodeDescriptor; |
38 import sun.invoke.util.BytecodeDescriptor; |
38 import static java.lang.invoke.MethodHandleStatics.*; |
39 import static java.lang.invoke.MethodHandleStatics.*; |
39 import sun.invoke.util.VerifyType; |
40 import sun.invoke.util.VerifyType; |
96 |
97 |
97 // The remaining fields are caches of various sorts: |
98 // The remaining fields are caches of various sorts: |
98 private @Stable MethodTypeForm form; // erased form, plus cached data about primitives |
99 private @Stable MethodTypeForm form; // erased form, plus cached data about primitives |
99 private @Stable MethodType wrapAlt; // alternative wrapped/unwrapped version |
100 private @Stable MethodType wrapAlt; // alternative wrapped/unwrapped version |
100 private @Stable Invokers invokers; // cache of handy higher-order adapters |
101 private @Stable Invokers invokers; // cache of handy higher-order adapters |
|
102 private @Stable String methodDescriptor; // cache for toMethodDescriptorString |
101 |
103 |
102 /** |
104 /** |
103 * Check the given parameters for validity and store them into the final fields. |
105 * Check the given parameters for validity and store them into the final fields. |
104 */ |
106 */ |
105 private MethodType(Class<?> rtype, Class<?>[] ptypes) { |
107 private MethodType(Class<?> rtype, Class<?>[] ptypes, boolean trusted) { |
106 checkRtype(rtype); |
108 checkRtype(rtype); |
107 checkPtypes(ptypes); |
109 checkPtypes(ptypes); |
|
110 this.rtype = rtype; |
|
111 // defensively copy the array passed in by the user |
|
112 this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length); |
|
113 } |
|
114 |
|
115 /** |
|
116 * Construct a temporary unchecked instance of MethodType for use only as a key to the intern table. |
|
117 * Does not check the given parameters for validity, and must be discarded after it is used as a searching key. |
|
118 * The parameters are reversed for this constructor, so that is is not accidentally used. |
|
119 */ |
|
120 private MethodType(Class<?>[] ptypes, Class<?> rtype) { |
108 this.rtype = rtype; |
121 this.rtype = rtype; |
109 this.ptypes = ptypes; |
122 this.ptypes = ptypes; |
110 } |
123 } |
111 |
124 |
112 /*trusted*/ MethodTypeForm form() { return form; } |
125 /*trusted*/ MethodTypeForm form() { return form; } |
144 * {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}. |
157 * {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}. |
145 */ |
158 */ |
146 /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1; // deduct one more for invoker |
159 /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1; // deduct one more for invoker |
147 |
160 |
148 private static void checkRtype(Class<?> rtype) { |
161 private static void checkRtype(Class<?> rtype) { |
149 rtype.equals(rtype); // null check |
162 Objects.requireNonNull(rtype); |
150 } |
163 } |
151 private static int checkPtype(Class<?> ptype) { |
164 private static void checkPtype(Class<?> ptype) { |
152 ptype.getClass(); //NPE |
165 Objects.requireNonNull(ptype); |
153 if (ptype == void.class) |
166 if (ptype == void.class) |
154 throw newIllegalArgumentException("parameter type cannot be void"); |
167 throw newIllegalArgumentException("parameter type cannot be void"); |
155 if (ptype == double.class || ptype == long.class) return 1; |
|
156 return 0; |
|
157 } |
168 } |
158 /** Return number of extra slots (count of long/double args). */ |
169 /** Return number of extra slots (count of long/double args). */ |
159 private static int checkPtypes(Class<?>[] ptypes) { |
170 private static int checkPtypes(Class<?>[] ptypes) { |
160 int slots = 0; |
171 int slots = 0; |
161 for (Class<?> ptype : ptypes) { |
172 for (Class<?> ptype : ptypes) { |
162 slots += checkPtype(ptype); |
173 checkPtype(ptype); |
|
174 if (ptype == double.class || ptype == long.class) { |
|
175 slots++; |
|
176 } |
163 } |
177 } |
164 checkSlotCount(ptypes.length + slots); |
178 checkSlotCount(ptypes.length + slots); |
165 return slots; |
179 return slots; |
166 } |
180 } |
167 static void checkSlotCount(int count) { |
181 static void checkSlotCount(int count) { |
282 * @param trusted whether the ptypes can be used without cloning |
296 * @param trusted whether the ptypes can be used without cloning |
283 * @return the unique method type of the desired structure |
297 * @return the unique method type of the desired structure |
284 */ |
298 */ |
285 /*trusted*/ static |
299 /*trusted*/ static |
286 MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) { |
300 MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) { |
|
301 MethodType mt = internTable.get(new MethodType(ptypes, rtype)); |
|
302 if (mt != null) |
|
303 return mt; |
287 if (ptypes.length == 0) { |
304 if (ptypes.length == 0) { |
288 ptypes = NO_PTYPES; trusted = true; |
305 ptypes = NO_PTYPES; trusted = true; |
289 } |
306 } |
290 MethodType mt1 = new MethodType(rtype, ptypes); |
307 mt = new MethodType(rtype, ptypes, trusted); |
291 MethodType mt0 = internTable.get(mt1); |
|
292 if (mt0 != null) |
|
293 return mt0; |
|
294 if (!trusted) |
|
295 // defensively copy the array passed in by the user |
|
296 mt1 = new MethodType(rtype, ptypes.clone()); |
|
297 // promote the object to the Real Thing, and reprobe |
308 // promote the object to the Real Thing, and reprobe |
298 MethodTypeForm form = MethodTypeForm.findForm(mt1); |
309 mt.form = MethodTypeForm.findForm(mt); |
299 mt1.form = form; |
310 return internTable.add(mt); |
300 return internTable.add(mt1); |
|
301 } |
311 } |
302 private static final MethodType[] objectOnlyTypes = new MethodType[20]; |
312 private static final MethodType[] objectOnlyTypes = new MethodType[20]; |
303 |
313 |
304 /** |
314 /** |
305 * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array. |
315 * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array. |
917 * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString}, |
927 * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString}, |
918 * because the latter requires a suitable class loader argument. |
928 * because the latter requires a suitable class loader argument. |
919 * @return the bytecode type descriptor representation |
929 * @return the bytecode type descriptor representation |
920 */ |
930 */ |
921 public String toMethodDescriptorString() { |
931 public String toMethodDescriptorString() { |
922 return BytecodeDescriptor.unparse(this); |
932 String desc = methodDescriptor; |
|
933 if (desc == null) { |
|
934 desc = BytecodeDescriptor.unparse(this); |
|
935 methodDescriptor = desc; |
|
936 } |
|
937 return desc; |
923 } |
938 } |
924 |
939 |
925 /*non-public*/ static String toFieldDescriptorString(Class<?> cls) { |
940 /*non-public*/ static String toFieldDescriptorString(Class<?> cls) { |
926 return BytecodeDescriptor.unparse(cls); |
941 return BytecodeDescriptor.unparse(cls); |
927 } |
942 } |