diff -r eca8e9c3ec3e -r cd50c1894ce5 rt/emul/compact/src/main/java/java/lang/invoke/LambdaMetafactory.java --- a/rt/emul/compact/src/main/java/java/lang/invoke/LambdaMetafactory.java Sun Aug 17 20:09:05 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,477 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.invoke; - -import java.io.Serializable; -import java.util.Arrays; - -/** - *

Methods to facilitate the creation of simple "function objects" that - * implement one or more interfaces by delegation to a provided {@link MethodHandle}, - * possibly after type adaptation and partial evaluation of arguments. These - * methods are typically used as bootstrap methods for {@code invokedynamic} - * call sites, to support the lambda expression and method - * reference expression features of the Java Programming Language. - * - *

Indirect access to the behavior specified by the provided {@code MethodHandle} - * proceeds in order through three phases: - *

- * - *

It is sometimes useful to restrict the set of inputs or results permitted - * at invocation. For example, when the generic interface {@code Predicate} - * is parameterized as {@code Predicate}, the input must be a - * {@code String}, even though the method to implement allows any {@code Object}. - * At linkage time, an additional {@link MethodType} parameter describes the - * "instantiated" method type; on invocation, the arguments and eventual result - * are checked against this {@code MethodType}. - * - *

This class provides two forms of linkage methods: a standard version - * ({@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}) - * using an optimized protocol, and an alternate version - * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}). - * The alternate version is a generalization of the standard version, providing - * additional control over the behavior of the generated function objects via - * flags and additional arguments. The alternate version adds the ability to - * manage the following attributes of function objects: - * - *

- * - *

Assume the linkage arguments are as follows: - *

- * - *

Then the following linkage invariants must hold: - *

- * - *

Further, at capture time, if {@code implMethod} corresponds to an instance - * method, and there are any capture arguments ({@code K > 0}), then the first - * capture argument (corresponding to the receiver) must be non-null. - * - *

A type Q is considered adaptable to S as follows: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
QSLink-time checksInvocation-time checks
PrimitivePrimitiveQ can be converted to S via a primitive widening conversionNone
PrimitiveReferenceS is a supertype of the Wrapper(Q)Cast from Wrapper(Q) to S
ReferencePrimitivefor parameter types: Q is a primitive wrapper and Primitive(Q) - * can be widened to S - *
for return types: If Q is a primitive wrapper, check that - * Primitive(Q) can be widened to S
If Q is not a primitive wrapper, cast Q to the base Wrapper(S); - * for example Number for numeric types
ReferenceReferencefor parameter types: S is a supertype of Q - *
for return types: none
Cast from Q to S
- * - * @apiNote These linkage methods are designed to support the evaluation - * of lambda expressions and method references in the Java - * Language. For every lambda expressions or method reference in the source code, - * there is a target type which is a functional interface. Evaluating a lambda - * expression produces an object of its target type. The recommended mechanism - * for evaluating lambda expressions is to desugar the lambda body to a method, - * invoke an invokedynamic call site whose static argument list describes the - * sole method of the functional interface and the desugared implementation - * method, and returns an object (the lambda object) that implements the target - * type. (For method references, the implementation method is simply the - * referenced method; no desugaring is needed.) - * - *

The argument list of the implementation method and the argument list of - * the interface method(s) may differ in several ways. The implementation - * methods may have additional arguments to accommodate arguments captured by - * the lambda expression; there may also be differences resulting from permitted - * adaptations of arguments, such as casting, boxing, unboxing, and primitive - * widening. (Varargs adaptations are not handled by the metafactories; these are - * expected to be handled by the caller.) - * - *

Invokedynamic call sites have two argument lists: a static argument list - * and a dynamic argument list. The static argument list is stored in the - * constant pool; the dynamic argument is pushed on the operand stack at capture - * time. The bootstrap method has access to the entire static argument list - * (which in this case, includes information describing the implementation method, - * the target interface, and the target interface method(s)), as well as a - * method signature describing the number and static types (but not the values) - * of the dynamic arguments and the static return type of the invokedynamic site. - * - * @implNote The implementation method is described with a method handle. In - * theory, any method handle could be used. Currently supported are direct method - * handles representing invocation of virtual, interface, constructor and static - * methods. - */ -public class LambdaMetafactory { - - /** Flag for alternate metafactories indicating the lambda object - * must be serializable */ - public static final int FLAG_SERIALIZABLE = 1 << 0; - - /** - * Flag for alternate metafactories indicating the lambda object implements - * other marker interfaces - * besides Serializable - */ - public static final int FLAG_MARKERS = 1 << 1; - - /** - * Flag for alternate metafactories indicating the lambda object requires - * additional bridge methods - */ - public static final int FLAG_BRIDGES = 1 << 2; - - private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; - private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0]; - - /** - * Facilitates the creation of simple "function objects" that implement one - * or more interfaces by delegation to a provided {@link MethodHandle}, - * after appropriate type adaptation and partial evaluation of arguments. - * Typically used as a bootstrap method for {@code invokedynamic} - * call sites, to support the lambda expression and method - * reference expression features of the Java Programming Language. - * - *

This is the standard, streamlined metafactory; additional flexibility - * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}. - * A general description of the behavior of this method is provided - * {@link LambdaMetafactory above}. - * - *

When the target of the {@code CallSite} returned from this method is - * invoked, the resulting function objects are instances of a class which - * implements the interface named by the return type of {@code invokedType}, - * declares a method with the name given by {@code invokedName} and the - * signature given by {@code samMethodType}. It may also override additional - * methods from {@code Object}. - * - * @param caller Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invokedName The name of the method to implement. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invokedType The expected signature of the {@code CallSite}. The - * parameter types represent the types of capture variables; - * the return type is the interface to implement. When - * used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * In the event that the implementation method is an - * instance method and this signature has any parameters, - * the first parameter in the invocation signature must - * correspond to the receiver. - * @param samMethodType Signature and return type of method to be implemented - * by the function object. - * @param implMethod A direct method handle describing the implementation - * method which should be called (with suitable adaptation - * of argument types, return types, and with captured - * arguments prepended to the invocation arguments) at - * invocation time. - * @param instantiatedMethodType The signature and return type that should - * be enforced dynamically at invocation time. - * This may be the same as {@code samMethodType}, - * or may be a specialization of it. - * @return a CallSite whose target can be used to perform capture, generating - * instances of the interface named by {@code invokedType} - * @throws LambdaConversionException If any of the linkage invariants - * described {@link LambdaMetafactory above} - * are violated - */ - public static CallSite metafactory(MethodHandles.Lookup caller, - String invokedName, - MethodType invokedType, - MethodType samMethodType, - MethodHandle implMethod, - MethodType instantiatedMethodType) - throws LambdaConversionException { - AbstractValidatingLambdaMetafactory mf; -// mf = new InnerClassLambdaMetafactory(caller, invokedType, -// invokedName, samMethodType, -// implMethod, instantiatedMethodType, -// false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY); -// mf.validateMetafactoryArgs(); -// return mf.buildCallSite(); - throw new IllegalStateException(); - } - - /** - * Facilitates the creation of simple "function objects" that implement one - * or more interfaces by delegation to a provided {@link MethodHandle}, - * after appropriate type adaptation and partial evaluation of arguments. - * Typically used as a bootstrap method for {@code invokedynamic} - * call sites, to support the lambda expression and method - * reference expression features of the Java Programming Language. - * - *

This is the general, more flexible metafactory; a streamlined version - * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}. - * A general description of the behavior of this method is provided - * {@link LambdaMetafactory above}. - * - *

