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