8004969: Generate $deserializeLambda$ method
authorrfield
Fri, 15 Feb 2013 18:40:38 -0800
changeset 16300 7cf27559c8df
parent 16299 05b5bf59c9d3
child 16301 b6fd735ea78e
8004969: Generate $deserializeLambda$ method 8006763: super in method reference used in anonymous class - ClassFormatError is produced 8005632: Inner classes within lambdas cause build failures 8005653: Lambdas containing inner classes referencing external type variables do not correctly parameterize the inner classes Reviewed-by: mcimadamore
langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java
langtools/src/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
langtools/src/share/classes/com/sun/tools/javac/util/Names.java
langtools/test/tools/javac/lambda/LambdaInnerTypeVarArgs.java
langtools/test/tools/javac/lambda/LambdaInnerTypeVarReflect.java
langtools/test/tools/javac/lambda/MethodReference61.java
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Feb 15 11:26:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Feb 15 18:40:38 2013 -0800
@@ -126,6 +126,7 @@
     public final Type stringBuilderType;
     public final Type cloneableType;
     public final Type serializableType;
+    public final Type serializedLambdaType;
     public final Type methodHandleType;
     public final Type methodHandleLookupType;
     public final Type methodTypeType;
@@ -458,6 +459,7 @@
         cloneableType = enterClass("java.lang.Cloneable");
         throwableType = enterClass("java.lang.Throwable");
         serializableType = enterClass("java.io.Serializable");
+        serializedLambdaType = enterClass("java.lang.invoke.SerializedLambda");
         methodHandleType = enterClass("java.lang.invoke.MethodHandle");
         methodHandleLookupType = enterClass("java.lang.invoke.MethodHandles$Lookup");
         methodTypeType = enterClass("java.lang.invoke.MethodType");
@@ -514,6 +516,7 @@
         synthesizeEmptyInterfaceIfMissing(cloneableType);
         synthesizeEmptyInterfaceIfMissing(serializableType);
         synthesizeEmptyInterfaceIfMissing(lambdaMetafactory);
+        synthesizeEmptyInterfaceIfMissing(serializedLambdaType);
         synthesizeBoxTypeIfMissing(doubleType);
         synthesizeBoxTypeIfMissing(floatType);
         synthesizeBoxTypeIfMissing(voidType);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Feb 15 11:26:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Feb 15 18:40:38 2013 -0800
@@ -48,6 +48,7 @@
 import static com.sun.tools.javac.code.Symbol.*;
 import static com.sun.tools.javac.code.Type.*;
 import static com.sun.tools.javac.code.TypeTag.*;
+import static com.sun.tools.javac.jvm.ClassFile.externalize;
 import static com.sun.tools.javac.util.ListBuffer.lb;
 
 /**
@@ -4354,4 +4355,172 @@
         return vis;
     }
     // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Signature Generation">
+
+    public static abstract class SignatureGenerator {
+
+        private final Types types;
+
+        protected abstract void append(char ch);
+        protected abstract void append(byte[] ba);
+        protected abstract void append(Name name);
+        protected void classReference(ClassSymbol c) { /* by default: no-op */ }
+
+        protected SignatureGenerator(Types types) {
+            this.types = types;
+        }
+
+        /**
+         * Assemble signature of given type in string buffer.
+         */
+        public void assembleSig(Type type) {
+            type = type.unannotatedType();
+            switch (type.getTag()) {
+                case BYTE:
+                    append('B');
+                    break;
+                case SHORT:
+                    append('S');
+                    break;
+                case CHAR:
+                    append('C');
+                    break;
+                case INT:
+                    append('I');
+                    break;
+                case LONG:
+                    append('J');
+                    break;
+                case FLOAT:
+                    append('F');
+                    break;
+                case DOUBLE:
+                    append('D');
+                    break;
+                case BOOLEAN:
+                    append('Z');
+                    break;
+                case VOID:
+                    append('V');
+                    break;
+                case CLASS:
+                    append('L');
+                    assembleClassSig(type);
+                    append(';');
+                    break;
+                case ARRAY:
+                    ArrayType at = (ArrayType) type;
+                    append('[');
+                    assembleSig(at.elemtype);
+                    break;
+                case METHOD:
+                    MethodType mt = (MethodType) type;
+                    append('(');
+                    assembleSig(mt.argtypes);
+                    append(')');
+                    assembleSig(mt.restype);
+                    if (hasTypeVar(mt.thrown)) {
+                        for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) {
+                            append('^');
+                            assembleSig(l.head);
+                        }
+                    }
+                    break;
+                case WILDCARD: {
+                    Type.WildcardType ta = (Type.WildcardType) type;
+                    switch (ta.kind) {
+                        case SUPER:
+                            append('-');
+                            assembleSig(ta.type);
+                            break;
+                        case EXTENDS:
+                            append('+');
+                            assembleSig(ta.type);
+                            break;
+                        case UNBOUND:
+                            append('*');
+                            break;
+                        default:
+                            throw new AssertionError(ta.kind);
+                    }
+                    break;
+                }
+                case TYPEVAR:
+                    append('T');
+                    append(type.tsym.name);
+                    append(';');
+                    break;
+                case FORALL:
+                    Type.ForAll ft = (Type.ForAll) type;
+                    assembleParamsSig(ft.tvars);
+                    assembleSig(ft.qtype);
+                    break;
+                default:
+                    throw new AssertionError("typeSig " + type.getTag());
+            }
+        }
+
+        public boolean hasTypeVar(List<Type> l) {
+            while (l.nonEmpty()) {
+                if (l.head.hasTag(TypeTag.TYPEVAR)) {
+                    return true;
+                }
+                l = l.tail;
+            }
+            return false;
+        }
+
+        public void assembleClassSig(Type type) {
+            type = type.unannotatedType();
+            ClassType ct = (ClassType) type;
+            ClassSymbol c = (ClassSymbol) ct.tsym;
+            classReference(c);
+            Type outer = ct.getEnclosingType();
+            if (outer.allparams().nonEmpty()) {
+                boolean rawOuter =
+                        c.owner.kind == Kinds.MTH || // either a local class
+                        c.name == types.names.empty; // or anonymous
+                assembleClassSig(rawOuter
+                        ? types.erasure(outer)
+                        : outer);
+                append('.');
+                Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname));
+                append(rawOuter
+                        ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength() + 1, c.flatname.getByteLength())
+                        : c.name);
+            } else {
+                append(externalize(c.flatname));
+            }
+            if (ct.getTypeArguments().nonEmpty()) {
+                append('<');
+                assembleSig(ct.getTypeArguments());
+                append('>');
+            }
+        }
+
+        public void assembleParamsSig(List<Type> typarams) {
+            append('<');
+            for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) {
+                Type.TypeVar tvar = (Type.TypeVar) ts.head;
+                append(tvar.tsym.name);
+                List<Type> bounds = types.getBounds(tvar);
+                if ((bounds.head.tsym.flags() & INTERFACE) != 0) {
+                    append(':');
+                }
+                for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) {
+                    append(':');
+                    assembleSig(l.head);
+                }
+            }
+            append('>');
+        }
+
+        private void assembleSig(List<Type> types) {
+            for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) {
+                assembleSig(ts.head);
+            }
+        }
+    }
+    // </editor-fold>
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Feb 15 11:26:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Feb 15 18:40:38 2013 -0800
@@ -31,8 +31,8 @@
 import com.sun.tools.javac.tree.TreeMaker;
 import com.sun.tools.javac.tree.TreeScanner;
 import com.sun.tools.javac.tree.TreeTranslator;