The argument list for this method includes three fixed parameters, - * corresponding to the parameters automatically stacked by the VM for the - * bootstrap method in an {@code invokedynamic} invocation, and an {@code Object[]} - * parameter that contains additional parameters. The declared argument - * list for this method is: - * - *

{@code
-     *  CallSite altMetafactory(MethodHandles.Lookup caller,
-     *                          String invokedName,
-     *                          MethodType invokedType,
-     *                          Object... args)
-     * }
- * - *

but it behaves as if the argument list is as follows: - * - *

{@code
-     *  CallSite altMetafactory(MethodHandles.Lookup caller,
-     *                          String invokedName,
-     *                          MethodType invokedType,
-     *                          MethodType samMethodType,
-     *                          MethodHandle implMethod,
-     *                          MethodType instantiatedMethodType,
-     *                          int flags,
-     *                          int markerInterfaceCount,  // IF flags has MARKERS set
-     *                          Class... markerInterfaces, // IF flags has MARKERS set
-     *                          int bridgeCount,           // IF flags has BRIDGES set
-     *                          MethodType... bridges      // IF flags has BRIDGES set
-     *                          )
-     * }
- * - *

Arguments that appear in the argument list for - * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)} - * have the same specification as in that method. The additional arguments - * are interpreted as follows: - *

