42 * method, and the static types of the captured lambda arguments, and link a call site which, when invoked, |
45 * method, and the static types of the captured lambda arguments, and link a call site which, when invoked, |
43 * produces the lambda object. |
46 * produces the lambda object. |
44 * |
47 * |
45 * <p>When parameterized types are used, the instantiated type of the functional interface method may be different |
48 * <p>When parameterized types are used, the instantiated type of the functional interface method may be different |
46 * from that in the functional interface. For example, consider |
49 * from that in the functional interface. For example, consider |
47 * <code>interface I<T> { int m(T x); }</code> if this functional interface type is used in a lambda |
50 * {@code interface I<T> { int m(T x); }} if this functional interface type is used in a lambda |
48 * <code>I<Byte> v = ...</code>, we need both the actual functional interface method which has the signature |
51 * {@code I<Byte>; v = ...}, we need both the actual functional interface method which has the signature |
49 * <code>(Object)int</code> and the erased instantiated type of the functional interface method (or simply |
52 * {@code (Object)int} and the erased instantiated type of the functional interface method (or simply |
50 * <I>instantiated method type</I>), which has signature |
53 * <I>instantiated method type</I>), which has signature |
51 * <code>(Byte)int</code>. |
54 * {@code (Byte)int}. |
52 * |
|
53 * <p>While functional interfaces only have a single abstract method from the language perspective (concrete |
|
54 * methods in Object are and default methods may be present), at the bytecode level they may actually have multiple |
|
55 * methods because of the need for bridge methods. Invoking any of these methods on the lambda object will result |
|
56 * in invoking the implementation method. |
|
57 * |
55 * |
58 * <p>The argument list of the implementation method and the argument list of the functional interface method(s) |
56 * <p>The argument list of the implementation method and the argument list of the functional interface method(s) |
59 * may differ in several ways. The implementation methods may have additional arguments to accommodate arguments |
57 * may differ in several ways. The implementation methods may have additional arguments to accommodate arguments |
60 * captured by the lambda expression; there may also be differences resulting from permitted adaptations of |
58 * captured by the lambda expression; there may also be differences resulting from permitted adaptations of |
61 * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args, |
59 * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args, |
142 * or additional marker superinterfaces. |
140 * or additional marker superinterfaces. |
143 * |
141 * |
144 */ |
142 */ |
145 public class LambdaMetafactory { |
143 public class LambdaMetafactory { |
146 |
144 |
147 /** Flag for alternate metafactories indicating the lambda object is must to be serializable */ |
145 /** Flag for alternate metafactories indicating the lambda object is |
|
146 * must to be serializable */ |
148 public static final int FLAG_SERIALIZABLE = 1 << 0; |
147 public static final int FLAG_SERIALIZABLE = 1 << 0; |
149 |
148 |
150 /** |
149 /** |
151 * Flag for alternate metafactories indicating the lambda object implements other marker interfaces |
150 * Flag for alternate metafactories indicating the lambda object implements |
|
151 * other marker interfaces |
152 * besides Serializable |
152 * besides Serializable |
153 */ |
153 */ |
154 public static final int FLAG_MARKERS = 1 << 1; |
154 public static final int FLAG_MARKERS = 1 << 1; |
155 |
155 |
|
156 /** |
|
157 * Flag for alternate metafactories indicating the lambda object requires |
|
158 * additional bridge methods |
|
159 */ |
|
160 public static final int FLAG_BRIDGES = 1 << 2; |
|
161 |
156 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0]; |
162 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0]; |
157 |
163 private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0]; |
158 /** |
164 |
159 * Standard meta-factory for conversion of lambda expressions or method references to functional interfaces. |
165 /** |
160 * |
166 * Standard meta-factory for conversion of lambda expressions or method |
161 * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges |
167 * references to functional interfaces. |
162 * of the caller. |
168 * |
163 * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site. |
169 * @param caller Stacked automatically by VM; represents a lookup context |
|
170 * with the accessibility privileges of the caller. |
|
171 * @param invokedName Stacked automatically by VM; the name of the invoked |
|
172 * method as it appears at the call site. |
164 * Currently unused. |
173 * Currently unused. |
165 * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the |
174 * @param invokedType Stacked automatically by VM; the signature of the |
166 * expected static type of the returned lambda object, and the static types of the captured |
175 * invoked method, which includes the expected static |
167 * arguments for the lambda. In the event that the implementation method is an instance method, |
176 * type of the returned lambda object, and the static |
168 * the first argument in the invocation signature will correspond to the receiver. |
177 * types of the captured arguments for the lambda. |
169 * @param samMethod The primary method in the functional interface to which the lambda or method reference is |
178 * In the event that the implementation method is an |
170 * being converted, represented as a method handle. |
179 * instance method, the first argument in the invocation |
171 * @param implMethod The implementation method which should be called (with suitable adaptation of argument |
180 * signature will correspond to the receiver. |
172 * types, return types, and adjustment for captured arguments) when methods of the resulting |
181 * @param samMethod The primary method in the functional interface to which |
173 * functional interface instance are invoked. |
182 * the lambda or method reference is being converted, |
174 * @param instantiatedMethodType The signature of the primary functional interface method after type variables |
183 * represented as a method handle. |
175 * are substituted with their instantiation from the capture site |
184 * @param implMethod The implementation method which should be called |
176 * @return a CallSite, which, when invoked, will return an instance of the functional interface |
185 * (with suitable adaptation of argument types, return |
|
186 * types, and adjustment for captured arguments) when |
|
187 * methods of the resulting functional interface instance |
|
188 * are invoked. |
|
189 * @param instantiatedMethodType The signature of the primary functional |
|
190 * interface method after type variables |
|
191 * are substituted with their instantiation |
|
192 * from the capture site |
|
193 * @return a CallSite, which, when invoked, will return an instance of the |
|
194 * functional interface |
177 * @throws ReflectiveOperationException |
195 * @throws ReflectiveOperationException |
178 * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated |
196 * @throws LambdaConversionException If any of the meta-factory protocol |
|
197 * invariants are violated |
179 */ |
198 */ |
180 public static CallSite metaFactory(MethodHandles.Lookup caller, |
199 public static CallSite metaFactory(MethodHandles.Lookup caller, |
181 String invokedName, |
200 String invokedName, |
182 MethodType invokedType, |
201 MethodType invokedType, |
183 MethodHandle samMethod, |
202 MethodHandle samMethod, |
184 MethodHandle implMethod, |
203 MethodHandle implMethod, |
185 MethodType instantiatedMethodType) |
204 MethodType instantiatedMethodType) |
186 throws ReflectiveOperationException, LambdaConversionException { |
205 throws ReflectiveOperationException, LambdaConversionException { |
187 AbstractValidatingLambdaMetafactory mf; |
206 AbstractValidatingLambdaMetafactory mf; |
188 mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType, |
207 mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, |
189 0, EMPTY_CLASS_ARRAY); |
208 implMethod, instantiatedMethodType, |
|
209 false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY); |
190 mf.validateMetafactoryArgs(); |
210 mf.validateMetafactoryArgs(); |
191 return mf.buildCallSite(); |
211 return mf.buildCallSite(); |
192 } |
212 } |
193 |
213 |
194 /** |
214 /** |
195 * Alternate meta-factory for conversion of lambda expressions or method references to functional interfaces, |
215 * Alternate meta-factory for conversion of lambda expressions or method |
196 * which supports serialization and other uncommon options. |
216 * references to functional interfaces, which supports serialization and |
|
217 * other uncommon options. |
197 * |
218 * |
198 * The declared argument list for this method is: |
219 * The declared argument list for this method is: |
199 * |
220 * |
200 * CallSite altMetaFactory(MethodHandles.Lookup caller, |
221 * CallSite altMetaFactory(MethodHandles.Lookup caller, |
201 * String invokedName, |
222 * String invokedName, |
211 * MethodHandle implMethod, |
232 * MethodHandle implMethod, |
212 * MethodType instantiatedMethodType, |
233 * MethodType instantiatedMethodType, |
213 * int flags, |
234 * int flags, |
214 * int markerInterfaceCount, // IF flags has MARKERS set |
235 * int markerInterfaceCount, // IF flags has MARKERS set |
215 * Class... markerInterfaces // IF flags has MARKERS set |
236 * Class... markerInterfaces // IF flags has MARKERS set |
|
237 * int bridgeCount, // IF flags has BRIDGES set |
|
238 * MethodType... bridges // IF flags has BRIDGES set |
216 * ) |
239 * ) |
217 * |
240 * |
218 * |
241 * |
219 * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges |
242 * @param caller Stacked automatically by VM; represents a lookup context |
220 * of the caller. |
243 * with the accessibility privileges of the caller. |
221 * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site. |
244 * @param invokedName Stacked automatically by VM; the name of the invoked |
222 * Currently unused. |
245 * method as it appears at the call site. Currently unused. |
223 * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes thefu |
246 * @param invokedType Stacked automatically by VM; the signature of the |
224 * expected static type of the returned lambda object, and the static types of the captured |
247 * invoked method, which includes the expected static |
225 * arguments for the lambda. In the event that the implementation method is an instance method, |
248 * type of the returned lambda object, and the static |
226 * the first argument in the invocation signature will correspond to the receiver. |
249 * types of the captured arguments for the lambda. |
227 * @param args argument to pass, flags, marker interface count, and marker interfaces as described above |
250 * In the event that the implementation method is an |
228 * @return a CallSite, which, when invoked, will return an instance of the functional interface |
251 * instance method, the first argument in the invocation |
|
252 * signature will correspond to the receiver. |
|
253 * @param args flags and optional arguments, as described above |
|
254 * @return a CallSite, which, when invoked, will return an instance of the |
|
255 * functional interface |
229 * @throws ReflectiveOperationException |
256 * @throws ReflectiveOperationException |
230 * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated |
257 * @throws LambdaConversionException If any of the meta-factory protocol |
|
258 * invariants are violated |
231 */ |
259 */ |
232 public static CallSite altMetaFactory(MethodHandles.Lookup caller, |
260 public static CallSite altMetaFactory(MethodHandles.Lookup caller, |
233 String invokedName, |
261 String invokedName, |
234 MethodType invokedType, |
262 MethodType invokedType, |
235 Object... args) |
263 Object... args) |
237 MethodHandle samMethod = (MethodHandle)args[0]; |
265 MethodHandle samMethod = (MethodHandle)args[0]; |
238 MethodHandle implMethod = (MethodHandle)args[1]; |
266 MethodHandle implMethod = (MethodHandle)args[1]; |
239 MethodType instantiatedMethodType = (MethodType)args[2]; |
267 MethodType instantiatedMethodType = (MethodType)args[2]; |
240 int flags = (Integer) args[3]; |
268 int flags = (Integer) args[3]; |
241 Class<?>[] markerInterfaces; |
269 Class<?>[] markerInterfaces; |
|
270 MethodType[] bridges; |
242 int argIndex = 4; |
271 int argIndex = 4; |
243 if ((flags & FLAG_MARKERS) != 0) { |
272 if ((flags & FLAG_MARKERS) != 0) { |
244 int markerCount = (Integer) args[argIndex++]; |
273 int markerCount = (Integer) args[argIndex++]; |
245 markerInterfaces = new Class<?>[markerCount]; |
274 markerInterfaces = new Class<?>[markerCount]; |
246 System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount); |
275 System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount); |
247 argIndex += markerCount; |
276 argIndex += markerCount; |
248 } |
277 } |
249 else |
278 else |
250 markerInterfaces = EMPTY_CLASS_ARRAY; |
279 markerInterfaces = EMPTY_CLASS_ARRAY; |
251 AbstractValidatingLambdaMetafactory mf; |
280 if ((flags & FLAG_BRIDGES) != 0) { |
252 mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType, |
281 int bridgeCount = (Integer) args[argIndex++]; |
253 flags, markerInterfaces); |
282 bridges = new MethodType[bridgeCount]; |
|
283 System.arraycopy(args, argIndex, bridges, 0, bridgeCount); |
|
284 argIndex += bridgeCount; |
|
285 } |
|
286 else |
|
287 bridges = EMPTY_MT_ARRAY; |
|
288 |
|
289 boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType()); |
|
290 for (Class<?> c : markerInterfaces) |
|
291 foundSerializableSupertype |= Serializable.class.isAssignableFrom(c); |
|
292 boolean isSerializable = ((flags & LambdaMetafactory.FLAG_SERIALIZABLE) != 0) |
|
293 || foundSerializableSupertype; |
|
294 |
|
295 if (isSerializable && !foundSerializableSupertype) { |
|
296 markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1); |
|
297 markerInterfaces[markerInterfaces.length-1] = Serializable.class; |
|
298 } |
|
299 |
|
300 AbstractValidatingLambdaMetafactory mf |
|
301 = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, |
|
302 implMethod, instantiatedMethodType, |
|
303 isSerializable, markerInterfaces, bridges); |
254 mf.validateMetafactoryArgs(); |
304 mf.validateMetafactoryArgs(); |
255 return mf.buildCallSite(); |
305 return mf.buildCallSite(); |
256 } |
306 } |
257 } |
307 } |