-import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.Scope;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
@@ -57,9 +57,7 @@
 import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*;
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.*;
-import static com.sun.tools.javac.code.TypeTag.BOT;
-import static com.sun.tools.javac.code.TypeTag.NONE;
-import static com.sun.tools.javac.code.TypeTag.VOID;
+import static com.sun.tools.javac.code.TypeTag.*;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /**
@@ -89,9 +87,51 @@
     /** current translation context (visitor argument) */
     private TranslationContext<?> context;
 
-    /** list of translated methods
-     **/
-    private ListBuffer<JCTree> translatedMethodList;
+    /** info about the current class being processed */
+    private KlassInfo kInfo;
+
+    /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
+    public static final int FLAG_SERIALIZABLE = 1 << 0;
+
+    /** Flag for alternate metafactories indicating the lambda object has multiple targets */
+    public static final int FLAG_MARKERS = 1 << 1;
+
+    private class KlassInfo {
+
+        /**
+         * list of methods to append
+         */
+        private ListBuffer<JCTree> appendedMethodList;
+
+        /**
+         * list of deserialization cases
+         */
+        private final Map<String, ListBuffer<JCStatement>> deserializeCases;
+
+       /**
+         * deserialize method symbol
+         */
+        private final MethodSymbol deserMethodSym;
+
+        /**
+         * deserialize method parameter symbol
+         */
+        private final VarSymbol deserParamSym;
+
+        private KlassInfo(Symbol kSym) {
+            appendedMethodList = ListBuffer.lb();
+            deserializeCases = new HashMap<String, ListBuffer<JCStatement>>();
+            long flags = PRIVATE | STATIC | SYNTHETIC;
+            MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType,
+                    List.<Type>nil(), syms.methodClass);
+            deserMethodSym = makeSyntheticMethod(flags, names.deserializeLambda, type, kSym);
+            deserParamSym = new VarSymbol(FINAL, names.fromString("lambda"), syms.serializedLambdaType, deserMethodSym);
+        }
+
+        private void addMethod(JCTree decl) {
+            appendedMethodList = appendedMethodList.prepend(decl);
+        }
+    }
 
     // <editor-fold defaultstate="collapsed" desc="Instantiating">
     private static final Context.Key<LambdaToMethod> unlambdaKey =
@@ -112,11 +152,7 @@
         make = TreeMaker.instance(context);
         types = Types.instance(context);
         transTypes = TransTypes.instance(context);
-        this.analyzer = makeAnalyzer();
-    }
-
-    private LambdaAnalyzer makeAnalyzer() {
-        return new LambdaAnalyzer();
+        analyzer = new LambdaAnalyzer();
     }
     // </editor-fold>
 
@@ -168,18 +204,22 @@
             //analyze class
             analyzer.analyzeClass(tree);
         }
-        ListBuffer<JCTree> prevTranslated = translatedMethodList;
+        KlassInfo prevKlassInfo = kInfo;
         try {
-            translatedMethodList = ListBuffer.lb();
+            kInfo = new KlassInfo(tree.sym);
             super.visitClassDef(tree);
+            if (!kInfo.deserializeCases.isEmpty()) {
+                kInfo.addMethod(makeDeserializeMethod(tree.sym));
+            }
             //add all translated instance methods here
-            tree.defs = tree.defs.appendList(translatedMethodList.toList());
-            for (JCTree lambda : translatedMethodList) {
+            List<JCTree> newMethods = kInfo.appendedMethodList.toList();
+            tree.defs = tree.defs.appendList(newMethods);
+            for (JCTree lambda : newMethods) {
                 tree.sym.members().enter(((JCMethodDecl)lambda).sym);
             }
             result = tree;
         } finally {
-            translatedMethodList = prevTranslated;
+            kInfo = prevKlassInfo;
         }
     }
 
@@ -217,7 +257,7 @@
         lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
 
         //Add the method to the list of methods to be added to this class.
-        translatedMethodList = translatedMethodList.prepend(lambdaDecl);
+        kInfo.addMethod(lambdaDecl);
 
         //now that we have generated a method for the lambda expression,
         //we can translate the lambda into a method reference pointing to the newly
@@ -234,7 +274,7 @@
 
         if (!sym.isStatic()) {
             syntheticInits.append(makeThis(
-                    sym.owner.asType(),
+                    sym.owner.enclClass().asType(),
                     localContext.owner.enclClass()));
         }
 
@@ -253,7 +293,7 @@
         int refKind = referenceKind(sym);
 
         //convert to an invokedynamic call
-        result = makeMetaFactoryIndyCall(tree, refKind, sym, indy_args);
+        result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args);
     }
 
     private JCIdent makeThis(Type type, Symbol owner) {
@@ -291,8 +331,8 @@
             case IMPLICIT_INNER:    /** Inner :: new */
             case SUPER:             /** super :: instMethod */
                 init = makeThis(
-                    localContext.owner.owner.asType(),
-                    localContext.owner);
+                    localContext.owner.enclClass().asType(),
+                    localContext.owner.enclClass());
                 break;
 
             case BOUND:             /** Expr :: instMethod */
