changeset 14323:5acca3d1f124

8000806: Implement runtime lambda metafactory Summary: Implement lambda invokedynamic bootstrap by generating at runtime an inner class that implements the functional interface Reviewed-by: twisti
author rfield
date Thu, 25 Oct 2012 17:34:24 -0700
parents f17cf2e58bb3
children 3510b4bf90ee
files jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java jdk/src/share/classes/java/lang/invoke/LambdaConversionException.java jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java jdk/src/share/classes/java/lang/invoke/MagicLambdaImpl.java jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java
diffstat 6 files changed, 1312 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java	Thu Oct 25 17:34:24 2012 -0700
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2012, 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.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import sun.invoke.util.Wrapper;
+import static sun.invoke.util.Wrapper.*;
+
+/**
+ * Abstract implementation of a meta-factory which provides parameter unrolling and input validation.
+ *
+ * @author Robert Field
+ */
+/*non-public*/ abstract class AbstractValidatingLambdaMetafactory {
+
+    /*
+     * For context, the comments for the following fields are marked in quotes with their values, given this program:
+     * interface II<T> {  Object foo(T x); }
+     * interface JJ<R extends Number> extends II<R> { }
+     * class CC {  String impl(int i) { return "impl:"+i; }}
+     * class X {
+     *     public static void main(String[] args) {
+     *         JJ<Integer> iii = (new CC())::impl;
+     *         System.out.printf(">>> %s\n", iii.foo(44));
+     * }}
+     */
+    final Class<?> targetClass;               // The class calling the meta-factory via invokedynamic "class X"
+    final MethodType invokedType;             // The type of the invoked method "(CC)II"
+    final Class<?> samBase;                   // The type of the returned instance "interface JJ"
+    final boolean isSerializable;             // Should the returned instance be serializable
+    final MethodHandleInfo samInfo;           // Info about the SAM method handle "MethodHandleInfo[9 II.foo(Object)Object]"
+    final Class<?> samClass;                  // Interface containing the SAM method "interface II"
+    final MethodType samMethodType;           // Type of the SAM method "(Object)Object"
+    final MethodHandleInfo implInfo;          // Info about the implementation method handle "MethodHandleInfo[5 CC.impl(int)String]"
+    final int implKind;                       // Invocation kind for implementation "5"=invokevirtual
+    final boolean implIsInstanceMethod;       // Is the implementation an instance method "true"
+    final Class<?> implDefiningClass;         // Type defining the implementation "class CC"
+    final MethodType implMethodType;          // Type of the implementation method "(int)String"
+    final MethodType instantiatedMethodType;  // Instantiated erased functional interface method type "(Integer)Object"
+
+
+    /**
+     * Meta-factory constructor.
+     *
+     * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
+     *               of the caller.
+     * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
+     *                    expected static type of the returned lambda object, and the static types of the captured
+     *                    arguments for the lambda.  In the event that the implementation method is an instance method,
+     *                    the first argument in the invocation signature will correspond to the receiver.
+     * @param samMethod The primary method in the functional interface to which the lambda or method reference is
+     *                  being converted, represented as a method handle.
+     * @param implMethod The implementation method which should be called (with suitable adaptation of argument
+     *                   types, return types, and adjustment for captured arguments) when methods of the resulting
+     *                   functional interface instance are invoked.
+     * @param instantiatedMethodType The signature of the SAM method from the functional interface's perspective
+     * @throws ReflectiveOperationException
+     */
+    AbstractValidatingLambdaMetafactory(MethodHandles.Lookup caller,
+                                       MethodType invokedType,
+                                       MethodHandle samMethod,
+                                       MethodHandle implMethod,
+                                       MethodType instantiatedMethodType)
+            throws ReflectiveOperationException {
+        this.targetClass = caller.lookupClass();
+        this.invokedType = invokedType;
+
+        this.samBase = invokedType.returnType();
+        this.isSerializable = Serializable.class.isAssignableFrom(samBase);
+
+        this.samInfo = new MethodHandleInfo(samMethod);
+        this.samClass = samInfo.getDeclaringClass();
+        this.samMethodType  = samInfo.getMethodType();
+
+        this.implInfo = new MethodHandleInfo(implMethod);
+        this.implKind = implInfo.getReferenceKind() == MethodHandleInfo.REF_invokeSpecial? MethodHandleInfo.REF_invokeVirtual : implInfo.getReferenceKind(); // @@@ Temp work-around to hotspot incorrectly converting to invokespecial
+        this.implIsInstanceMethod =
+                implKind == MethodHandleInfo.REF_invokeVirtual ||
+                implKind == MethodHandleInfo.REF_invokeSpecial ||
+                implKind == MethodHandleInfo.REF_invokeInterface;
+        this.implDefiningClass = implInfo.getDeclaringClass();
+        this.implMethodType = implInfo.getMethodType();
+
+        this.instantiatedMethodType = instantiatedMethodType;
+    }
+
+    /**
+     * Build the CallSite.
+     *
+     * @return a CallSite, which, when invoked, will return an instance of the
+     * functional interface
+     * @throws ReflectiveOperationException
+     */
+    abstract CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException;
+
+    /**
+     * Check the meta-factory arguments for errors
+     * @throws LambdaConversionException if there are improper conversions
+     */
+    void validateMetafactoryArgs() throws LambdaConversionException {
+        // Check target type is a subtype of class where SAM method is defined
+        if (!samClass.isAssignableFrom(samBase)) {
+            throw new LambdaConversionException(String.format("Invalid target type %s for lambda conversion; not a subtype of functional interface %s",
+                    samBase.getName(), samClass.getName()));
+        }
+
+        switch (implKind) {
+            case MethodHandleInfo.REF_invokeInterface:
+            case MethodHandleInfo.REF_invokeVirtual:
+            case MethodHandleInfo.REF_invokeStatic:
+            case MethodHandleInfo.REF_newInvokeSpecial:
+            case MethodHandleInfo.REF_invokeSpecial:
+                break;
+            default:
+                throw new LambdaConversionException(String.format("Unsupported MethodHandle kind: %s", implInfo));
+        }
+
+        // Check arity: optional-receiver + captured + SAM == impl
+        final int implArity = implMethodType.parameterCount();
+        final int receiverArity = implIsInstanceMethod ? 1 : 0;
+        final int capturedArity = invokedType.parameterCount();
+        final int samArity = samMethodType.parameterCount();
+        final int instantiatedArity = instantiatedMethodType.parameterCount();
+        if (implArity + receiverArity != capturedArity + samArity) {
+            throw new LambdaConversionException(String.format("Incorrect number of parameters for %s method %s; %d captured parameters, %d functional interface parameters, %d implementation parameters",
+                    implIsInstanceMethod ? "instance" : "static", implInfo,
+                    capturedArity, samArity, implArity));
+        }
+        if (instantiatedArity != samArity) {
+            throw new LambdaConversionException(String.format("Incorrect number of parameters for %s method %s; %d functional interface parameters, %d SAM method parameters",
+                    implIsInstanceMethod ? "instance" : "static", implInfo,
+                    instantiatedArity, samArity));
+        }
+
+        // If instance: first captured arg (receiver) must be subtype of class where impl method is defined
+        final int capturedStart;
+        final int samStart;
+        if (implIsInstanceMethod) {
+            final Class<?> receiverClass;
+
+            // implementation is an instance method, adjust for receiver in captured variables / SAM arguments
+            if (capturedArity == 0) {
+                // receiver is function parameter
+                capturedStart = 0;
+                samStart = 1;
+                receiverClass = instantiatedMethodType.parameterType(0);
+            } else {
+                // receiver is a captured variable
+                capturedStart = 1;
+                samStart = 0;
+                receiverClass = invokedType.parameterType(0);
+            }
+
+            // check receiver type
+            if (!implDefiningClass.isAssignableFrom(receiverClass)) {
+                throw new LambdaConversionException(String.format("Invalid receiver type %s; not a subtype of implementation type %s",
+                                                                  receiverClass, implDefiningClass));
+            }
+        } else {
+            // no receiver
+            capturedStart = 0;
+            samStart = 0;
+        }
+
+        // Check for exact match on non-receiver captured arguments
+        final int implFromCaptured = capturedArity - capturedStart;
+        for (int i=0; i<implFromCaptured; i++) {
+            Class<?> implParamType = implMethodType.parameterType(i);
+            Class<?> capturedParamType = invokedType.parameterType(i + capturedStart);
+            if (!capturedParamType.equals(implParamType)) {
+                throw new LambdaConversionException(
+                        String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s", i, capturedParamType, implParamType));
+            }
+        }
+        // Check for adaptation match on SAM arguments
+        final int samOffset = samStart - implFromCaptured;
+        for (int i=implFromCaptured; i<implArity; i++) {
+            Class<?> implParamType = implMethodType.parameterType(i);
+            Class<?> instantiatedParamType = instantiatedMethodType.parameterType(i + samOffset);
+            if (!isAdaptableTo(instantiatedParamType, implParamType, true)) {
+                throw new LambdaConversionException(
+                        String.format("Type mismatch for lambda argument %d: %s is not convertible to %s", i, instantiatedParamType, implParamType));
+            }
+        }
+
+        // Adaptation match: return type
+        Class<?> expectedType = instantiatedMethodType.returnType();
+        Class<?> actualReturnType =
+                (implKind == MethodHandleInfo.REF_newInvokeSpecial)
+                  ? implDefiningClass
+                  : implMethodType.returnType();
+        if (!isAdaptableToAsReturn(actualReturnType, expectedType)) {
+            throw new LambdaConversionException(
+                    String.format("Type mismatch for lambda return: %s is not convertible to %s", actualReturnType, expectedType));
+        }
+     }
+
+    /**
+     * Check type adaptability
+     * @param fromType
+     * @param toType
+     * @param strict If true, do strict checks, else allow that fromType may be parameterized
+     * @return True if 'fromType' can be passed to an argument of 'toType'
+     */
+    private boolean isAdaptableTo(Class<?> fromType, Class<?> toType, boolean strict) {
+        if (fromType.equals(toType)) {
+            return true;
+        }
+        if (fromType.isPrimitive()) {
+            Wrapper wfrom = forPrimitiveType(fromType);
+            if (toType.isPrimitive()) {
+                // both are primitive: widening
+                Wrapper wto = forPrimitiveType(toType);
+                return wto.isConvertibleFrom(wfrom);
+            } else {
+                // from primitive to reference: boxing
+                return toType.isAssignableFrom(wfrom.wrapperType());
+            }
+        } else {
+            if (toType.isPrimitive()) {
+                // from reference to primitive: unboxing
+                Wrapper wfrom;
+                if (isWrapperType(fromType) && (wfrom = forWrapperType(fromType)).primitiveType().isPrimitive()) {
+                    // fromType is a primitive wrapper; unbox+widen
+                    Wrapper wto = forPrimitiveType(toType);
+                    return wto.isConvertibleFrom(wfrom);
+                } else {
+                    // must be convertible to primitive
+                    return !strict;
+                }
+            } else {
+                // both are reference types: fromType should be a superclass of toType.
+                return strict? toType.isAssignableFrom(fromType) : true;
+            }
+        }
+    }
+
+    /**
+     * Check type adaptability for return types -- special handling of void type) and parameterized fromType
+     * @param fromType
+     * @param toType
+     * @return True if 'fromType' can be converted to 'toType'
+     */
+    private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
+        return toType.equals(void.class)
+               || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
+    }
+
+
+    /*********** Logging support -- for debugging only
+    static final Executor logPool = Executors.newSingleThreadExecutor(); // @@@ For debugging only
+    protected static void log(final String s) {
+        MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
+            @Override
+            public void run() {
+                System.out.println(s);
+            }
+        });
+    }
+
+    protected static void log(final String s, final Throwable e) {
+        MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
+            @Override
+            public void run() {
+                System.out.println(s);
+                e.printStackTrace(System.out);
+            }
+        });
+    }
+    ***********************/
+
+    /**
+     * Find the SAM method and corresponding methods which should be bridged. SAM method and those to be bridged
+     * will have the same name and number of parameters. Check for matching default methods (non-abstract), they
+     * should not be bridged-over and indicate a complex bridging situation.
+     */
+    class MethodAnalyzer {
+        private final Method[] methods = samBase.getMethods();
+        private final List<Method> methodsFound = new ArrayList<>(methods.length);
+
+        private Method samMethod = null;
+        private final List<Method> methodsToBridge = new ArrayList<>(methods.length);
+        private boolean defaultMethodFound = false;
+
+        MethodAnalyzer() {
+            String samMethodName = samInfo.getName();
+            Class<?>[] samParamTypes = samMethodType.parameterArray();
+            int samParamLength = samParamTypes.length;
+            Class<?> samReturnType = samMethodType.returnType();
+            Class<?> objectClass = Object.class;
+
+            for (Method m : methods) {
+                if (m.getName().equals(samMethodName) && m.getDeclaringClass() != objectClass) {
+                    Class<?>[] mParamTypes = m.getParameterTypes();
+                    if (mParamTypes.length == samParamLength) {
+                        if (Modifier.isAbstract(m.getModifiers())) {
+                            // Exclude methods with duplicate signatures
+                            if (methodUnique(m)) {
+                                if (m.getReturnType().equals(samReturnType) && Arrays.equals(mParamTypes, samParamTypes)) {
+                                    // Exact match, this is the SAM method signature
+                                    samMethod = m;
+                                } else {
+                                    methodsToBridge.add(m);
+                                }
+                            }
+                        } else {
+                            // This is a default method, flag for special processing
+                            defaultMethodFound = true;
+                            // Ignore future matching abstracts.
+                            // Note, due to reabstraction, this is really a punt, hence pass-off to VM
+                            methodUnique(m);
+                        }
+                    }
+                }
+            }
+        }
+
+        Method getSamMethod() {
+            return samMethod;
+        }
+
+        List<Method> getMethodsToBridge() {
+            return methodsToBridge;
+        }
+
+        boolean wasDefaultMethodFound() {
+            return defaultMethodFound;
+        }
+
+        /**
+         * Search the list of previously found methods to determine if there is a method with the same signature
+         * (return and parameter types) as the specified method. If it wasn't found before, add to the found list.
+         *
+         * @param m The method to match
+         * @return False if the method was found, True otherwise
+         */
+        private boolean methodUnique(Method m) {
+            Class<?>[] ptypes = m.getParameterTypes();
+            Class<?> rtype = m.getReturnType();
+            for (Method md : methodsFound) {
+                if (md.getReturnType().equals(rtype) && Arrays.equals(ptypes, md.getParameterTypes())) {
+                    return false;
+                }
+            }
+            methodsFound.add(m);
+            return true;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu Oct 25 17:34:24 2012 -0700
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2012, 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.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.security.ProtectionDomain;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import jdk.internal.org.objectweb.asm.*;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import sun.misc.Unsafe;
+
+/**
+ * InnerClassLambdaMetafactory
+ */
+/*non-public*/ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
+    private static final int CLASSFILE_VERSION = 51;
+    private static final Type TYPE_VOID = Type.getType(void.class);
+    private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
+    private static final String NAME_MAGIC_ACCESSOR_IMPL = "java/lang/invoke/MagicLambdaImpl";
+    private static final String NAME_SERIALIZABLE = "java/io/Serializable";
+    private static final String NAME_CTOR = "<init>";
+
+    //Serialization support
+    private static final String NAME_SERIALIZED_LAMBDA = "com/oracle/java/lang/invoke/SerializedLambdaImpl";
+    private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
+    private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
+    private static final String NAME_OBJECT = "java/lang/Object";
+
+    // Used to ensure that each spun class name is unique
+    private static final AtomicInteger counter = new AtomicInteger(0);
+
+    // See context values in AbstractValidatingLambdaMetafactory
+    private final String implMethodClassName;        // Name of type containing implementation "CC"
+    private final String implMethodName;             // Name of implementation method "impl"
+    private final String implMethodDesc;             // Type descriptor for implementation methods "(I)Ljava/lang/String;"
+    private final Type[] implMethodArgumentTypes;    // ASM types for implementaion method parameters
+    private final Type implMethodReturnType;         // ASM type for implementaion method return type "Ljava/lang/String;"
+    private final MethodType constructorType;        // Generated class constructor type "(CC)void"
+    private final String constructorDesc;            // Type descriptor for constructor "(LCC;)V"
+    private final ClassWriter cw;                    // ASM class writer
+    private final Type[] argTypes;                   // ASM types for the constructor arguments
+    private final String[] argNames;                 // Generated names for the constructor arguments
+    private final String lambdaClassName;            // Generated name for the generated class "X$$Lambda$1"
+    private final Type[] instantiatedArgumentTypes;  // ASM types for the functional interface arguments
+
+    /**
+     * Meta-factory constructor.
+     *
+     * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
+     *               of the caller.
+     * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
+     *                    expected static type of the returned lambda object, and the static types of the captured
+     *                    arguments for the lambda.  In the event that the implementation method is an instance method,
+     *                    the first argument in the invocation signature will correspond to the receiver.
+     * @param samMethod The primary method in the functional interface to which the lambda or method reference is
+     *                  being converted, represented as a method handle.
+     * @param implMethod The implementation method which should be called (with suitable adaptation of argument
+     *                   types, return types, and adjustment for captured arguments) when methods of the resulting
+     *                   functional interface instance are invoked.
+     * @param instantiatedMethodType The signature of the SAM method from the functional interface's perspective
+     * @throws ReflectiveOperationException
+     */
+    public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
+                                       MethodType invokedType,
+                                       MethodHandle samMethod,
+                                       MethodHandle implMethod,
+                                       MethodType instantiatedMethodType)
+            throws ReflectiveOperationException {
+        super(caller, invokedType, samMethod, implMethod, instantiatedMethodType);
+        implMethodClassName = implDefiningClass.getName().replace('.', '/');
+        implMethodName = implInfo.getName();
+        implMethodDesc = implMethodType.toMethodDescriptorString();
+        Type implMethodAsmType = Type.getMethodType(implMethodDesc);
+        implMethodArgumentTypes = implMethodAsmType.getArgumentTypes();
+        implMethodReturnType = implMethodAsmType.getReturnType();
+        constructorType = invokedType.changeReturnType(Void.TYPE);
+        constructorDesc = constructorType.toMethodDescriptorString();
+        lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
+        cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+        argTypes = Type.getArgumentTypes(constructorDesc);
+        argNames = new String[argTypes.length];
+        for (int i = 0; i < argTypes.length; i++) {
+            argNames[i] = "arg$" + (i + 1);
+        }
+        instantiatedArgumentTypes = Type.getArgumentTypes(instantiatedMethodType.toMethodDescriptorString());
+
+    }
+
+    /**
+     * Build the CallSite. Generate a class file which implements the functional
+     * interface, define the class, if there are no parameters create an instance
+     * of the class which the CallSite will return, otherwise, generate handles
+     * which will call the class' constructor.
+     *
+     * @return a CallSite, which, when invoked, will return an instance of the
+     * functional interface
+     * @throws ReflectiveOperationException
+     */
+    @Override
+    CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException {
+        final Class<?> innerClass = spinInnerClass();
+        if (invokedType.parameterCount() == 0) {
+            return new ConstantCallSite(MethodHandles.constant(samBase, innerClass.newInstance()));
+        } else {
+            return new ConstantCallSite(
+                    MethodHandles.Lookup.IMPL_LOOKUP
+                    .findConstructor(innerClass, constructorType)
+                    .asType(constructorType.changeReturnType(samBase)));
+        }
+    }
+
+    /**
+     * Generate a class file which implements the functional
+     * interface, define and return the class.
+     *
+     * @return a Class which implements the functional interface
+     */
+    private <T> Class<? extends T> spinInnerClass() throws LambdaConversionException {
+        String samName = samBase.getName().replace('.', '/');
+
+        cw.visit(CLASSFILE_VERSION, ACC_PUBLIC + ACC_SUPER, lambdaClassName, null, NAME_MAGIC_ACCESSOR_IMPL,
+                 isSerializable ? new String[]{samName, NAME_SERIALIZABLE} : new String[]{samName});
+
+        // Generate final fields to be filled in by constructor
+        for (int i = 0; i < argTypes.length; i++) {
+            FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argTypes[i].getDescriptor(), null, null);
+            fv.visitEnd();
+        }
+
+        generateConstructor();
+
+        MethodAnalyzer ma = new MethodAnalyzer();
+
+        // Forward the SAM method
+        if (ma.getSamMethod() == null) {
+            throw new LambdaConversionException(String.format("SAM method not found: %s", samMethodType));
+        } else {
+            generateForwardingMethod(ma.getSamMethod(), false);
+        }
+
+        // Forward the bridges
+        // @@@ Once the VM can do fail-over, uncomment the default method test
+        if (!ma.getMethodsToBridge().isEmpty() /* && !ma.wasDefaultMethodFound() */) {
+            for (Method m : ma.getMethodsToBridge()) {
+                generateForwardingMethod(m, true);
+            }
+        }
+
+        /***** Serialization not yet supported
+        if (isSerializable) {
+            String samMethodName = samInfo.getName();
+            Type samType = Type.getType(samBase);
+            generateSerializationMethod(samType, samMethodName);
+        }
+        ******/
+
+        cw.visitEnd();
+
+        // Define the generated class in this VM.
+
+        final byte[] classBytes = cw.toByteArray();
+
+        if (System.getProperty("debug.dump.generated") != null) {
+            System.out.printf("Loaded: %s (%d bytes) %n", lambdaClassName, classBytes.length);
+            try (FileOutputStream fos = new FileOutputStream(lambdaClassName.replace('/', '.') + ".class")) {
+                fos.write(classBytes);
+            } catch (IOException ex) {
+                Logger.getLogger(InnerClassLambdaMetafactory.class.getName()).log(Level.SEVERE, null, ex);
+            }
+        }
+
+        ClassLoader loader = targetClass.getClassLoader();
+        ProtectionDomain pd = (loader == null) ? null : targetClass.getProtectionDomain();
+        return (Class<? extends T>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length, loader, pd);
+    }
+
+    /**
+     * Generate the constructor for the class
+     */
+    private void generateConstructor() {
+        // Generate constructor
+        MethodVisitor ctor = cw.visitMethod(ACC_PUBLIC, NAME_CTOR, constructorDesc, null, null);
+        ctor.visitCode();
+        ctor.visitVarInsn(ALOAD, 0);
+        ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR, METHOD_DESCRIPTOR_VOID);
+        int lvIndex = 0;
+        for (int i = 0; i < argTypes.length; i++) {
+            ctor.visitVarInsn(ALOAD, 0);
+            ctor.visitVarInsn(argTypes[i].getOpcode(ILOAD), lvIndex + 1);
+            lvIndex += argTypes[i].getSize();
+            ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argTypes[i].getDescriptor());
+        }
+        ctor.visitInsn(RETURN);
+        ctor.visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
+        ctor.visitEnd();
+    }
+
+    /**
+     * Generate the serialization method (if needed)
+     */
+    /****** This code is out of date -- known to be wrong -- and not currently used ******
+    private void generateSerializationMethod(Type samType, String samMethodName) {
+        String samMethodDesc = samMethodType.toMethodDescriptorString();
+        TypeConvertingMethodAdapter mv = new TypeConvertingMethodAdapter(cw.visitMethod(ACC_PRIVATE + ACC_FINAL, NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE, null, null));
+
+        mv.visitCode();
+        mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA);
+        mv.dup();
+        mv.visitLdcInsn(samType);
+        mv.visitLdcInsn(samMethodName);
+        mv.visitLdcInsn(samMethodDesc);
+        mv.visitLdcInsn(Type.getType(implDefiningClass));
+        mv.visitLdcInsn(implMethodName);
+        mv.visitLdcInsn(implMethodDesc);
+
+        mv.iconst(argTypes.length);
+        mv.visitTypeInsn(ANEWARRAY, NAME_OBJECT);
+        for (int i = 0; i < argTypes.length; i++) {
+            mv.dup();
+            mv.iconst(i);
+            mv.visitVarInsn(ALOAD, 0);
+            mv.getfield(lambdaClassName, argNames[i], argTypes[i].getDescriptor());
+            mv.boxIfPrimitive(argTypes[i]);
+            mv.visitInsn(AASTORE);
+        }
+        mv.invokespecial(NAME_SERIALIZED_LAMBDA, NAME_CTOR,
+                           "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V");
+        mv.visitInsn(ARETURN);
+        mv.visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
+        mv.visitEnd();
+    }
+    ********/
+
+    /**
+     * Generate a method which calls the lambda implementation method,
+     * converting arguments, as needed.
+     * @param m The method whose signature should be generated
+     * @param isBridge True if this methods should be flagged as a bridge
+     */
+    private void generateForwardingMethod(Method m, boolean isBridge) {
+        Class<?>[] exceptionTypes = m.getExceptionTypes();
+        String[] exceptionNames = new String[exceptionTypes.length];
+        for (int i = 0; i < exceptionTypes.length; i++) {
+            exceptionNames[i] = exceptionTypes[i].getName().replace('.', '/');
+        }
+        String methodDescriptor = Type.getMethodDescriptor(m);
+        int access = isBridge? ACC_PUBLIC | ACC_BRIDGE : ACC_PUBLIC;
+        MethodVisitor mv = cw.visitMethod(access, m.getName(), methodDescriptor, null, exceptionNames);
+        new ForwardingMethodGenerator(mv).generate(m);
+    }
+
+    /**
+     * This class generates a method body which calls the lambda implementation
+     * method, converting arguments, as needed.
+     */
+    private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter {
+
+        ForwardingMethodGenerator(MethodVisitor mv) {
+            super(mv);
+        }
+
+        void generate(Method m) throws InternalError {
+            visitCode();
+
+            if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
+                visitTypeInsn(NEW, implMethodClassName);
+                dup();
+            }
+            for (int i = 0; i < argTypes.length; i++) {
+                visitVarInsn(ALOAD, 0);
+                getfield(lambdaClassName, argNames[i], argTypes[i].getDescriptor());
+            }
+
+            convertArgumentTypes(Type.getArgumentTypes(m));
+
+            // Invoke the method we want to forward to
+            visitMethodInsn(invocationOpcode(), implMethodClassName, implMethodName, implMethodDesc);
+
+            // Convert the return value (if any) and return it
+            // Note: if adapting from non-void to void, the 'return' instruction will pop the unneeded result
+            Type samReturnType = Type.getReturnType(m);
+            convertType(implMethodReturnType, samReturnType, samReturnType);
+            areturn(samReturnType);
+
+            visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
+            visitEnd();
+        }
+
+        private void convertArgumentTypes(Type[] samArgumentTypes) {
+            int lvIndex = 0;
+            boolean samIncludesReceiver = implIsInstanceMethod && argTypes.length == 0;
+            int samReceiverLength = samIncludesReceiver ? 1 : 0;
+            if (samIncludesReceiver) {
+                // push receiver
+                Type rcvrType = samArgumentTypes[0];
+                Type instantiatedRcvrType = instantiatedArgumentTypes[0];
+
+                load(lvIndex + 1, rcvrType);
+                lvIndex += rcvrType.getSize();
+                convertType(rcvrType, Type.getType(implDefiningClass), instantiatedRcvrType);
+            }
+            int argOffset = implMethodArgumentTypes.length - samArgumentTypes.length;
+            for (int i = samReceiverLength; i < samArgumentTypes.length; i++) {
+                Type argType = samArgumentTypes[i];
+                Type targetType = implMethodArgumentTypes[argOffset + i];
+                Type instantiatedArgType = instantiatedArgumentTypes[i];
+
+                load(lvIndex + 1, argType);
+                lvIndex += argType.getSize();
+                convertType(argType, targetType, instantiatedArgType);
+            }
+        }
+
+        private void convertType(Type argType, Type targetType, Type functionalType) {
+            convertType(argType.getDescriptor(), targetType.getDescriptor(), functionalType.getDescriptor());
+        }
+
+        private int invocationOpcode() throws InternalError {
+            switch (implKind) {
+                case MethodHandleInfo.REF_invokeStatic:
+                    return INVOKESTATIC;
+                case MethodHandleInfo.REF_newInvokeSpecial:
+                    return INVOKESPECIAL;
+                 case MethodHandleInfo.REF_invokeVirtual:
+                    return INVOKEVIRTUAL;
+                case MethodHandleInfo.REF_invokeInterface:
+                    return INVOKEINTERFACE;
+                case MethodHandleInfo.REF_invokeSpecial:
+                    return INVOKESPECIAL;
+                default:
+                    throw new InternalError("Unexpected invocation kind: " + implKind);
+            }
+        }
+
+        /**
+         * The following methods are copied from
+         * org.objectweb.asm.commons.InstructionAdapter. Part of ASM: a very
+         * small and fast Java bytecode manipulation framework. Copyright (c)
+         * 2000-2005 INRIA, France Telecom All rights reserved.
+         *
+         * Subclass with that (removing these methods) if that package/class is
+         * ever added to the JDK.
+         */
+        private void iconst(final int cst) {
+            if (cst >= -1 && cst <= 5) {
+                mv.visitInsn(Opcodes.ICONST_0 + cst);
+            } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
+                mv.visitIntInsn(Opcodes.BIPUSH, cst);
+            } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
+                mv.visitIntInsn(Opcodes.SIPUSH, cst);
+            } else {
+                mv.visitLdcInsn(cst);
+            }
+        }
+
+        private void load(final int var, final Type type) {
+            mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
+        }
+
+        private void dup() {
+            mv.visitInsn(Opcodes.DUP);
+        }
+
+        private void areturn(final Type t) {
+            mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
+        }
+
+        private void getfield(
+                final String owner,
+                final String name,
+                final String desc) {
+            mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/LambdaConversionException.java	Thu Oct 25 17:34:24 2012 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, 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;
+
+/**
+ * LambdaConversionException
+ */
+public class LambdaConversionException extends Exception {
+    public LambdaConversionException() {
+    }
+
+    public LambdaConversionException(String message) {
+        super(message);
+    }
+
+    public LambdaConversionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public LambdaConversionException(Throwable cause) {
+        super(cause);
+    }
+
+    public LambdaConversionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java	Thu Oct 25 17:34:24 2012 -0700
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2012, 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;
+
+/**
+ * <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p>
+ *
+ * <p>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 mechanism for
+ * evaluating lambda expressions is to invoke an invokedynamic call site, which takes arguments describing the sole
+ * method of the functional interface and the implementation method, and returns an object (the lambda object) that
+ * implements the target type. Methods of the lambda object invoke the implementation method. For method
+ * references, the implementation method is simply the referenced method; for lambda expressions, the
+ * implementation method is produced by the compiler based on the body of the lambda expression. The methods in
+ * this file are the bootstrap methods for those invokedynamic call sites, called lambda factories, and the
+ * bootstrap methods responsible for linking the lambda factories are called lambda meta-factories.
+ *
+ * <p>The bootstrap methods in this class take the information about the functional interface, the implementation
+ * method, and the static types of the captured lambda arguments, and link a call site which, when invoked,
+ * produces the lambda object.
+ *
+ * <p>Two pieces of information are needed about the functional interface: the SAM method and the type of the SAM
+ * method in the functional interface. The type can be different when parameterized types are used. For example,
+ * consider
+ * <code>interface I&lt;T&gt; { int m(T x); }</code> if this SAM type is used in a lambda
+ * <code>I&lt;Byte&gt; v = ...</code>, we need both the actual SAM method which has the signature
+ * <code>(Object)int</code> and the functional interface type of the method, which has signature
+ * <code>(Byte)int</code>.  The latter is the instantiated erased functional interface method type, or
+ * simply <I>instantiated method type</I>.
+ *
+ * <p>While functional interfaces only have a single abstract method from the language perspective (concrete
+ * methods in Object are and default methods may be present), at the bytecode level they may actually have multiple
+ * methods because of the need for bridge methods. Invoking any of these methods on the lambda object will result
+ * in invoking the implementation method.
+ *
+ * <p>The argument list of the implementation method and the argument list of the functional 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. They may also differ because of var-args,
+ * but this is expected to be handled by the compiler.
+ *
+ * <p>Invokedynamic call sites have two argument lists: a static argument list and a dynamic argument list.  The
+ * static argument list lives in the constant pool; the dynamic argument list lives on the operand stack at
+ * invocation time.  The bootstrap method has access to the entire static argument list (which in this case,
+ * contains method handles describing the implementation method and the canonical functional interface method),
+ * 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.
+ *
+ * <p>The implementation method is described with a method handle. In theory, any method handle could be used.
+ * Currently supported are method handles representing invocation of virtual, interface, constructor and static
+ * methods.
+ *
+ * <p>Assume:
+ * <ul>
+ *      <li>the functional interface method has N arguments, of types (U1, U2, ... Un) and return type Ru</li>
+ *      <li>then the instantiated method type also has N arguments, of types (T1, T2, ... Tn) and return type Rt</li>
+ *      <li>the implementation method has M arguments, of types (A1..Am) and return type Ra,</li>
+ *      <li>the dynamic argument list has K arguments of types (D1..Dk), and the invokedynamic return site has
+ *          type Rd</li>
+ *      <li>the functional interface type is F</li>
+ * </ul>
+ *
+ * <p>The following signature invariants must hold:
+ * <ul>
+ *     <li>Rd is a subtype of F</li>
+ *     <li>For i=1..N, Ti is a subtype of Ui</li>
+ *     <li>Either Rt and Ru are primitive and are the same type, or both are reference types and
+ *         Rt is a subtype of Ru</li>
+ *     <li>If the implementation method is a static method:
+ *     <ul>
+ *         <li>K + N = M</li>
+ *         <li>For i=1..K, Di = Ai</li>
+ *         <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
+ *     </ul></li>
+ *     <li>If the implementation method is an instance method:
+ *     <ul>
+ *         <li>K + N = M + 1</li>
+ *         <li>D1 must be a subtype of the enclosing class for the implementation method</li>
+ *         <li>For i=2..K, Di = Aj, where j=i-1</li>
+ *         <li>For i=1..N, Ti is adaptable to Aj, where j=i+k-1</li>
+ *     </ul></li>
+ *     <li>The return type Rt is void, or the return type Ra is not void and is adaptable to Rt</li>
+ * </ul>
+ *
+ * <p>Note that the potentially parameterized implementation return type provides the value for the SAM. Whereas
+ * the completely known instantiated return type is adapted to the implementation arguments. Because the
+ * instantiated type of the implementation method is not available, the adaptability of return types cannot be
+ * checked as precisely at link-time as the arguments can be checked. Thus a loose version of link-time checking is
+ * done on return type, while a strict version is applied to arguments.
+ *
+ * <p>A type Q is considered adaptable to S as follows:
+ * <table>
+ *     <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Capture-time checks</th></tr>
+ *     <tr>
+ *         <td>Primitive</td><td>Primitive</td>
+ *         <td>Q can be converted to S via a primitive widening conversion</td>
+ *         <td>None</td>
+ *     </tr>
+ *     <tr>
+ *         <td>Primitive</td><td>Reference</td>
+ *         <td>S is a supertype of the Wrapper(Q)</td>
+ *         <td>Cast from Wrapper(Q) to S</td>
+ *     </tr>
+ *     <tr>
+ *         <td>Reference</td><td>Primitive</td>
+ *         <td>strict: Q is a primitive wrapper and Primitive(Q) can be widened to S
+ *         <br>loose: If Q is a primitive wrapper, check that Primitive(Q) can be widened to S</td>
+ *         <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types</td>
+ *     </tr>
+ *     <tr>
+ *         <td>Reference</td><td>Reference</td>
+ *         <td>strict: S is a supertype of Q
+ *         <br>loose: none</td>
+ *         <td>Cast from Q to S</td>
+ *     </tr>
+ * </table>
+ *
+ *
+ */
+public class LambdaMetafactory {
+
+    /**
+     * Standard meta-factory for conversion of lambda expressions or method references to functional interfaces.
+     *
+     * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
+     *               of the caller.
+     * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
+     *                    Currently unused.
+     * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
+     *                    expected static type of the returned lambda object, and the static types of the captured
+     *                    arguments for the lambda.  In the event that the implementation method is an instance method,
+     *                    the first argument in the invocation signature will correspond to the receiver.
+     * @param samMethod The primary method in the functional interface to which the lambda or method reference is
+     *                  being converted, represented as a method handle.
+     * @param implMethod The implementation method which should be called (with suitable adaptation of argument
+     *                   types, return types, and adjustment for captured arguments) when methods of the resulting
+     *                   functional interface instance are invoked.
+     * @param instantiatedMethodType The signature of the SAM method from the functional interface's perspective
+     * @return a CallSite, which, when invoked, will return an instance of the functional interface
+     * @throws ReflectiveOperationException
+     * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
+     */
+    public static CallSite metaFactory(MethodHandles.Lookup caller,
+                                       String invokedName,
+                                       MethodType invokedType,
+                                       MethodHandle samMethod,
+                                       MethodHandle implMethod,
+                                       MethodType instantiatedMethodType)
+                   throws ReflectiveOperationException, LambdaConversionException {
+        AbstractValidatingLambdaMetafactory mf;
+        mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType);
+        mf.validateMetafactoryArgs();
+        return mf.buildCallSite();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MagicLambdaImpl.java	Thu Oct 25 17:34:24 2012 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 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;
+
+/** <P> MagicLambdaImpl (named for similarity to MagicAccessorImpl and
+ others, not because it actually implements an interface) is a
+ marker class in the hierarchy. All subclasses of this class are
+ "magically" granted access by the VM to otherwise inaccessible
+ fields and methods of other classes. It is distinct from MagicAccessorImpl
+ because, while we want to bypass accessibility checks, we do not want to
+ bypass verification.</P>
+
+ <P> Do not change the name of this class without also changing the
+ VM's code. </P> */
+
+class MagicLambdaImpl {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java	Thu Oct 25 17:34:24 2012 -0700
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2012, 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 jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import sun.invoke.util.Wrapper;
+import static sun.invoke.util.Wrapper.*;
+
+class TypeConvertingMethodAdapter extends MethodVisitor {
+
+    TypeConvertingMethodAdapter(MethodVisitor mv) {
+        super(Opcodes.ASM4, mv);
+    }
+
+    private static final int NUM_WRAPPERS = Wrapper.values().length;
+
+    private static final String NAME_OBJECT = "java/lang/Object";
+    private static final String WRAPPER_PREFIX = "Ljava/lang/";
+
+    // Same for all primitives; name of the boxing method
+    private static final String NAME_BOX_METHOD = "valueOf";
+
+    // Table of opcodes for widening primitive conversions; NOP = no conversion
+    private static final int[][] wideningOpcodes = new int[NUM_WRAPPERS][NUM_WRAPPERS];
+
+    private static final Wrapper[] FROM_WRAPPER_NAME = new Wrapper[16];
+
+    static {
+        for (Wrapper w : Wrapper.values()) {
+            if (w.basicTypeChar() != 'L') {
+                int wi = hashWrapperName(w.wrapperSimpleName());
+                assert (FROM_WRAPPER_NAME[wi] == null);
+                FROM_WRAPPER_NAME[wi] = w;
+            }
+        }
+
+        for (int i = 0; i < NUM_WRAPPERS; i++) {
+            for (int j = 0; j < NUM_WRAPPERS; j++) {
+                wideningOpcodes[i][j] = Opcodes.NOP;
+            }
+        }
+
+        initWidening(LONG,   Opcodes.I2L, BYTE, SHORT, INT, CHAR);
+        initWidening(LONG,   Opcodes.F2L, FLOAT);
+        initWidening(FLOAT,  Opcodes.I2F, BYTE, SHORT, INT, CHAR);
+        initWidening(FLOAT,  Opcodes.L2F, LONG);
+        initWidening(DOUBLE, Opcodes.I2D, BYTE, SHORT, INT, CHAR);
+        initWidening(DOUBLE, Opcodes.F2D, FLOAT);
+        initWidening(DOUBLE, Opcodes.L2D, LONG);
+    }
+
+    private static void initWidening(Wrapper to, int opcode, Wrapper... from) {
+        for (Wrapper f : from) {
+            wideningOpcodes[f.ordinal()][to.ordinal()] = opcode;
+        }
+    }
+
+    /**
+     * Class name to Wrapper hash, derived from Wrapper.hashWrap()
+     * @param xn
+     * @return The hash code 0-15
+     */
+    private static int hashWrapperName(String xn) {
+        if (xn.length() < 3) {
+            return 0;
+        }
+        return (3 * xn.charAt(1) + xn.charAt(2)) % 16;
+    }
+
+    private Wrapper wrapperOrNullFromDescriptor(String desc) {
+        if (!desc.startsWith(WRAPPER_PREFIX)) {
+            // Not a class type (array or method), so not a boxed type
+            // or not in the right package
+            return null;
+        }
+        // Pare it down to the simple class name
+        String cname = desc.substring(WRAPPER_PREFIX.length(), desc.length() - 1);
+        // Hash to a Wrapper
+        Wrapper w = FROM_WRAPPER_NAME[hashWrapperName(cname)];
+        if (w == null || w.wrapperSimpleName().equals(cname)) {
+            return w;
+        } else {
+            return null;
+        }
+    }
+
+    private static String wrapperName(Wrapper w) {
+        return "java/lang/" + w.wrapperSimpleName();
+    }
+
+    private static String unboxMethod(Wrapper w) {
+        return w.primitiveSimpleName() + "Value";
+    }
+
+    private static String boxingDescriptor(Wrapper w) {
+        return String.format("(%s)L%s;", w.basicTypeChar(), wrapperName(w));
+    }
+
+    private static String unboxingDescriptor(Wrapper w) {
+        return "()" + w.basicTypeChar();
+    }
+
+    void boxIfPrimitive(Wrapper w) {
+        if (w.zero() != null) {
+            box(w);
+        }
+    }
+
+    void widen(Wrapper ws, Wrapper wt) {
+        if (ws != wt) {
+            int opcode = wideningOpcodes[ws.ordinal()][wt.ordinal()];
+            if (opcode != Opcodes.NOP) {
+                visitInsn(opcode);
+            }
+        }
+    }
+
+    void box(Wrapper w) {
+        visitMethodInsn(Opcodes.INVOKESTATIC,
+                wrapperName(w),
+                NAME_BOX_METHOD,
+                boxingDescriptor(w));
+    }
+
+    /**
+     * Convert types by unboxing. The source type is known to be a primitive wrapper.
+     * @param ws A primitive wrapper corresponding to wrapped reference source type
+     * @param wt A primitive wrapper being converted to
+     */
+    void unbox(String sname, Wrapper wt) {
+        visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+                sname,
+                unboxMethod(wt),
+                unboxingDescriptor(wt));
+    }
+
+    private String descriptorToName(String desc) {
+        int last = desc.length() - 1;
+        if (desc.charAt(0) == 'L' && desc.charAt(last) == ';') {
+            // In descriptor form
+            return desc.substring(1, last);
+        } else {
+            // Already in internal name form
+            return desc;
+        }
+    }
+
+    void cast(String ds, String dt) {
+        String ns = descriptorToName(ds);
+        String nt = descriptorToName(dt);
+        if (!nt.equals(ns) && !nt.equals(NAME_OBJECT)) {
+            visitTypeInsn(Opcodes.CHECKCAST, nt);
+        }
+    }
+
+    private boolean isPrimitive(Wrapper w) {
+        return w != OBJECT;
+    }
+
+    private Wrapper toWrapper(String desc) {
+        char first = desc.charAt(0);
+        if (first == '[' || first == '(') {
+            first = 'L';
+        }
+        return Wrapper.forBasicType(first);
+    }
+
+    /**
+     * Convert an argument of type 'argType' to be passed to 'targetType' assuring that it is 'functionalType'.
+     * Insert the needed conversion instructions in the method code.
+     * @param argType
+     * @param targetType
+     * @param functionalType
+     */
+    void convertType(String dArg, String dTarget, String dFunctional) {
+        if (dArg.equals(dTarget)) {
+            return;
+        }
+        Wrapper wArg = toWrapper(dArg);
+        Wrapper wTarget = toWrapper(dTarget);
+        if (wArg == VOID || wTarget == VOID) {
+            return;
+        }
+        if (isPrimitive(wArg)) {
+            if (isPrimitive(wTarget)) {
+                // Both primitives: widening
+                widen(wArg, wTarget);
+            } else {
+                // Primitive argument to reference target
+                Wrapper wPrimTarget = wrapperOrNullFromDescriptor(dTarget);
+                if (wPrimTarget != null) {
+                    // The target is a boxed primitive type, widen to get there before boxing
+                    widen(wArg, wPrimTarget);
+                    box(wPrimTarget);
+                } else {
+                    // Otherwise, box and cast
+                    box(wArg);
+                    cast(wrapperName(wArg), dTarget);
+                }
+            }
+        } else {
+            String dSrc;
+            Wrapper wFunctional = toWrapper(dFunctional);
+            if (isPrimitive(wFunctional)) {
+                dSrc = dArg;
+            } else {
+                // Cast to convert to possibly more specific type, and generate CCE for invalid arg
+                dSrc = dFunctional;
+                cast(dArg, dFunctional);
+            }
+            if (isPrimitive(wTarget)) {
+                // Reference argument to primitive target
+                Wrapper wps = wrapperOrNullFromDescriptor(dSrc);
+                if (wps != null) {
+                    if (wps.isSigned() || wps.isFloating()) {
+                        // Boxed number to primitive
+                        unbox(wrapperName(wps), wTarget);
+                    } else {
+                        // Character or Boolean
+                        unbox(wrapperName(wps), wps);
+                        widen(wps, wTarget);
+                    }
+                } else {
+                    // Source type is reference type, but not boxed type,
+                    // assume it is super type of target type
+                    String intermediate;
+                    if (wTarget.isSigned() || wTarget.isFloating()) {
+                        // Boxed number to primitive
+                        intermediate = "java/lang/Number";
+                    } else {
+                        // Character or Boolean
+                        intermediate = wrapperName(wTarget);
+                    }
+                    cast(dSrc, intermediate);
+                    unbox(intermediate, wTarget);
+                }
+            } else {
+                // Both reference types: just case to target type
+                cast(dSrc, dTarget);
+            }
+        }
+    }
+}