- * - *

Each class named by {@code markerInterfaces} is subject to the same - * restrictions as {@code Rd}, the return type of {@code invokedType}, - * as described {@link LambdaMetafactory above}. Each {@code MethodType} - * named by {@code bridges} is subject to the same restrictions as - * {@code samMethodType}, as described {@link LambdaMetafactory above}. - * - *

When FLAG_SERIALIZABLE is set in {@code flags}, the function objects - * will implement {@code Serializable}, and will have a {@code writeReplace} - * method that returns an appropriate {@link SerializedLambda}. The - * {@code caller} class must have an appropriate {@code $deserializeLambda$} - * method, as described in {@link SerializedLambda}. - * - *

When the target of the {@code CallSite} returned from this method is - * invoked, the resulting function objects are instances of a class with - * the following properties: - *

- * - * @param caller Represents a lookup context with the accessibility - * privileges of the caller. When used with {@code invokedynamic}, - * this is stacked automatically by the VM. - * @param invokedName The name of the method to implement. When used with - * {@code invokedynamic}, this is provided by the - * {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * @param invokedType The expected signature of the {@code CallSite}. The - * parameter types represent the types of capture variables; - * the return type is the interface to implement. When - * used with {@code invokedynamic}, this is provided by - * the {@code NameAndType} of the {@code InvokeDynamic} - * structure and is stacked automatically by the VM. - * In the event that the implementation method is an - * instance method and this signature has any parameters, - * the first parameter in the invocation signature must - * correspond to the receiver. - * @param args An {@code Object[]} array containing the required - * arguments {@code samMethodType}, {@code implMethod}, - * {@code instantiatedMethodType}, {@code flags}, and any - * optional arguments, as described - * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)} above} - * @return a CallSite whose target can be used to perform capture, generating - * instances of the interface named by {@code invokedType} - * @throws LambdaConversionException If any of the linkage invariants - * described {@link LambdaMetafactory above} - * are violated - */ - public static CallSite altMetafactory(MethodHandles.Lookup caller, - String invokedName, - MethodType invokedType, - Object... args) - throws LambdaConversionException { - MethodType samMethodType = (MethodType)args[0]; - MethodHandle implMethod = (MethodHandle)args[1]; - MethodType instantiatedMethodType = (MethodType)args[2]; - int flags = (Integer) args[3]; - Class[] markerInterfaces; - MethodType[] bridges; - int argIndex = 4; - if ((flags & FLAG_MARKERS) != 0) { - int markerCount = (Integer) args[argIndex++]; - markerInterfaces = new Class[markerCount]; - System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount); - argIndex += markerCount; - } - else - markerInterfaces = EMPTY_CLASS_ARRAY; - if ((flags & FLAG_BRIDGES) != 0) { - int bridgeCount = (Integer) args[argIndex++]; - bridges = new MethodType[bridgeCount]; - System.arraycopy(args, argIndex, bridges, 0, bridgeCount); - argIndex += bridgeCount; - } - else - bridges = EMPTY_MT_ARRAY; - - boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0); - if (isSerializable) { - boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType()); - for (Class c : markerInterfaces) - foundSerializableSupertype |= Serializable.class.isAssignableFrom(c); - if (!foundSerializableSupertype) { - markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1); - markerInterfaces[markerInterfaces.length-1] = Serializable.class; - } - } - -// AbstractValidatingLambdaMetafactory mf -// = new InnerClassLambdaMetafactory(caller, invokedType, -// invokedName, samMethodType, -// implMethod, -// instantiatedMethodType, -// isSerializable, -// markerInterfaces, bridges); -// mf.validateMetafactoryArgs(); -// return mf.buildCallSite(); - throw new IllegalStateException(); - } -}