@@ -314,7 +354,7 @@
 
 
         //build a sam instance using an indy call to the meta-factory
-        result = makeMetaFactoryIndyCall(tree, localContext.referenceKind(), refSym, indy_args);
+        result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args);
     }
 
     /**
@@ -333,6 +373,9 @@
             } else if (lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
                 Symbol translatedSym = lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym);
                 result = make.Ident(translatedSym).setType(tree.type);
+            } else if (lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) {
+                Symbol translatedSym = lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym);
+                result = make.Ident(translatedSym).setType(translatedSym.type);
             } else if (lambdaContext.getSymbolMap(CAPTURED_VAR).containsKey(tree.sym)) {
                 Symbol translatedSym = lambdaContext.getSymbolMap(CAPTURED_VAR).get(tree.sym);
                 result = make.Ident(translatedSym).setType(tree.type);
@@ -362,6 +405,16 @@
         if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
             JCExpression init = translate(tree.init);
             result = make.VarDef((VarSymbol)lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym), init);
+        } else if (context != null && lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) {
+            JCExpression init = translate(tree.init);
+            VarSymbol xsym = (VarSymbol)lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym);
+            result = make.VarDef(xsym, init);
+            // Replace the entered symbol for this variable
+            Scope sc = tree.sym.owner.members();
+            if (sc != null) {
+                sc.remove(tree.sym);
+                sc.enter(xsym);
+            }
         } else {
             super.visitVarDef(tree);
         }
@@ -451,6 +504,135 @@
         return trans_block;
     }
 
+    private JCMethodDecl makeDeserializeMethod(Symbol kSym) {
+        ListBuffer<JCCase> cases = ListBuffer.lb();
+        ListBuffer<JCBreak> breaks = ListBuffer.lb();
+        for (Map.Entry<String, ListBuffer<JCStatement>> entry : kInfo.deserializeCases.entrySet()) {
+            JCBreak br = make.Break(null);
+            breaks.add(br);
+            List<JCStatement> stmts = entry.getValue().append(br).toList();
+            cases.add(make.Case(make.Literal(entry.getKey()), stmts));
+        }
+        JCSwitch sw = make.Switch(deserGetter("getImplMethodName", syms.stringType), cases.toList());
+        for (JCBreak br : breaks) {
+            br.target = sw;
+        }
+        JCBlock body = make.Block(0L, List.<JCStatement>of(
+                sw,
+                make.Throw(makeNewClass(
+                    syms.illegalArgumentExceptionType,
+                    List.<JCExpression>of(make.Literal("Invalid lambda deserialization"))))));
+        JCMethodDecl deser = make.MethodDef(make.Modifiers(kInfo.deserMethodSym.flags()),
+                        names.deserializeLambda,
+                        make.QualIdent(kInfo.deserMethodSym.getReturnType().tsym),
+                        List.<JCTypeParameter>nil(),
+                        List.of(make.VarDef(kInfo.deserParamSym, null)),
+                        List.<JCExpression>nil(),
+                        body,
+                        null);
+        deser.sym = kInfo.deserMethodSym;
+        deser.type = kInfo.deserMethodSym.type;
+        //System.err.printf("DESER: '%s'\n", deser);
+        return deser;
+    }
+
+    /** Make an attributed class instance creation expression.
+     *  @param ctype    The class type.
+     *  @param args     The constructor arguments.
+     */
+    JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
+        JCNewClass tree = make.NewClass(null,
+            null, make.QualIdent(ctype.tsym), args, null);
+        tree.constructor = rs.resolveConstructor(
+            null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil());
+        tree.type = ctype;
+        return tree;
+    }
+
+    private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
+            DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
+        String functionalInterfaceClass = classSig(targetType);
+        String functionalInterfaceMethodName = samSym.getSimpleName().toString();
+        String functionalInterfaceMethodSignature = methodSig(types.erasure(samSym.type));
+        String implClass = classSig(refSym.owner.type);
+        String implMethodName = refSym.getQualifiedName().toString();
+        String implMethodSignature = methodSig(types.erasure(refSym.type));
+
+        JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
+        ListBuffer<JCExpression> serArgs = ListBuffer.lb();
+        int i = 0;
+        for (Type t : indyType.getParameterTypes()) {
+            List<JCExpression> indexAsArg = ListBuffer.<JCExpression>lb().append(make.Literal(i)).toList();
+            List<Type> argTypes = ListBuffer.<Type>lb().append(syms.intType).toList();
+            serArgs.add(make.TypeCast(types.erasure(t), deserGetter("getCapturedArg", syms.objectType, argTypes, indexAsArg)));
+            ++i;
+        }
+        JCStatement stmt = make.If(
+                deserTest(deserTest(deserTest(deserTest(deserTest(
+                    kindTest,
+                    "getFunctionalInterfaceClass", functionalInterfaceClass),
+                    "getFunctionalInterfaceMethodName", functionalInterfaceMethodName),
+                    "getFunctionalInterfaceMethodSignature", functionalInterfaceMethodSignature),
+                    "getImplClass", implClass),
+                    "getImplMethodSignature", implMethodSignature),
+                make.Return(makeIndyCall(
+                    pos,
+                    syms.lambdaMetafactory,
+                    names.altMetaFactory,
+                    staticArgs, indyType, serArgs.toList())),
+                null);
+        ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
+        if (stmts == null) {
+            stmts = ListBuffer.lb();
+            kInfo.deserializeCases.put(implMethodName, stmts);
+        }
+        /****
+        System.err.printf("+++++++++++++++++\n");
+        System.err.printf("*functionalInterfaceClass: '%s'\n", functionalInterfaceClass);
+        System.err.printf("*functionalInterfaceMethodName: '%s'\n", functionalInterfaceMethodName);
+        System.err.printf("*functionalInterfaceMethodSignature: '%s'\n", functionalInterfaceMethodSignature);
+        System.err.printf("*implMethodKind: %d\n", implMethodKind);
+        System.err.printf("*implClass: '%s'\n", implClass);
+        System.err.printf("*implMethodName: '%s'\n", implMethodName);
+        System.err.printf("*implMethodSignature: '%s'\n", implMethodSignature);
+        ****/
+        stmts.append(stmt);
+    }
+
+    private JCExpression eqTest(Type argType, JCExpression arg1, JCExpression arg2) {
+        JCBinary testExpr = make.Binary(JCTree.Tag.EQ, arg1, arg2);
+        testExpr.operator = rs.resolveBinaryOperator(null, JCTree.Tag.EQ, attrEnv, argType, argType);
+        testExpr.setType(syms.booleanType);
+        return testExpr;
+    }
+
+    private JCExpression deserTest(JCExpression prev, String func, String lit) {
+        MethodType eqmt = new MethodType(List.of(syms.objectType), syms.booleanType, List.<Type>nil(), syms.methodClass);
+        Symbol eqsym = rs.resolveQualifiedMethod(null, attrEnv, syms.objectType, names.equals, List.of(syms.objectType), List.<Type>nil());
+        JCMethodInvocation eqtest = make.Apply(
+                List.<JCExpression>nil(),
+                make.Select(deserGetter(func, syms.stringType), eqsym).setType(eqmt),
+                List.<JCExpression>of(make.Literal(lit)));
+        eqtest.setType(syms.booleanType);
+        JCBinary compound = make.Binary(JCTree.Tag.AND, prev, eqtest);
+        compound.operator = rs.resolveBinaryOperator(null, JCTree.Tag.AND, attrEnv, syms.booleanType, syms.booleanType);
+        compound.setType(syms.booleanType);
+        return compound;
+    }
+
+    private JCExpression deserGetter(String func, Type type) {
+        return deserGetter(func, type, List.<Type>nil(), List.<JCExpression>nil());
+    }
+
+    private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) {
+        MethodType getmt = new MethodType(argTypes, type, List.<Type>nil(), syms.methodClass);
+        Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.<Type>nil());
+        return make.Apply(
+                    List.<JCExpression>nil(),
+                    make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt),
+                    args).setType(type);
+    }
+
     /**
      * Create new synthetic method with given flags, name, type, owner
      */
@@ -678,14 +860,14 @@
      * * super is used
      */
     private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) {
-        JCMethodDecl bridgeDecl = (new MemberReferenceBridger(tree, localContext).bridge());
-        translatedMethodList = translatedMethodList.prepend(bridgeDecl);
+        kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge());
     }
 
     /**
      * Generate an indy method call to the meta factory
      */
-    private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, int refKind, Symbol refSym, List<JCExpression> indy_args) {
+    private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory,
+            boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) {
         //determine the static bsm args
         Type mtype = types.erasure(tree.descriptorType);
         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
@@ -709,7 +891,31 @@
                 List.<Type>nil(),
                 syms.methodClass);
 
-        return makeIndyCall(tree, syms.lambdaMetafactory, names.metaFactory, staticArgs, indyType, indy_args);
+        Name metafactoryName = needsAltMetafactory ?
+                names.altMetaFactory : names.metaFactory;
+
+        if (needsAltMetafactory) {
+            ListBuffer<Object> markers = ListBuffer.lb();
+            for (Symbol t : tree.targets.tail) {
+                if (t != syms.serializableType.tsym) {
+                    markers.append(t);
+                }
+            }
+            int flags = isSerializable? FLAG_SERIALIZABLE : 0;
+            boolean hasMarkers = markers.nonEmpty();
+            flags |= hasMarkers ? FLAG_MARKERS : 0;
+            staticArgs = staticArgs.append(flags);
+            if (hasMarkers) {
+                staticArgs = staticArgs.append(markers.length());
+                staticArgs = staticArgs.appendList(markers.toList());
+            }
+            if (isSerializable) {
+                addDeserializationCase(refKind, refSym, tree.type, samSym,
+                        tree, staticArgs, indyType);
+            }
+        }
+
+        return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args);
     }
 
     /**
@@ -795,6 +1001,7 @@
             }
         }
     }
+
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">\
@@ -814,6 +1021,20 @@
          */
         private int lambdaCount = 0;
 
+        /**
+         * keep the count of lambda expression defined in given context (used to
+         * generate unambiguous names for serializable lambdas)
+         */
+        private Map<String, Integer> serializableLambdaCounts =
+                new HashMap<String, Integer>();
+
+        /**
+         * maps for fake clinit symbols to be used as owners of lambda occurring in
+         * a static var init context
+         */
+        private Map<ClassSymbol, Symbol> clinits =
+                new HashMap<ClassSymbol, Symbol>();
+
         private void analyzeClass(JCClassDecl tree) {
             frameStack = List.nil();
             scan(tree);
@@ -836,21 +1057,26 @@
         @Override
         public void visitClassDef(JCClassDecl tree) {
             List<Frame> prevStack = frameStack;
+            Map<String, Integer> prevSerializableLambdaCount = serializableLambdaCounts;
+            Map<ClassSymbol, Symbol> prevClinits = clinits;
             try {
-                if (frameStack.nonEmpty() && enclosingLambda() != null) {
+                serializableLambdaCounts = new HashMap<String, Integer>();
+                prevClinits = new HashMap<ClassSymbol, Symbol>();
+                if (directlyEnclosingLambda() != null) {
                     tree.sym.owner = owner();
-                    LambdaTranslationContext lambdaContext = (LambdaTranslationContext)contextMap.get(enclosingLambda());
+                    LambdaTranslationContext lambdaContext = (LambdaTranslationContext) contextMap.get(directlyEnclosingLambda());
                     Type encl = lambdaContext.enclosingType();
                     if (encl.hasTag(NONE)) {
                         //if the translated lambda body occurs in a static context,
                         //any class declaration within it must be made static
+                        //@@@TODO: What about nested classes within lambda?
                         tree.sym.flags_field |= STATIC;
-                        ((ClassType)tree.sym.type).setEnclosingType(Type.noType);
+                        ((ClassType) tree.sym.type).setEnclosingType(Type.noType);
                     } else {
                         //if the translated lambda body is in an instance context
                         //the enclosing type of any class declaration within it
                         //must be updated to point to the new enclosing type (if any)
-                        ((ClassType)tree.sym.type).setEnclosingType(encl);
+                        ((ClassType) tree.sym.type).setEnclosingType(encl);
                     }
                 }
                 frameStack = frameStack.prepend(new Frame(tree));
@@ -858,8 +1084,10 @@
             }
             finally {
                 frameStack = prevStack;
+                serializableLambdaCounts = prevSerializableLambdaCount;
+                clinits = prevClinits;
             }
-            if (!tree.sym.isStatic() && frameStack.nonEmpty() && enclosingLambda() != null) {
+            if (!tree.sym.isStatic() && directlyEnclosingLambda() != null) {
                 // Any (non-static) class defined within a lambda is an implicit 'this' reference
                 // because its constructor will reference the enclosing class
                 ((LambdaTranslationContext) context()).addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS);
@@ -868,9 +1096,7 @@
 
         @Override
         public void visitIdent(JCIdent tree) {
-            if (context() == null || !lambdaIdentSymbolFilter(tree.sym)) {
-                super.visitIdent(tree);
-            } else {
+            if (context() != null && lambdaIdentSymbolFilter(tree.sym)) {
                 if (tree.sym.kind == VAR &&
                         tree.sym.owner.kind == MTH &&
                         tree.type.constValue() == null) {
@@ -902,6 +1128,7 @@
                     }
                 }
             }
+            super.visitIdent(tree);
         }
 
         @Override
@@ -969,9 +1196,22 @@
 
         @Override
         public void visitVarDef(JCVariableDecl tree) {
-            if (frameStack.head.tree.hasTag(LAMBDA)) {
-                ((LambdaTranslationContext)context()).addSymbol(tree.sym, LOCAL_VAR);
+            TranslationContext<?> context = context();
+            LambdaTranslationContext ltc = (context != null && context instanceof LambdaTranslationContext)?
+                    (LambdaTranslationContext)context :
+                    null;
+            if (ltc != null) {
+                if (frameStack.head.tree.hasTag(LAMBDA)) {
+                    ltc.addSymbol(tree.sym, LOCAL_VAR);
+                }
+                // Check for type variables (including as type arguments).
+                // If they occur within class nested in a lambda, mark for erasure
+                Type type = tree.sym.asType();
+                if (inClassWithinLambda() && !types.isSameType(types.erasure(type), type)) {
+                    ltc.addSymbol(tree.sym, TYPE_VAR);
+                }
             }
+
             List<Frame> prevStack = frameStack;
             try {
                 if (tree.sym.owner.kind == MTH) {
@@ -986,7 +1226,25 @@
         }
 
         private Name lambdaName() {
-            return names.lambda.append(names.fromString("$" + lambdaCount++));
+            return names.lambda.append(names.fromString("" + lambdaCount++));
+        }
+
+        private Name serializedLambdaName(Symbol owner) {
+            StringBuilder buf = new StringBuilder();
+            buf.append(names.lambda);
+            buf.append(owner.name);
+            buf.append('$');
+            int methTypeHash = methodSig(owner.type).hashCode();
+            buf.append(methTypeHash);
+            buf.append('$');
+            String temp = buf.toString();
+            Integer count = serializableLambdaCounts.get(temp);
+            if (count == null) {
+                count = 0;
+            }
+            buf.append(count++);
+            serializableLambdaCounts.put(temp, count);
+            return names.fromString(buf.toString());
         }
 
         /**
@@ -1008,10 +1266,12 @@
                             break;
                         }
                         JCClassDecl cdecl = (JCClassDecl)frameStack2.tail.head.tree;
-                        return makeSyntheticMethod(((JCVariableDecl)frameStack2.head.tree).sym.flags() & STATIC, names.empty, null, cdecl.sym);
+                        return initSym(cdecl.sym,
+                                ((JCVariableDecl)frameStack2.head.tree).sym.flags() & STATIC);
                     case BLOCK:
                         JCClassDecl cdecl2 = (JCClassDecl)frameStack2.tail.head.tree;
-                        return makeSyntheticMethod(((JCBlock)frameStack2.head.tree).flags & STATIC | Flags.BLOCK, names.empty, null, cdecl2.sym);
+                        return initSym(cdecl2.sym,
+                                ((JCBlock)frameStack2.head.tree).flags & STATIC);
                     case CLASSDEF:
                         return ((JCClassDecl)frameStack2.head.tree).sym;
                     case METHODDEF:
@@ -1027,7 +1287,33 @@
             return null;
         }
 
-        private JCTree enclosingLambda() {
+        private Symbol initSym(ClassSymbol csym, long flags) {
+            boolean isStatic = (flags & STATIC) != 0;
+            if (isStatic) {
+                //static clinits are generated in Gen - so we need to fake them
+                Symbol clinit = clinits.get(csym);
+                if (clinit == null) {
+                    clinit = makeSyntheticMethod(STATIC,
+                            names.clinit,
+                            new MethodType(List.<Type>nil(), syms.voidType, List.<Type>nil(), syms.methodClass),
+                            csym);
+                    clinits.put(csym, clinit);
+                }
+                return clinit;
+            } else {
+                //get the first constructor and treat it as the instance init sym
+                for (Symbol s : csym.members_field.getElementsByName(names.init)) {
+                    return s;
+                }
+            }
+            Assert.error("init not found");
+            return null;
+        }
+
+        private JCTree directlyEnclosingLambda() {
+            if (frameStack.isEmpty()) {
+                return null;
+            }
             List<Frame> frameStack2 = frameStack;
             while (frameStack2.nonEmpty()) {
                 switch (frameStack2.head.tree.getTag()) {
@@ -1044,6 +1330,28 @@
             return null;
         }
 
+        private boolean inClassWithinLambda() {
+            if (frameStack.isEmpty()) {
+                return false;
+            }
+            List<Frame> frameStack2 = frameStack;
+            boolean classFound = false;
+            while (frameStack2.nonEmpty()) {
+                switch (frameStack2.head.tree.getTag()) {
+                    case LAMBDA:
+                        return classFound;
+                    case CLASSDEF:
+                        classFound = true;
+                        frameStack2 = frameStack2.tail;
+                        break;
+                    default:
+                        frameStack2 = frameStack2.tail;
+                }
+            }
+            // No lambda
+            return false;
+        }
+
         /**
          * Return the declaration corresponding to a symbol in the enclosing
          * scope; the depth parameter is used to filter out symbols defined
@@ -1178,6 +1486,22 @@
                 this.depth = frameStack.size() - 1;
                 this.prev = context();
             }
+
+            /** does this functional expression need to be created using alternate metafactory? */
+            boolean needsAltMetafactory() {
+                return (tree.targets.length() > 1 ||
+                        isSerializable());
+            }
+
+            /** does this functional expression require serialization support? */
+            boolean isSerializable() {
+                for (Symbol target : tree.targets) {
+                    if (types.asSuper(target.type, syms.serializableType.tsym) != null) {
+                        return true;
+                    }
+                }
+                return false;
+            }
         }
 
         /**
@@ -1203,6 +1527,9 @@
             /** map from class symbols to translated synthetic parameters (for captured member access) */
             Map<Symbol, Symbol> capturedThis = new LinkedHashMap<Symbol, Symbol>();
 
+            /** map from original to translated lambda locals */
+            Map<Symbol, Symbol> typeVars = new LinkedHashMap<Symbol, Symbol>();
+
             /** the synthetic symbol for the method hoisting the translated lambda */
             Symbol translatedSym;
 
@@ -1214,7 +1541,8 @@
                 if (frame.tree.hasTag(VARDEF)) {
                     self = ((JCVariableDecl)frame.tree).sym;
                 }
-                this.translatedSym = makeSyntheticMethod(0, lambdaName(), null, owner.enclClass());
+                Name name = isSerializable() ? serializedLambdaName(owner) : lambdaName();
+                this.translatedSym = makeSyntheticMethod(0, name, null, owner.enclClass());
             }
 
             /**
@@ -1222,10 +1550,14 @@
              * synthetic lambda body
              */
             Symbol translate(String name, Symbol sym, LambdaSymbolKind skind) {
-                if (skind == CAPTURED_THIS) {
-                    return sym;  // self represented
-                } else {
-                    return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym);
+                switch (skind) {
+                    case CAPTURED_THIS:
+                        return sym;  // self represented
+                    case TYPE_VAR:
+                        // Just erase the type var
+                        return new VarSymbol(sym.flags(), names.fromString(name), types.erasure(sym.type), sym.owner);
+                    default:
+                        return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym);
                 }
             }
 
@@ -1249,6 +1581,10 @@
                         transMap = lambdaParams;
                         preferredName = sym.name.toString();
                         break;
+                    case TYPE_VAR:
+                        transMap = typeVars;
+                        preferredName = sym.name.toString();
+                        break;
                     default: throw new AssertionError();
                 }
                 if (!transMap.containsKey(sym)) {
@@ -1272,6 +1608,9 @@
                         case PARAM:
                             translationMap.putAll(lambdaParams);
                             break;
+                        case TYPE_VAR:
+                            translationMap.putAll(typeVars);
+                            break;
                         default: throw new AssertionError();
                     }
                 }
@@ -1311,8 +1650,8 @@
                 syntheticParams = params.toList();
 
                 //prepend synthetic args to translated lambda method signature
-                translatedSym.type = (MethodType) types.createMethodTypeWithParameters(
-                        (MethodType) generatedLambdaSig(),
+                translatedSym.type = types.createMethodTypeWithParameters(
+                        generatedLambdaSig(),
                         TreeInfo.types(syntheticParams));
             }
 
@@ -1389,6 +1728,60 @@
         CAPTURED_VAR,
         CAPTURED_THIS,
         LOCAL_VAR,
-        PARAM;
+        PARAM,
+        TYPE_VAR;
+    }
+
+    /**
+     * ****************************************************************
+     * Signature Generation
+     * ****************************************************************
+     */
+
+    private String methodSig(Type type) {
+        L2MSignatureGenerator sg = new L2MSignatureGenerator();
+        sg.assembleSig(type);
+        return sg.toString();
+    }
+
+    private String classSig(Type type) {
+        L2MSignatureGenerator sg = new L2MSignatureGenerator();
+        sg.assembleClassSig(type);
+        return sg.toString();
+    }
+
+    /**
+     * Signature Generation
+     */
+    private class L2MSignatureGenerator extends Types.SignatureGenerator {
+
+        /**
+         * An output buffer for type signatures.
+         */
+        StringBuilder sb = new StringBuilder();
+
+        L2MSignatureGenerator() {
+            super(types);
+        }
+
+        @Override
+        protected void append(char ch) {
+            sb.append(ch);
+        }
+
+        @Override
+        protected void append(byte[] ba) {
+            sb.append(new String(ba));
+        }
+
+        @Override
+        protected void append(Name name) {
+            sb.append(name.toString());
+        }
+
+        @Override
+        public String toString() {
+            return sb.toString();
+        }
     }
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Feb 15 11:26:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Feb 15 18:40:38 2013 -0800
@@ -309,7 +309,9 @@
     /** Add member to class unless it is synthetic.
      */
     private void enterMember(ClassSymbol c, Symbol sym) {
-        if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC)
+        // Synthetic members are not entered -- reason lost to history (optimization?).
+        // Lambda methods must be entered because they may have inner classes (which reference them)
+        if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda))
             c.members_field.enter(sym);
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Feb 15 11:26:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Feb 15 18:40:38 2013 -0800
@@ -39,6 +39,9 @@
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
 import com.sun.tools.javac.code.Attribute.TypeCompound;
+import static com.sun.tools.javac.code.BoundKind.EXTENDS;
+import static com.sun.tools.javac.code.BoundKind.SUPER;
+import static com.sun.tools.javac.code.BoundKind.UNBOUND;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Types.UniqueType;
@@ -126,10 +129,6 @@
      */
     ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
 
-    /** An output buffer for type signatures.
-     */
-    ByteBuffer sigbuf = new ByteBuffer();
-
     /** The constant pool.
      */
     Pool pool;
@@ -158,6 +157,9 @@
     /** Access to files. */
     private final JavaFileManager fileManager;
 
+    /** Sole signature generator */
+    private final CWSignatureGenerator signatureGen;
+
     /** The tags and constants used in compressed stackmap. */
     static final int SAME_FRAME_SIZE = 64;
     static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
@@ -185,6 +187,7 @@
         source = Source.instance(context);
         types = Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
+        signatureGen = new CWSignatureGenerator(types);
 
         verbose        = options.isSet(VERBOSE);
         scramble       = options.isSet("-scramble");
@@ -270,172 +273,81 @@
         buf.elems[adr+3] = (byte)((x      ) & 0xFF);
     }
 
-/******************************************************************
- * Signature Generation
- ******************************************************************/
-
-    /** Assemble signature of given type in string buffer.
+    /**
+     * Signature Generation
      */
-    void assembleSig(Type type) {
-        type = type.unannotatedType();
-        switch (type.getTag()) {
-        case BYTE:
-            sigbuf.appendByte('B');
-            break;
-        case SHORT:
-            sigbuf.appendByte('S');
-            break;
-        case CHAR:
-            sigbuf.appendByte('C');
-            break;
-        case INT:
-            sigbuf.appendByte('I');
-            break;
-        case LONG:
-            sigbuf.appendByte('J');
-            break;
-        case FLOAT:
-            sigbuf.appendByte('F');
-            break;
-        case DOUBLE:
-            sigbuf.appendByte('D');
-            break;
-        case BOOLEAN:
-            sigbuf.appendByte('Z');
-            break;
-        case VOID:
-            sigbuf.appendByte('V');
-            break;
-        case CLASS:
-            sigbuf.appendByte('L');
-            assembleClassSig(type);
-            sigbuf.appendByte(';');
-            break;
-        case ARRAY:
-            ArrayType at = (ArrayType)type;
-            sigbuf.appendByte('[');
-            assembleSig(at.elemtype);
-            break;
-        case METHOD:
-            MethodType mt = (MethodType)type;
-            sigbuf.appendByte('(');
-            assembleSig(mt.argtypes);
-            sigbuf.appendByte(')');
-            assembleSig(mt.restype);
-            if (hasTypeVar(mt.thrown)) {
-                for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) {
-                    sigbuf.appendByte('^');
-                    assembleSig(l.head);
-                }
+    private class CWSignatureGenerator extends Types.SignatureGenerator {
+
+        /**
+         * An output buffer for type signatures.
+         */
+        ByteBuffer sigbuf = new ByteBuffer();
+
+        CWSignatureGenerator(Types types) {
+            super(types);
+        }
+
+        /**
+         * Assemble signature of given type in string buffer.
+         * Check for uninitialized types before calling the general case.
+         */
+        @Override
+        public void assembleSig(Type type) {
+            type = type.unannotatedType();
+            switch (type.getTag()) {
+                case UNINITIALIZED_THIS:
+                case UNINITIALIZED_OBJECT:
+                    // we don't yet have a spec for uninitialized types in the
+                    // local variable table
+                    assembleSig(types.erasure(((UninitializedType)type).qtype));
+                    break;
+                default:
+                    super.assembleSig(type);
             }
-            break;
-        case WILDCARD: {
-            WildcardType ta = (WildcardType) type;
-            switch (ta.kind) {
-            case SUPER:
-                sigbuf.appendByte('-');
-                assembleSig(ta.type);
-                break;
-            case EXTENDS:
-                sigbuf.appendByte('+');
-                assembleSig(ta.type);
-                break;
-            case UNBOUND:
-                sigbuf.appendByte('*');
-                break;
-            default:
-                throw new AssertionError(ta.kind);
-            }
-            break;
+        }
+
+        @Override
+        protected void append(char ch) {
+            sigbuf.appendByte(ch);
+        }
+
+        @Override
+        protected void append(byte[] ba) {
+            sigbuf.appendBytes(ba);
+        }
+
+        @Override
+        protected void append(Name name) {
+            sigbuf.appendName(name);
         }
-        case TYPEVAR:
-            sigbuf.appendByte('T');
-            sigbuf.appendName(type.tsym.name);
-            sigbuf.appendByte(';');
-            break;
-        case FORALL:
-            ForAll ft = (ForAll)type;
-            assembleParamsSig(ft.tvars);
-            assembleSig(ft.qtype);
-            break;
-        case UNINITIALIZED_THIS:
-        case UNINITIALIZED_OBJECT:
-            // we don't yet have a spec for uninitialized types in the
-            // local variable table
-            assembleSig(types.erasure(((UninitializedType)type).qtype));
-            break;
-        default:
-            throw new AssertionError("typeSig " + type.getTag());
+
+        @Override
+        protected void classReference(ClassSymbol c) {
+            enterInner(c);
+        }
+
+        private void reset() {
+            sigbuf.reset();
+        }
+
+        private Name toName() {
+            return sigbuf.toName(names);
+        }
+
+        private boolean isEmpty() {
+            return sigbuf.length == 0;
         }
     }
 
-    boolean hasTypeVar(List<Type> l) {
-        while (l.nonEmpty()) {
-            if (l.head.hasTag(TYPEVAR)) return true;
-            l = l.tail;
-        }
-        return false;
-    }
-
-    void assembleClassSig(Type type) {
-        type = type.unannotatedType();
-        ClassType ct = (ClassType)type;
-        ClassSymbol c = (ClassSymbol)ct.tsym;
-        enterInner(c);
-        Type outer = ct.getEnclosingType();
-        if (outer.allparams().nonEmpty()) {
-            boolean rawOuter =
-                c.owner.kind == MTH || // either a local class
-                c.name == names.empty; // or anonymous
-            assembleClassSig(rawOuter
-                             ? types.erasure(outer)
-                             : outer);
-            sigbuf.appendByte('.');
-            Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname));
-            sigbuf.appendName(rawOuter
-                              ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength()+1,c.flatname.getByteLength())
-                              : c.name);
-        } else {
-            sigbuf.appendBytes(externalize(c.flatname));
-        }
-        if (ct.getTypeArguments().nonEmpty()) {
-            sigbuf.appendByte('<');
-            assembleSig(ct.getTypeArguments());
-            sigbuf.appendByte('>');
-        }
-    }
-
-
-    void assembleSig(List<Type> types) {
-        for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail)
-            assembleSig(ts.head);
-    }
-
-    void assembleParamsSig(List<Type> typarams) {
-        sigbuf.appendByte('<');
-        for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) {
-            TypeVar tvar = (TypeVar)ts.head;
-            sigbuf.appendName(tvar.tsym.name);
-            List<Type> bounds = types.getBounds(tvar);
-            if ((bounds.head.tsym.flags() & INTERFACE) != 0) {
-                sigbuf.appendByte(':');
-            }
-            for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) {
-                sigbuf.appendByte(':');
-                assembleSig(l.head);
-            }
-        }
-        sigbuf.appendByte('>');
-    }
-
-    /** Return signature of given type
+    /**
+     * Return signature of given type
      */
     Name typeSig(Type type) {
-        Assert.check(sigbuf.length == 0);
+        Assert.check(signatureGen.isEmpty());
         //- System.out.println(" ? " + type);
-        assembleSig(type);
-        Name n = sigbuf.toName(names);
-        sigbuf.reset();
+        signatureGen.assembleSig(type);
+        Name n = signatureGen.toName();
+        signatureGen.reset();
         //- System.out.println("   " + n);
         return n;
     }
@@ -711,7 +623,7 @@
             (flags & (SYNTHETIC|BRIDGE)) != SYNTHETIC &&
             (flags & ANONCONSTR) == 0 &&
             (!types.isSameType(sym.type, sym.erasure(types)) ||
-             hasTypeVar(sym.type.getThrownTypes()))) {
+            signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
             // note that a local class with captured variables
             // will get a signature attribute
             int alenIdx = writeAttr(names.Signature);
@@ -1730,7 +1642,7 @@
         Assert.check((c.flags() & COMPOUND) == 0);
         databuf.reset();
         poolbuf.reset();
-        sigbuf.reset();
+        signatureGen.reset();
         pool = c.pool;
         innerClasses = null;
         innerClassesQueue = null;
@@ -1791,12 +1703,12 @@
         if (sigReq) {
             Assert.check(source.allowGenerics());
             int alenIdx = writeAttr(names.Signature);
-            if (typarams.length() != 0) assembleParamsSig(typarams);
-            assembleSig(supertype);
+            if (typarams.length() != 0) signatureGen.assembleParamsSig(typarams);
+            signatureGen.assembleSig(supertype);
             for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
-                assembleSig(l.head);
-            databuf.appendChar(pool.put(sigbuf.toName(names)));
-            sigbuf.reset();
+                signatureGen.assembleSig(l.head);
+            databuf.appendChar(pool.put(signatureGen.toName()));
+            signatureGen.reset();
             endAttr(alenIdx);
             acount++;
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Names.java	Fri Feb 15 11:26:11 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Names.java	Fri Feb 15 18:40:38 2013 -0800
@@ -73,6 +73,7 @@
     public final Name clone;
     public final Name close;
     public final Name compareTo;
+    public final Name deserializeLambda;
     public final Name desiredAssertionStatus;
     public final Name equals;
     public final Name error;
@@ -174,6 +175,7 @@
     //lambda-related
     public final Name lambda;
     public final Name metaFactory;
+    public final Name altMetaFactory;
 
     public final Name.Table table;
 
@@ -207,6 +209,7 @@
         clone = fromString("clone");
         close = fromString("close");
         compareTo = fromString("compareTo");
+        deserializeLambda = fromString("$deserializeLambda$");
         desiredAssertionStatus = fromString("desiredAssertionStatus");
         equals = fromString("equals");
         error = fromString("<error>");
@@ -306,8 +309,9 @@
         package_info = fromString("package-info");
 
         //lambda-related
-        lambda = fromString("lambda");
+        lambda = fromString("lambda$");
         metaFactory = fromString("metaFactory");
+        altMetaFactory = fromString("altMetaFactory");
     }
 
     protected Name.Table createTable(Options options) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/LambdaInnerTypeVarArgs.java	Fri Feb 15 18:40:38 2013 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8005653
+ * @summary A lambda containing an inner class referencing an external type var in class parameter type
+ * @author  Robert Field
+ * @run main LambdaInnerTypeVarArgs
+ */
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.ArrayList;
+
+public class LambdaInnerTypeVarArgs {
+
+    static int assertionCount = 0;
+
+    static void assertTrue(boolean cond) {
+        assertionCount++;
+        if (!cond)
+            throw new AssertionError();
+    }
+
+    interface I {
+        C doit();
+    }
+
+    abstract class C {
+        abstract Object it();
+    }
+
+    class TV {
+        C go() {
+            List<String> ls = new ArrayList<>();
+            ls.add("Oh");
+            ls.add("my");
+            return foo(ls).doit();
+        }
+
+        <RRRRR> I foo(List<RRRRR> r) {
+            return () -> new C() {
+                List<RRRRR> xxxxx = r;
+                @Override
+                    Object it() { return xxxxx; };
+            };
+        }
+    }
+
+    void test1() {
+        assertTrue(((List<String>)(new TV().go().it())).get(0).equals("Oh"));
+    }
+
+    public static void main(String[] args) {
+        LambdaInnerTypeVarArgs t = new LambdaInnerTypeVarArgs();
+        t.test1();
+        assertTrue(assertionCount == 1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/LambdaInnerTypeVarReflect.java	Fri Feb 15 18:40:38 2013 -0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8005653
+ * @summary A lambda containing an inner class referencing an external type var
+ * @author  Robert Field
+ * @run main LambdaInnerTypeVarReflect
+ */
+
+import java.io.StringWriter;
+import java.io.PrintWriter;
+import java.io.IOException;
+
+public class LambdaInnerTypeVarReflect {
+
+    static int assertionCount = 0;
+
+    static void assertTrue(boolean cond) {
+        assertionCount++;
+        if (!cond)
+            throw new AssertionError();
+    }
+
+    interface I {
+        C doit();
+    }
+
+    abstract class C {
+        abstract Object it();
+    }
+
+    class TV {
+        C go() {
+            return foo("Frump").doit();
+        }
+
+        <RRRRR> I foo(RRRRR r) {
+            return () -> new C() {
+                public RRRRR xxxxx = r;
+                @Override
+                    Object it() { return xxxxx; };
+            };
+        }
+    }
+
+    void test1() throws IOException {
+        char[] buffer = new char[1024];
+        String innerName = new TV().go().getClass().getName();
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        int exitCode = com.sun.tools.javap.Main.run(new String[] {innerName}, pw);
+        assertTrue(exitCode == 0);
+
+        String javapOut = sw.toString();
+        assertTrue(javapOut.contains(innerName));
+        assertTrue(!javapOut.contains("RRRRR"));
+    }
+
+    public static void main(String[] args) throws IOException {
+        LambdaInnerTypeVarReflect t = new LambdaInnerTypeVarReflect();
+        t.test1();
+        assertTrue(assertionCount == 3);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference61.java	Fri Feb 15 18:40:38 2013 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8006763
+ * @summary super in method reference used in anonymous class
+ */
+public class MethodReference61 {
+    interface SAM {
+        void m();
+    }
+
+    static class MyTester {
+        public void ifoo() { }
+    }
+
+    public static void main(String args[]) {
+        MyTester t = new MyTester() {
+            SAM s = super::ifoo;
+        };
+    }
+}