changeset 1148:afd33b3093d3

Updated compiler implementation as per latest spec draft (v0.4.1) *) Lambda parameters are not allowed to shadow locals in the enclosing scope anymore. Cleanup/improvements *) Simplified logic for lambda attribution environment creation in Attr.java *) Removed redundant flags in Flags.java *) Simplified lambda AST node *) Convert LambdaToInnerTranslator to a 'true' lambda/reference to inner class translator - i.e. so that it does not use ProxyHelper for method reference translation *) Removed '-XDuseIndy'/'-XDuseProxy' options - now indy is the default choice when -XDlambdaToMethod is selected *) Move code shared by both translators in the base class LambdaTranslator - now both translator share the same two-phase translation strategy (one step for analyzing lambdas/mrefs, one step for actual translation) *) Cleanup Gen.java (all method references are now completely desugared when we get to code generation - no need to support bytecode translation for method references)
author mcimadamore
date Wed, 26 Oct 2011 16:41:55 +0100
parents f2e7fad12285
children 3721384cb546
files src/share/classes/com/sun/runtime/ProxyHelper.java src/share/classes/com/sun/tools/javac/code/Flags.java src/share/classes/com/sun/tools/javac/code/Types.java src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/AttrContext.java src/share/classes/com/sun/tools/javac/comp/Flow.java src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/com/sun/tools/javac/comp/TransTypes.java src/share/classes/com/sun/tools/javac/jvm/Gen.java src/share/classes/com/sun/tools/javac/tree/JCTree.java test/tools/javac/lambda/BadBreakContinue.out test/tools/javac/lambda/BadStatementInLambda02.out test/tools/javac/lambda/LambdaCapture01.java test/tools/javac/lambda/LambdaCapture02.java test/tools/javac/lambda/LambdaCapture03.java test/tools/javac/lambda/LambdaConv01.java test/tools/javac/lambda/LambdaScope01.java test/tools/javac/lambda/LambdaScope04.java test/tools/javac/lambda/LambdaScope04.out test/tools/javac/lambda/MethodReference30.java test/tools/javac/lambda/sqe/lambdaExpression/LambdaTest4.java test/tools/javac/lambda/sqe/methodReference/BridgeMethod.java
diffstat 25 files changed, 1691 insertions(+), 1331 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/runtime/ProxyHelper.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/runtime/ProxyHelper.java	Wed Oct 26 16:41:55 2011 +0100
@@ -45,10 +45,6 @@
  *  deletion without notice.</b>
  */
 public class ProxyHelper {
-    
-    public static <T> T makeProxy(final Class<T> sam, final MethodHandle mh) {
-        return makeProxy(sam, mh, false, (Object[])null);
-    }
 
     @SuppressWarnings("unchecked")
     public static <T> T makeProxy(final Class<T> sam, MethodHandle mh, boolean recursive, Object... captured) {
--- a/src/share/classes/com/sun/tools/javac/code/Flags.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Flags.java	Wed Oct 26 16:41:55 2011 +0100
@@ -238,41 +238,31 @@
     public static final long THROWS = 1L<<39;
 
     /**
-     * Flag that marks a method symbol representing a lambda expression
-     */
-    public static final long LAMBDA = 1L<<40;
-
-    /**
-     * Flag that marks a lambda expression symbol that requires access to enclosing class
-     */
-    public static final long OUTER_ACCESS = 1L<<41;
-
-    /**
      * Flag that marks a defender method/interface
      */
-    public static final long DEFENDER = 1L<<42;
+    public static final long DEFENDER = 1L<<40;
 
     /**
      * Flag that marks a signature-polymorphic invoke method.
      * (These occur inside java.lang.invoke.MethodHandle.)
      */
-    public static final long POLYMORPHIC_SIGNATURE = 1L<<43;
+    public static final long POLYMORPHIC_SIGNATURE = 1L<<41;
     
     /**
      * Flag that marks an 'effectively final' local variable
      */
-    public static final long EFFECTIVELY_FINAL = 1L<<44;
+    public static final long EFFECTIVELY_FINAL = 1L<<42;
 
     /**
      * Flag that marks a special kind of bridge methods (the ones that
      * come from restricted supertype bounds)
      */
-    public static final long OVERRIDE_BRIDGE = 1L<<45;
+    public static final long OVERRIDE_BRIDGE = 1L<<43;
 
     /**
      * Flag that marks non-override equivalent methods with the same signature
      */
-    public static final long CLASH = 1L<<46;
+    public static final long CLASH = 1L<<44;
 
     /** Modifier masks.
      */
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Wed Oct 26 16:41:55 2011 +0100
@@ -36,10 +36,7 @@
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Scope.CompoundScope;
 import com.sun.tools.javac.comp.Check;
-import com.sun.tools.javac.comp.Env;
-import com.sun.tools.javac.comp.Resolve;
 import com.sun.tools.javac.comp.Infer;
-import com.sun.tools.javac.comp.AttrContext;
 
 import static com.sun.tools.javac.code.Type.*;
 import static com.sun.tools.javac.code.TypeTags.*;
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Oct 26 16:41:55 2011 +0100
@@ -39,7 +39,6 @@
 
 import com.sun.tools.javac.jvm.Target;
 import com.sun.tools.javac.code.Lint.LintCategory;
-import com.sun.tools.javac.code.Attribute.Compound;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.code.Type.ForAll.*;
@@ -1369,6 +1368,7 @@
             boolean seenLambda = false;
             LOOP:
             while (env1 != null) {
+                seenLambda |= env1.info.lambdaAttr;
                 switch (env1.tree.getTag()) {
                 case JCTree.LABELLED:
                     JCLabeledStatement labelled = (JCLabeledStatement)env1.tree;
@@ -1382,8 +1382,14 @@
                                 log.error(pos, "not.loop.label", label);
                             // Found labelled statement target, now go inwards
                             // to next non-labelled tree.
+                            if (seenLambda) {
+                                log.error(pos, "cont.inside.lambda");
+                            }
                             return TreeInfo.referencedStatement(labelled);
                         } else {
+                            if (seenLambda) {
+                                log.error(pos, "break.inside.lambda");
+                            }
                             return labelled;
                         }
                     }
@@ -1399,7 +1405,6 @@
                     break;
                 case JCTree.METHODDEF:
                 case JCTree.CLASSDEF:
-                    seenLambda = (env1.enclClass.sym.flags() & LAMBDA) != 0;
                     break LOOP;
                 default:
                 }
@@ -1421,15 +1426,15 @@
     public void visitReturn(JCReturn tree) {
         // Check that there is an enclosing method which is
         // nested within than the enclosing class.
-        if (env.enclMethod == null ||
-            env.enclMethod.sym.owner != env.enclClass.sym) {
+        if ((env.enclMethod == null ||
+            env.enclMethod.sym.owner != env.enclClass.sym) &&
+            !env.info.lambdaAttr) {
             log.error(tree.pos(), "ret.outside.meth");
         } else {
-            Type typeToCheck = env.enclMethod.sym.type.getReturnType();
             //lambda expression does not have expected return type (at this stage)
-            if ((env.enclMethod.sym.flags() & LAMBDA) != 0) {
-                typeToCheck = Infer.lambdaPoly;
-            }
+            Type typeToCheck = env.info.lambdaAttr ?
+                    Infer.lambdaPoly :
+                    env.enclMethod.sym.type.getReturnType();
             // Attribute return expression, if it exists, and check that
             // it conforms to result type of enclosing method.
             if (typeToCheck.tag == VOID) {
@@ -1601,9 +1606,6 @@
                 Type qualifier = (tree.meth.getTag() == JCTree.SELECT)
                     ? ((JCFieldAccess) tree.meth).selected.type
                     : env.enclClass.sym.type;
-                while ((qualifier.tsym.flags() & LAMBDA) != 0) {
-                    qualifier = qualifier.getEnclosingType();
-                }
                 restype = new
                     ClassType(restype.getEnclosingType(),
                               List.<Type>of(new WildcardType(types.erasure(qualifier),
@@ -2039,93 +2041,6 @@
         result = check(tree, owntype, VAL, pkind, pt);
     }
 
-    /**
-     * An environment in which to evaluate a lambda.
-     * This environment is a method environment nested into a class environment.
-     * The compiler generates synthetic symbols for both envs. 'Fake' AST must
-     * also be generated as they are required during lowering (in order to find
-     * free-variables used within a lambda expression).
-     */
-    Env<AttrContext> lambdaEnvironment(Env<AttrContext> env, JCLambda tree, final Type targetType) {
-
-        //create synthetic outer class symbol hoisting the lambda
-        ClassSymbol lambdaClassSym = makeLambdaClass(env.info.scope.owner,
-                LAMBDA | SYNTHETIC);
-
-        JCClassDecl classdef = make.ClassDef(make.Modifiers(lambdaClassSym.flags()),
-                names.empty,
-                List.<JCTypeParameter>nil(),
-                null, null, null);
-
-        classdef.sym = lambdaClassSym;
-        classdef.type = lambdaClassSym.type;
-
-        Env<AttrContext> outerEnv = enter.classEnv(classdef, env);
-        outerEnv.info.lint = env.info.lint.augment(List.<Compound>nil());
-
-        lambdaEnvs.put(tree, outerEnv);
-        enter.typeEnvs.put(lambdaClassSym, outerEnv);
-
-        //create synthetic lambda symbol
-        MethodSymbol lambdaSym = makeLambdaSymbol(targetType, lambdaClassSym);
-
-        JCBlock body = tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION ?
-            make.Block(0, List.<JCStatement>of(make.Return((JCExpression)tree.body))) :
-            (JCBlock)tree.body;
-        JCMethodDecl lambda = make.MethodDef(make.Modifiers(lambdaSym.flags()),
-                lambdaSym.name,
-                null, // missing restype
-                List.<JCTypeParameter>nil(),
-                List.<JCVariableDecl>nil(),
-                List.<JCExpression>nil(),
-                body,
-                null); // missing defaultValue
-
-        lambda.type = lambdaSym.type;
-        tree.sym = lambda.sym = lambdaSym;
-        outerEnv.enclClass.defs = List.<JCTree>of(lambda);
-        Env<AttrContext> newEnv = memberEnter.methodEnv(lambda, outerEnv);
-        newEnv.info.scope.owner = lambda.sym;
-        
-        return newEnv;
-    }
-    //where
-    private ClassSymbol makeLambdaClass(Symbol owner, long flags) {
-
-        ClassSymbol lambdaClassSym =
-                    new ClassSymbol(flags, names.empty, null, owner);
-        lambdaClassSym.sourcefile = env.enclClass.sym.sourcefile;
-
-        lambdaClassSym.type = new ClassType(Type.noType,
-                List.<Type>nil(),
-                lambdaClassSym);
-
-        enter.setEnclosingType(lambdaClassSym, lambdaClassSym.owner);
-
-        lambdaClassSym.flatname = chk.localClassName(lambdaClassSym);
-        chk.compiled.put(lambdaClassSym.flatname, lambdaClassSym);
-
-        if (lambdaClassSym.type.getEnclosingType().tag != NONE) {
-            lambdaClassSym.flags_field |= OUTER_ACCESS;            
-        }
-        lambdaClassSym.members_field = new Scope(lambdaClassSym);
-
-        return lambdaClassSym;
-    }
-    //where
-    private MethodSymbol makeLambdaSymbol(Type targetType, Symbol owner) {
-        MethodSymbol samDescriptor = types.findDescriptor(targetType.tsym);
-        Name lambdaName = samDescriptor.name;
-        long lambdaFlags = (samDescriptor.flags() | LAMBDA) & ~ABSTRACT ;
-        Type lambdaType = types.memberType(targetType, samDescriptor);
-
-        return new MethodSymbol(
-                lambdaFlags,
-                lambdaName,
-                lambdaType,
-                owner);
-    }
-
     /*
      * Some lambda expressions are attributed using a two-phase process. First,
      * thrown types/return type of a lambda expression is inferred from the lambda
@@ -2185,6 +2100,21 @@
                 pt == Infer.lambdaPoly);
     }
     
+    Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) {
+        Env<AttrContext> lambdaEnv;
+        Symbol owner = env.info.scope.owner;
+        if (owner.kind == VAR && !owner.isLocal()) {
+            lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared()));
+            lambdaEnv.info.scope.owner =
+                new MethodSymbol(0, names.lambda, null,
+                                 env.info.scope.owner);
+        } else {
+            lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
+        }
+        lambdaEnv.info.lambdaAttr = true;
+        return lambdaEnv;
+    }
+    
     /*
      * Attribute a lambda expression - return type/thrown types of the lambda
      * expression are inferred from the lambda body.
@@ -2193,67 +2123,73 @@
             final boolean allowBoxing, final boolean check, SAMDeferredAttribution<JCLambda> deferredAttr) {
         
         //create an environment for attribution of the lambda expression
-        final Env<AttrContext> localEnv = lambdaEnvironment(env, that, target);
-
-        if (that.needsParameterInference()) {
-            //add param type info in the AST
-            List<Type> actuals = types.findDescriptor(target).getParameterTypes();
-            List<JCVariableDecl> params = that.params;
-            while (params.nonEmpty()) {
-                if (actuals.isEmpty()) {
-                    //not enough actuals to perform lambda parameter inference
-                    throw new Infer.InvalidInstanceException(diags).setMessage("infer.incompatible.arg.types.in.lambda");
+        final Env<AttrContext> localEnv = lambdaEnv(that, env);
+        localEnv.info.lambdaAttr = true;
+        try {
+            final Type lambdaType = types.findDescriptor(target);
+
+            if (that.needsParameterInference()) {
+                //add param type info in the AST
+                List<Type> actuals = types.findDescriptor(target).getParameterTypes();
+                List<JCVariableDecl> params = that.params;
+                while (params.nonEmpty()) {
+                    if (actuals.isEmpty()) {
+                        //not enough actuals to perform lambda parameter inference
+                        throw new Infer.InvalidInstanceException(diags).setMessage("infer.incompatible.arg.types.in.lambda");
+                    }
+                    if (params.head.vartype == null) {
+                        params.head.vartype = make.Type(actuals.head);
+                    }
+                    actuals = actuals.tail;
+                    params = params.tail;
                 }
-                if (params.head.vartype == null) {
-                    params.head.vartype = make.Type(actuals.head);
+            }
+
+            //attribute lambda parameters
+            attribStats(that.params, localEnv);
+
+            int prevErrors = deferredAttr.errorCount(check);
+
+            ForAll.Completer prevPolyCompleter = chk.setPolyCompleter(new ForAll.Completer() {
+                public Type complete(DiagnosticPosition pos, Env<AttrContext> env, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException {
+                    Type expectedType = lambdaType.getReturnType();
+                    return pt == Infer.lambdaPoly ?
+                        infer.instantiatePoly(env, inferenceContext, t, expectedType, warn, allowBoxing, check) :
+                        chk.instantiatePoly(pos, env, t, pt, warn);
                 }
-                actuals = actuals.tail;
-                params = params.tail;
+            });
+
+            try {
+                if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
+                    attribExpr(that.getBody(), localEnv, Infer.lambdaPoly);
+                }
+                else {
+                    JCBlock body = (JCBlock)that.body;
+                    attribStats(body.stats, localEnv);
+                }
             }
+            finally {
+                chk.setPolyCompleter(prevPolyCompleter);
+            }
+
+            List<Type> returnTypes =
+                    new LambdaReturnExprVisitor().getLambdaReturnTypes(that);
+
+            List<Type> thrownTypes = List.nil();
+
+            if (prevErrors == deferredAttr.errorCount(check)) {
+                //infer thrown types from lambda body
+                flow.analyzeLambda(that, env, make);
+                thrownTypes = that.inferredThrownTypes;
+            }
+
+            checkSAMCompatible(inferenceContext, target, returnTypes,
+                    TreeInfo.types(that.params), thrownTypes, allowBoxing, that.canCompleteNormally);
+            
+            return that.targetType = target;
+        } finally {
+            localEnv.info.scope.leave();
         }
-
-        //attribute lambda parameters
-        attribStats(that.params, localEnv);
-
-        int prevErrors = deferredAttr.errorCount(check);
-        
-        ForAll.Completer prevPolyCompleter = chk.setPolyCompleter(new ForAll.Completer() {
-            public Type complete(DiagnosticPosition pos, Env<AttrContext> env, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException {
-                Type expectedType = localEnv.enclMethod.type.getReturnType();
-                return pt == Infer.lambdaPoly ?
-                    infer.instantiatePoly(env, inferenceContext, t, expectedType, warn, allowBoxing, check) :
-                    chk.instantiatePoly(pos, env, t, pt, warn);
-            }
-        });
-
-        try {
-            if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
-                attribExpr(that.getBody(), localEnv, Infer.lambdaPoly);
-            }
-            else {
-                JCBlock body = (JCBlock)that.body;
-                attribStats(body.stats, localEnv);
-            }
-        }
-        finally {
-            chk.setPolyCompleter(prevPolyCompleter);
-        }
-
-        List<Type> returnTypes =
-                new LambdaReturnExprVisitor().getLambdaReturnTypes(that);
-
-        List<Type> thrownTypes = List.nil();
-
-        if (prevErrors == deferredAttr.errorCount(check)) {
-            //infer thrown types from lambda body
-            flow.analyzeLambda(that, env, make);
-            thrownTypes = that.inferredThrownTypes;
-        }
-
-        checkSAMCompatible(inferenceContext, target, returnTypes,
-                TreeInfo.types(that.params), thrownTypes, allowBoxing, that.canCompleteNormally);
-        
-        return that.targetType = target;
     }
 
     class LambdaReturnExprVisitor extends TreeScanner {
@@ -2524,7 +2460,7 @@
             if (v.owner.kind == MTH &&
                     v.owner != env.info.scope.owner &&
                     (v.flags_field & FINAL) == 0 &&
-                    (env.enclClass.sym.flags() & LAMBDA) == 0) {
+                    !env.info.lambdaAttr) {
                 log.error(tree.pos(),
                         "local.var.accessed.from.inner.ctx.needs.final",
                         v, diags.fragment("icls"));
@@ -4071,9 +4007,6 @@
         @Override
         public void visitLambda(JCLambda that) {
             super.visitLambda(that);
-            if (that.sym == null) {
-                that.sym = new MethodSymbol(0, names.lambda, syms.unknownType, syms.noSymbol);
-            }
             if (that.targetType == null) {
                 that.targetType = syms.unknownType;
             }
--- a/src/share/classes/com/sun/tools/javac/comp/AttrContext.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/AttrContext.java	Wed Oct 26 16:41:55 2011 +0100
@@ -57,6 +57,10 @@
     /** Are arguments to current function applications boxed into an array for varargs?
      */
     boolean varArgs = false;
+    
+    /** Are we attributing the body of a lambda expression?
+     */
+    boolean lambdaAttr = false;
 
     /** A list of type variables that are all-quantifed in current context.
      */
@@ -88,6 +92,7 @@
         info.lint = lint;
         info.enclVar = enclVar;
         info.allowsDisjointTypes = allowsDisjointTypes;
+        info.lambdaAttr = lambdaAttr;
         return info;
     }
 
--- a/src/share/classes/com/sun/tools/javac/comp/Flow.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Oct 26 16:41:55 2011 +0100
@@ -194,7 +194,7 @@
     private final boolean allowImprovedRethrowAnalysis;
     private final boolean allowImprovedCatchAnalysis;
     boolean daEnabled = true;
-    Symbol currentLambda = null;
+    JCLambda currentLambda = null;
 
     public static Flow instance(Context context) {
         Flow instance = context.get(flowKey);
@@ -452,7 +452,7 @@
     void checkEffectivelyFinal(DiagnosticPosition pos, VarSymbol sym) {
         if (currentLambda != null &&
                 sym.owner.kind == MTH &&
-                sym.owner != currentLambda &&
+                sym.pos < currentLambda.getStartPosition() &&
                 (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) == 0) {
             log.error(pos, "cant.ref.non.effectively.final.var",
                     sym);
@@ -624,7 +624,7 @@
         int nextadrPrev = nextadr;
         ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
         Lint lintPrev = lint;
-        Symbol prevLambda = currentLambda;
+        JCLambda prevLambda = currentLambda;
 
         pendingExits = new ListBuffer<PendingExit>();
         if (tree.name != names.empty) {
@@ -1401,9 +1401,9 @@
         Bits prevInits = inits;
         ListBuffer<PendingExit> prevPending = pendingExits;
         boolean prevAlive = alive;
-        Symbol prevLambda = currentLambda;
+        JCLambda prevLambda = currentLambda;
         try {
-            currentLambda = tree.sym;
+            currentLambda = tree;
             caught = List.of(syms.throwableType); //inhibit exception checking
             thrown = List.nil();            
             inits = inits.orSet(uninits);
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Wed Oct 26 16:41:55 2011 +0100
@@ -25,16 +25,24 @@
 
 package com.sun.tools.javac.comp;
 
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.comp.LambdaTranslator.LambdaAnalyzer;
+import com.sun.tools.javac.comp.LambdaToInnerClass.LambdaToInnerAnalyzer.*;
 import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
 
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.code.Type.*;
 
+import java.util.Map;
+
+import static com.sun.tools.javac.code.Flags.*;
+import static com.sun.tools.javac.comp.LambdaTranslator.LambdaSymbolKind.*;
+
 /** This pass desugars lambda expressions into anonymous inner classes
  *
  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
@@ -43,6 +51,11 @@
  *  deletion without notice.</b>
  */
 public class LambdaToInnerClass extends LambdaTranslator {
+    
+    private Check chk;
+    private Enter enter;
+    
+    // <editor-fold defaultstate="collapsed" desc="Instantiating">
     protected static final Context.Key<LambdaToInnerClass> unlambdaKey =
         new Context.Key<LambdaToInnerClass>();
 
@@ -52,192 +65,398 @@
             instance = new LambdaToInnerClass(context);
         return instance;
     }
-    
-    private Enter enter;
-    private MemberEnter memberEnter;
 
-    private JCClassDecl currentClass;
-    
     protected LambdaToInnerClass(Context context) {
-        super(context);
+        super(context, null);
+        analyzer = new LambdaToInnerAnalyzer();
+        chk = Check.instance(context);
         enter = Enter.instance(context);
-        memberEnter = MemberEnter.instance(context);
     }
 
     @Override
-    public void visitClassDef(JCClassDecl tree) {
-        JCClassDecl prevClass = currentClass;
-        try {
-            currentClass = tree;
-            super.visitClassDef(tree);
+    protected LambdaAnalyzer makeAnalyzer() {
+        return new LambdaToInnerAnalyzer();
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="visitor methods">
+    @Override
+    public void visitLambda(JCLambda tree) {
+        LambdaToInnerTranslationContext localContext = (LambdaToInnerTranslationContext)context;
+            
+        //create new anon class definition implementing SAM method
+        //   class <anon> extends SAMClass { ... }
+
+        JCClassDecl samClassDecl = make.ClassDef(
+                make.Modifiers(localContext.lambdaClassSym.flags_field),
+                names.empty,
+                List.<JCTypeParameter>nil(),
+                tree.targetType.isInterface() ? make.QualIdent(syms.objectType.tsym).setType(syms.objectType) : make.QualIdent(tree.targetType.tsym).setType(tree.targetType),
+                tree.targetType.isInterface() ? List.of(make.QualIdent(tree.targetType.tsym).setType(tree.targetType)) : List.<JCExpression>nil(),
+                null);
+
+        samClassDecl.sym = localContext.lambdaClassSym;
+        samClassDecl.type = localContext.lambdaClassSym.type;
+
+        ListBuffer<JCVariableDecl> capturedFields = ListBuffer.lb();
+
+        //add encl$n and cap$n if needed
+        for (Map.Entry<Symbol, Symbol> e : localContext.getSymbolMap(CAPTURED_THIS, CAPTURED_VAR).entrySet()) {
+            if (e.getKey() == localContext.self) continue;
+            capturedFields.append(make.VarDef((VarSymbol)e.getValue(), null));
+            samClassDecl.sym.members().enter(e.getValue());
         }
-        finally {
-            currentClass = prevClass;
+
+        //create constructor
+        JCMethodDecl samConstrDecl = makeConstructor(tree.pos(),
+                localContext.lambdaClassSym,
+                tree.targetType,
+                capturedFields.toList());
+
+        //create SAM method
+        //   R m(A1, A2 ... An) throws T1, T2 ... Tn {
+        //      [return] <body>
+        //   }
+
+        JCMethodDecl samMethodDecl = make.MethodDef((MethodSymbol)localContext.translatedSym, null);
+        ListBuffer<JCVariableDecl> params = ListBuffer.lb();
+        for (Symbol param : localContext.getSymbolMap(PARAM).values()) {
+            params.append(make.at(tree.pos).VarDef((VarSymbol)param, null));
         }
+        samMethodDecl.params = params.toList();
+
+        samMethodDecl.body = translate(makeLambdaBody(tree, localContext.translatedSym.type.getReturnType()));
+        samClassDecl.defs = List.<JCTree>of(samConstrDecl, samMethodDecl).prependList(List.convert(JCTree.class, capturedFields.toList()));
+        localContext.lambdaClassSym.members().enter(samConstrDecl.sym);
+        localContext.lambdaClassSym.members().enter(samMethodDecl.sym);
+
+        Env<AttrContext> outerEnv = enter.typeEnvs.get(localContext.lambdaClassSym.owner.enclClass());
+        enter.typeEnvs.put(localContext.lambdaClassSym, enter.classEnv(samClassDecl, outerEnv));
+        
+        ListBuffer<JCExpression> syntheticInits = ListBuffer.lb();
+
+        //append reference to enclosing contexts
+        for (Symbol sym : localContext.getSymbolMap(CAPTURED_THIS).keySet()) {
+            VarSymbol _this = new VarSymbol(Flags.FINAL | Flags.SYNTHETIC,
+                    names._this,
+                    sym.type, localContext.owner);
+            JCTree qualifiedThis = make.Select(make.QualIdent(sym), _this).setType(sym.type);
+            syntheticInits.append((JCExpression)qualifiedThis);
+        }
+
+        //add captured locals
+        for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
+            if (fv == localContext.self) continue;
+            JCTree captured_local = make.Ident(fv).setType(fv.type);
+            syntheticInits.append((JCExpression)captured_local);
+        }
+
+        JCNewClass newClass = make.NewClass(null,
+                List.<JCExpression>nil(),
+                make.QualIdent(tree.targetType.tsym),
+                syntheticInits.toList(),
+                (JCClassDecl)enter.typeEnvs.get(localContext.lambdaClassSym).tree);
+        newClass.constructor = samConstrDecl.sym;
+        newClass.setType(localContext.lambdaClassSym.type);
+        
+        result = translate(newClass, localContext.prev);
     }
 
     @Override
-    public void visitLambda(JCLambda tree) {
+    public void visitReference(JCMemberReference tree) {
+        ReferenceToInnerTranslationContext localContext = (ReferenceToInnerTranslationContext)context;
+        
+        Symbol refSym = localContext.isSpecial() ?
+            bridgeMemberReference(tree, localContext) :
+            tree.sym;
+            
         //create new anon class definition implementing SAM method
         //   class <anon> extends SAMClass { ... }
 
-        ClassSymbol samClassSym = (ClassSymbol)tree.sym.owner;
+        JCClassDecl samClassDecl = make.ClassDef(
+                make.Modifiers(localContext.referenceClassSym.flags_field),
+                names.empty,
+                List.<JCTypeParameter>nil(),
+                tree.targetType.isInterface() ? make.QualIdent(syms.objectType.tsym).setType(syms.objectType) : make.QualIdent(tree.targetType.tsym).setType(tree.targetType),
+                tree.targetType.isInterface() ? List.of(make.QualIdent(tree.targetType.tsym).setType(tree.targetType)) : List.<JCExpression>nil(),
+                null);
 
-        Type superType = tree.targetType;
+        samClassDecl.sym = localContext.referenceClassSym;
+        samClassDecl.type = localContext.referenceClassSym.type;
 
-        if (superType.isInterface()) {
-            ((ClassType)samClassSym.type).supertype_field = syms.objectType;
-            ((ClassType)samClassSym.type).interfaces_field = List.of(superType);
-        }
-        else {
-            ((ClassType)samClassSym.type).supertype_field = superType;
+        ListBuffer<JCVariableDecl> capturedFields = ListBuffer.lb();
+        if (localContext.isInstanceRef() && !localContext.isSpecial()) {
+            Symbol recField = makeSyntheticVar(0, "rec$", tree.getQualifierExpression().type, localContext.referenceClassSym);
+            capturedFields.append(make.at(tree.pos).VarDef((VarSymbol)recField, null));
+            samClassDecl.sym.members().enter(recField);
         }
 
-        JCClassDecl samClassDecl = make.ClassDef(
-                make.Modifiers(samClassSym.flags_field),
-                names.empty,
-                List.<JCTypeParameter>nil(),
-                superType.isInterface() ? make.QualIdent(syms.objectType.tsym).setType(syms.objectType) : make.QualIdent(superType.tsym).setType(superType),
-                superType.isInterface() ? List.of(make.QualIdent(superType.tsym).setType(superType)) : List.<JCExpression>nil(),
-                null);
-
-        samClassDecl.sym = samClassSym;
-        samClassDecl.type = samClassSym.type;
-
-        JCMethodDecl samConstrDecl = makeDefaultConstructor(tree.pos(), samClassSym);
+        //create declaration for the sam class' constructor (the constructor
+        //contains the initializers for the captured fields)
+        JCMethodDecl samConstrDecl = makeConstructor(tree.pos(),
+                localContext.referenceClassSym,
+                tree.targetType,
+                capturedFields.toList());
 
         //create SAM method
         //   R m(A1, A2 ... An) throws T1, T2 ... Tn {
-        //      [return] $mh.invoke(a1, a2, ... an);
+        //      [return] <body>
         //   }
 
-        MethodSymbol samMethSym = (MethodSymbol)tree.sym;
+        JCMethodDecl samMethodDecl = make.MethodDef((MethodSymbol)localContext.translatedSym, null);
+        ListBuffer<JCVariableDecl> params = ListBuffer.lb();
+        for (Type paramType : localContext.translatedSym.type.getParameterTypes()) {
+            Symbol paramSym = makeSyntheticVar(PARAMETER, "x$" + params.length(), paramType, localContext.translatedSym);
+            params.append(make.at(tree.pos).VarDef((VarSymbol)paramSym, null));
+        }
+        samMethodDecl.params = params.toList();
 
+        JCExpression rec = null;
+        if (localContext.isInstanceRef()) {
+            rec = localContext.isSpecial() ?
+                    null :
+                    make.Ident(capturedFields.toList().head.sym);
+        } else if (localContext.isUnbound()) {
+            rec = make.Ident(params.toList().head.sym);
+        } else {
+            rec = tree.mode == ReferenceMode.INVOKE ?
+                    make.Type(refSym.owner.type) : null;
+        }
 
-        JCMethodDecl samMethodDecl = make.MethodDef(samMethSym, null);
-        samMethodDecl.params = tree.params;
+        ListBuffer<JCExpression> args = ListBuffer.lb();
+        for (JCVariableDecl param : params) {
+            if (param == params.first() && localContext.isUnbound()) continue;
+            args.append(make.Ident(param.sym));
+        }
+        JCExpression ref_call = null;
+        if (tree.mode == ReferenceMode.NEW) {
+            ref_call = make.NewClass(rec, null, tree.getQualifierExpression(), args.toList(), null).setType(tree.getQualifierExpression().type);
+            ((JCNewClass)ref_call).constructor = refSym;
+            if ((refSym.flags() & VARARGS) != 0) {
+                ((JCNewClass)ref_call).varargsElement = types.elemtype(refSym.type.getParameterTypes().last());
+            }
+        } else {
+            JCExpression meth = rec == null ?
+                    make.Ident(refSym) :
+                    make.Select(rec, refSym);
+            ref_call = make.Apply(List.<JCExpression>nil(), meth, args.toList(), false).setType(localContext.translatedSym.type.getReturnType());
+            if ((refSym.flags() & VARARGS) != 0) {
+                ((JCMethodInvocation)ref_call).varargsElement = types.elemtype(refSym.type.getParameterTypes().last());
+            }
+        }
+        samMethodDecl.body = make.Block(0, List.of(ref_call.type.tag == TypeTags.VOID ? make.Exec(ref_call) : make.Return(ref_call)));
+        samClassDecl.defs = List.<JCTree>of(samConstrDecl, samMethodDecl).prependList(List.convert(JCTree.class, capturedFields.toList()));
+        localContext.referenceClassSym.members().enter(samConstrDecl.sym);
+        localContext.referenceClassSym.members().enter(samMethodDecl.sym);
 
-        samMethodDecl.body = makeLambdaBody(tree);
-        samClassDecl.defs = List.<JCTree>of(samConstrDecl, samMethodDecl);
-        samClassSym.members().enter(samConstrDecl.sym);
-        samClassSym.members().enter(samMethodDecl.sym);
+        Env<AttrContext> outerEnv = enter.typeEnvs.get(localContext.referenceClassSym.owner.enclClass());
+        enter.typeEnvs.put(localContext.referenceClassSym, enter.classEnv(samClassDecl, outerEnv));
+
+        ListBuffer<JCExpression> syntheticInits = ListBuffer.lb();
+
+        if (localContext.isInstanceRef() && !localContext.isSpecial()) {
+            syntheticInits.append(localContext.tree.getQualifierExpression());
+        }
 
         JCNewClass newClass = make.NewClass(null,
                 List.<JCExpression>nil(),
-                make.QualIdent(superType.tsym),
+                make.QualIdent(tree.targetType.tsym),
+                syntheticInits.toList(),
+                (JCClassDecl)enter.typeEnvs.get(localContext.referenceClassSym).tree);
+        newClass.constructor = samConstrDecl.sym;
+        newClass.setType(localContext.referenceClassSym.type);
+        
+        result = translate(newClass, localContext.prev);
+        
+        //if we had a static reference with non-static qualifier, add a let
+        //expression to force the evaluation of the qualifier expr
+        if (localContext.needsReceiverEval()) {
+            VarSymbol recVar = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner);
+            JCVariableDecl recDef = make.VarDef(recVar, tree.getQualifierExpression());
+            result = make.LetExpr(recDef, result).setType(types.erasure(tree.targetType));
+        }
+    }
+    // </editor-fold>
+    
+    // <editor-fold defaultstate="collapsed" desc="Translation helper methods">
+    private JCMethodDecl makeConstructor(DiagnosticPosition pos, Symbol owner, Type supertype, List<JCVariableDecl> fieldsToAssign) {
+        MethodSymbol lambdaClassConstrSym = new MethodSymbol(0, names.init, null, owner);
+        ListBuffer<JCVariableDecl> constrArgs = ListBuffer.lb();
+        
+        for (JCVariableDecl f : fieldsToAssign) {
+            Symbol argSym =
+                  new VarSymbol(Flags.PARAMETER | Flags.SYNTHETIC,
+                          names.fromString("x$" + constrArgs.size()),
+                          f.type,
+                          lambdaClassConstrSym);
+            constrArgs.append(make.at(pos).VarDef((VarSymbol)argSym, null));
+        }
+
+        //patch constructor type
+        lambdaClassConstrSym.type =
+                new MethodType(TreeInfo.types(constrArgs.toList()),
+                        syms.voidType,
+                        List.<Type>nil(),
+                        syms.methodClass);
+
+        //create declaration for the sam class' constructor (the constructor
+        //contains the initializers for the captured fields)
+        JCMethodDecl samConstrDecl = make.MethodDef(make.Modifiers(0),
+                names.init,
+                null,
+                List.<JCTypeParameter>nil(),
+                constrArgs.toList(),
                 List.<JCExpression>nil(),
-                samClassDecl);
-        newClass.constructor = samConstrDecl.sym;
-        newClass.setType(samClassSym.type);
-        enter.typeEnvs.get(samClassSym).tree = samClassDecl;
-        result = translate(newClass);
+                null,
+                null);
+        samConstrDecl.sym = lambdaClassConstrSym;
+        samConstrDecl.type = lambdaClassConstrSym.type;
+
+        JCIdent _super = (JCIdent)make.Ident(names._super).setType(supertype);
+        _super.sym = syms.objectType.tsym.members().lookup(names.init).sym;
+        JCMethodInvocation sup_call = make.Apply(List.<JCExpression>nil(), _super, List.<JCExpression>nil(), false).setType(syms.voidType);
+        ListBuffer<JCStatement> initializers = ListBuffer.lb();
+        for (int i = 0; i < constrArgs.size() ; i ++) {
+            Symbol from = constrArgs.toList().get(i).sym;
+            Symbol to = fieldsToAssign.get(i).sym;
+            JCExpression assign = make.Assign(make.Ident(to), make.Ident(from)).setType(to.type);
+            initializers.add(make.Exec(assign));
+        }
+        samConstrDecl.body = make.Block(0, List.<JCStatement>of(make.Exec(sup_call)).appendList(initializers.toList()));
+        return samConstrDecl;
     }
 
-    private JCMethodDecl makeDefaultConstructor(final DiagnosticPosition pos, final ClassSymbol owner) {
+    /**
+     * Bridges a member reference - this is needed whenever the qualifier expression
+     * for the method reference is special (either 'this' or 'super'). In such cases
+     * an instance method is added to the client class and the translated reference class
+     * implementation will invoke the bridged instance implementation.
+     */
+    private Symbol bridgeMemberReference(JCMemberReference tree, ReferenceToInnerTranslationContext localContext) {
+        JCMethodDecl bridgeDecl = make.MethodDef((MethodSymbol)localContext.bridgeSym, null);
+        ListBuffer<JCVariableDecl> params = ListBuffer.lb();
+        for (Type paramType : localContext.translatedSym.type.getParameterTypes()) {
+            Symbol paramSym = makeSyntheticVar(PARAMETER, "x$" + params.length(), paramType, localContext.bridgeSym);
+            params.append(make.at(tree.pos).VarDef((VarSymbol)paramSym, null));
+        }
+        bridgeDecl.params = params.toList();
+        
+        ListBuffer<JCExpression> args = ListBuffer.lb();
+        for (JCVariableDecl param : params) {
+            if (param == params.first() && localContext.isUnbound()) continue;
+            args.append(make.Ident(param.sym));
+        }
 
-        final MethodSymbol defaultConstrSym = new MethodSymbol(0, names.init, null, owner);
-        defaultConstrSym.type = new MethodType(List.<Type>nil(), syms.voidType, List.<Type>nil(), syms.methodClass);
+        JCExpression meth = make.Select(tree.getQualifierExpression(), tree.sym);
+        JCExpression ref_call = make.Apply(List.<JCExpression>nil(), meth, args.toList(), false).setType(localContext.translatedSym.type.getReturnType());
+        if ((tree.sym.flags() & VARARGS) != 0) {
+            ((JCMethodInvocation)ref_call).varargsElement = types.elemtype(tree.sym.type.getParameterTypes().last());
+        }
+        
+        bridgeDecl.body = make.Block(0, List.of(ref_call.type.tag == TypeTags.VOID ? make.Exec(ref_call) : make.Return(ref_call)));
+        
+        trans_instance = trans_instance.prepend(bridgeDecl);
+        return bridgeDecl.sym;
+    }
+    
+    private MethodSymbol makeFunctionalDescriptorSym(Type targetType, Symbol owner) {
+        MethodSymbol samDescriptor = types.findDescriptor(targetType.tsym);
+        return makeSyntheticMethod(samDescriptor.flags() & ~Flags.ABSTRACT,
+                samDescriptor.name,
+                types.memberType(targetType, samDescriptor),
+                owner);
+    }
 
-        JCMethodDecl defaultConstr = (JCMethodDecl)memberEnter.DefaultConstructor(
-                make,
-                owner,
+    private ClassSymbol makeFunctionalClassSym(long flags, Type targetType, Symbol owner) {
+        ClassSymbol functionalClassSym = new ClassSymbol(flags | Flags.SYNTHETIC, names.empty, null, owner);
+        functionalClassSym.sourcefile = owner.enclClass().sourcefile;
+
+        functionalClassSym.type = new ClassType(Type.noType,
                 List.<Type>nil(),
-                List.<Type>nil(),
-                List.<Type>nil(),
-                defaultConstrSym.flags(),
-                false);
-        defaultConstr.sym = defaultConstrSym;
-        defaultConstr.type = defaultConstrSym.type;
+                functionalClassSym);
 
-        class DefaultConstructorPatcher extends TreeScanner {
+        enter.setEnclosingType(functionalClassSym, functionalClassSym.owner);
+
+        functionalClassSym.flatname = chk.localClassName(functionalClassSym);
+        chk.compiled.put(functionalClassSym.flatname, functionalClassSym);
+
+        functionalClassSym.members_field = new Scope(functionalClassSym);
+
+        if (targetType.isInterface()) {
+            ((ClassType)functionalClassSym.type).supertype_field = syms.objectType;
+            ((ClassType)functionalClassSym.type).interfaces_field = List.of(targetType);
+        }
+        else {
+            ((ClassType)functionalClassSym.type).supertype_field = targetType;
+        }
+
+        return functionalClassSym;
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
+    class LambdaToInnerAnalyzer extends LambdaAnalyzer {
+
+        @Override
+        TranslationContext makeLambdaContext(JCLambda tree) {
+            return new LambdaToInnerTranslationContext(tree);
+        }
+
+        @Override
+        TranslationContext makeReferenceContext(JCMemberReference tree) {
+            return new ReferenceToInnerTranslationContext(tree);
+        }
+        
+        class LambdaToInnerTranslationContext extends LambdaTranslationContext {
+
+            /** the synthetic symbol for the method hoisting the translated lambda */
+            Symbol translatedSym;
+
+            /** the synthetic symbol for the class hoisting the translated lambda */
+            ClassSymbol lambdaClassSym;
+
+            LambdaToInnerTranslationContext(JCLambda tree) {
+                super(tree);
+                this.lambdaClassSym = makeFunctionalClassSym(STATIC, tree.targetType, owner);
+                this.translatedSym = makeFunctionalDescriptorSym(tree.targetType, lambdaClassSym);
+            }
+
             @Override
-            public void visitApply(JCMethodInvocation tree) {
-                super.visitApply(tree);
-                tree.type = syms.voidType; //super constructor call has void type
-            }
-            @Override
-            public void visitIdent(JCIdent tree) {
-                if (tree.name == names._super) {
-                    //set super constructor symbol and type
-                    tree.sym = syms.objectType.tsym.members().lookup(names.init).sym;
-                    tree.type = tree.sym.type;
+            protected Symbol translate(String name, Symbol sym, LambdaSymbolKind skind) {
+                switch (skind) {
+                    case CAPTURED_THIS:
+                    case CAPTURED_VAR:
+                        return sym == self ?
+                                makeSyntheticVar(FINAL, names._this, self.type, lambdaClassSym) :
+                                makeSyntheticVar(0, name, sym.type, lambdaClassSym);
+                    case LOCAL_VAR:
+                    case PARAM:
+                        return makeSyntheticVar(0, name, sym.type, translatedSym);
+                    default: throw new AssertionError();
                 }
             }
         }
 
-        new DefaultConstructorPatcher().scan(defaultConstr);
-        return defaultConstr;
-    }
+        class ReferenceToInnerTranslationContext extends ReferenceTranslationContext {
 
-    @Override
-    public void visitIdent(JCIdent tree) {
-        if ((currentClass.sym.flags() & Flags.LAMBDA) != 0 &&
-                (tree.name == names._super ||
-                tree.name == names._this)) {
-            Type encl = tree.sym.owner.type;
-            result = make.Select(make.Type(types.erasure(encl)), tree.sym);
-        }
-        else if ((currentClass.sym.flags() & Flags.LAMBDA) != 0 &&
-                (tree.sym.kind == Kinds.VAR || tree.sym.kind == Kinds.MTH) &&
-                tree.sym.owner == syms.objectType.tsym) {
-            Type encl = currentClass.type.getEnclosingType();
-            while (encl != Type.noType && (encl.tsym.flags() & Flags.LAMBDA) != 0) {
-                encl = encl.getEnclosingType();
-            }
-            JCFieldAccess qualifiedThis =
-                    (JCFieldAccess)make.Select(make.Type(types.erasure(encl)),
-                                               names._this).setType(encl);
-            qualifiedThis.sym =  new VarSymbol(0, names._this, encl, encl.tsym);
-            result = make.Select(qualifiedThis, tree.sym);
-        }
-        else {
-            super.visitIdent(tree);
+            /** the synthetic symbol for the method hoisting the translated reference */
+            Symbol translatedSym;
+
+            /** the synthetic symbol for the class hoisting the translated reference */
+            ClassSymbol referenceClassSym;
+
+            /** the synthetic symbol for the method hoisting the bridged lambda */
+            Symbol bridgeSym;
+
+            ReferenceToInnerTranslationContext(JCMemberReference tree) {
+                super(tree);
+                this.referenceClassSym = makeFunctionalClassSym(isSpecial() ? 0 : STATIC, tree.targetType, owner);
+                this.translatedSym = makeFunctionalDescriptorSym(tree.targetType, referenceClassSym);
+                if (isSpecial()) {
+                    this.bridgeSym = makeSyntheticMethod(0, "$bridge$" + tree.pos, translatedSym.type, owner.enclClass());
+                }
+            }   
         }
     }
-
-    @Override
-    public void visitMethodDef(JCMethodDecl tree) {
-        if (tree.name == names.init &&
-                (currentClass.sym.flags() & Flags.LAMBDA) != 0) {
-            //skip synthetic constructor of lambda class
-            result = tree;
-            return;
-        }
-        super.visitMethodDef(tree);
-    }
-
-    @Override
-    public void visitVarDef(final JCVariableDecl tree) {
-        if (tree.sym.owner.kind == Kinds.MTH &&
-                tree.init != null &&
-                tree.init.getTag() == JCTree.LAMBDA) {
-
-            //if this is a local variable initialized with a lambda expression
-            //we need to check whether the variable is referenced from the lambda
-
-            super.visitVarDef(tree);
-            JCClassDecl c = ((JCNewClass)tree.init).def;
-            final VarSymbol selfRef = new VarSymbol(0, names._this, c.type, c.sym);
-
-            //references to variable under initialization from lambda body
-            //are automatically turned into references to a synthetic field
-            //of the desugared lambda class
-            
-            class LambdaVarInitPatcher extends TreeScanner {
-                boolean needsCapture = true;
-                @Override
-                public void visitIdent(JCIdent that) {
-                    if (tree.sym == that.sym) {
-                        needsCapture = true;
-                        that.sym = selfRef;
-                        that.name = selfRef.name;
-                    }
-                }
-            }
-            LambdaVarInitPatcher lvis = new LambdaVarInitPatcher();
-            lvis.scan(tree.init);
-        } else {
-            super.visitVarDef(tree);
-        }
-    }
+    // </editor-fold>
 }
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Wed Oct 26 16:41:55 2011 +0100
@@ -25,23 +25,21 @@
 
 package com.sun.tools.javac.comp;
 
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.comp.LambdaTranslator.LambdaAnalyzer;
+import com.sun.tools.javac.comp.LambdaToMethod.LambdaToMethodAnalyzer.*;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.List;
 
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Type.*;
-import com.sun.tools.javac.tree.JCTree.*;
-
 import static com.sun.tools.javac.code.Flags.*;
-import static com.sun.tools.javac.code.Kinds.*;
+import static com.sun.tools.javac.comp.LambdaTranslator.LambdaSymbolKind.*;
 
 /** This pass desugars lambda expressions into static methods
  *
@@ -52,6 +50,7 @@
  */
 public class LambdaToMethod extends LambdaTranslator {
 
+    // <editor-fold defaultstate="collapsed" desc="Instantiating">
     protected static final Context.Key<LambdaToMethod> unlambdaKey =
         new Context.Key<LambdaToMethod>();
 
@@ -62,63 +61,20 @@
         return instance;
     }
 
-    /** use indy calls to create instances of SAM types */
-    boolean useIndy;
-
-    /** current lambda translation context */
-    LambdaTranslationContext context = null;
-
-    /** list of static methods corresponding to translated static methods
-     *  such as lambdas, and member reference bridges */
-    private ListBuffer<JCTree> trans_static;
-    
-    /** list of static methods corresponding to translated instance methods
-     *  used for special reference bridges (super/this) */
-    private ListBuffer<JCTree> trans_instance;
-
-    /** map from lambda trees to translation contexts */
-    private Map<JCTree, TranslationContext> contextMap = new HashMap<JCTree, TranslationContext>();
-    
     protected LambdaToMethod(Context context) {
-        super(context);
-        Options options = Options.instance(context);
-        useIndy = options.isSet("useIndy");
+        super(context, null);
+        analyzer = new LambdaToMethodAnalyzer();
     }
 
     @Override
-    public void visitClassDef(JCClassDecl tree) {
-        if (tree.sym.owner.kind == PCK) {
-            new LambdaAnalyzer().scan(tree);
-            trans_static = ListBuffer.lb();
-        }
-        ListBuffer<JCTree> prevTranslatedInstance = trans_instance;
-        try {
-            trans_instance = ListBuffer.lb();
-            super.visitClassDef(tree);
-            if (tree.sym.owner.kind == PCK) {
-                //if this is a toplevel class, add all translated statics here
-                tree.defs = tree.defs.appendList(trans_static.toList());
-                for (JCTree lambda : trans_static) {
-                    tree.sym.members().enter(((JCMethodDecl)lambda).sym);
-                }
-            }
-            //add all translated instance methods here
-            tree.defs = tree.defs.appendList(trans_instance.toList());
-            for (JCTree lambda : trans_instance) {
-                tree.sym.members().enter(((JCMethodDecl)lambda).sym);
-            }
-            result = tree;
-        }
-        finally {
-            trans_instance = prevTranslatedInstance;
-        }
+    protected LambdaAnalyzer makeAnalyzer() {
+        return new LambdaToMethodAnalyzer();
     }
+    // </editor-fold>
 
+    // <editor-fold defaultstate="collapsed" desc="visitor methods">
     @Override
     public void visitLambda(JCLambda tree) {
-        LambdaTranslationContext localContext = (LambdaTranslationContext)contextMap.get(tree);
-        LambdaTranslationContext prevContext = context;
-
         //Step One:
         //translate the lambda expression into a static method. The signature of
         //the static method is augmented with the following synthetic parameters:
@@ -131,50 +87,38 @@
         //captured variables, enclosing members are adjusted accordingly
         //to refer to the static method parameters (rather than i.e. acessing to
         //captured members directly).
-        
-        try {
-            context = localContext;
-            //compute synthetic params
-            ListBuffer<JCVariableDecl> syntheticParams = ListBuffer.lb();
-            
-            //add encl$n if needed
-            for (Symbol thisSym : localContext.capturedThis.values()) {
-                syntheticParams.append(make.VarDef((VarSymbol)thisSym, null));
-            }
-            //add captured locals
-            for (Symbol fv : localContext.capturedLocals.values()) {
-                syntheticParams.append(make.at(tree.pos).VarDef((VarSymbol)fv, null));
-            }
-            //add lambda parameters
-            for (Symbol param : localContext.lambdaParams.values()) {
-                syntheticParams.append(make.at(tree.pos).VarDef((VarSymbol)param, null));
-            }
 
-            //prepend synthetic args to translated lambda method signature
-            MethodType lambdaType = types.findDescriptor(tree.targetType);
-            localContext.translatedSym.type = lambdaType = types.createMethodTypeWithParameters(lambdaType, TreeInfo.types(syntheticParams.toList()));
+        LambdaToMethodTranslationContext localContext = (LambdaToMethodTranslationContext)context;
 
-            //create method declaration hoisting the lambda body
-            JCBlock body = translate(makeLambdaBody(tree));
-            JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(STATIC | SYNTHETIC),
-                    localContext.translatedSym.name,
-                    make.QualIdent(lambdaType.getReturnType().tsym),
-                    List.<JCTypeParameter>nil(),
-                    syntheticParams.toList(),
-                    tree.sym.type.getThrownTypes() == null ?
-                        List.<JCExpression>nil() :
-                        make.Types(tree.sym.type.getThrownTypes()),
-                    body,
-                    null);
-            lambdaDecl.sym = (MethodSymbol)localContext.translatedSym;
-            lambdaDecl.type = lambdaType;
+        //compute synthetic params
+        ListBuffer<JCVariableDecl> syntheticParams = ListBuffer.lb();
 
-            //translate lambda body
-            trans_static = trans_static.prepend(lambdaDecl);
+        //add encl$n, cap$n and $n if needed
+        for (Symbol thisSym : localContext.getSymbolMap(CAPTURED_THIS, CAPTURED_VAR, PARAM).values()) {
+            syntheticParams.append(make.VarDef((VarSymbol)thisSym, null));
         }
-        finally {
-            context = prevContext;
-        }
+
+        //prepend synthetic args to translated lambda method signature
+        MethodType lambdaType = types.findDescriptor(tree.targetType);
+        localContext.translatedSym.type = lambdaType = types.createMethodTypeWithParameters(lambdaType, TreeInfo.types(syntheticParams.toList()));
+
+        //create method declaration hoisting the lambda body
+        JCBlock body = translate(makeLambdaBody(tree, lambdaType.getReturnType()));
+        JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(STATIC | SYNTHETIC),
+                localContext.translatedSym.name,
+                make.QualIdent(lambdaType.getReturnType().tsym),
+                List.<JCTypeParameter>nil(),
+                syntheticParams.toList(),
+                lambdaType.getThrownTypes() == null ?
+                    List.<JCExpression>nil() :
+                    make.Types(lambdaType.getThrownTypes()),
+                body,
+                null);
+        lambdaDecl.sym = (MethodSymbol)localContext.translatedSym;
+        lambdaDecl.type = lambdaType;
+
+        //translate lambda body
+        trans_static = trans_static.prepend(lambdaDecl);
 
         //Step Two:
         //now that we have generated a static method for the lambda expression,
@@ -191,7 +135,7 @@
         ListBuffer<JCExpression> syntheticInits = ListBuffer.lb();
 
         //append reference to enclosing contexts
-        for (Symbol sym : localContext.capturedThis.keySet()) {
+        for (Symbol sym : localContext.getSymbolMap(CAPTURED_THIS).keySet()) {
             VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
                     names._this,
                     sym.type, localContext.owner);
@@ -200,106 +144,152 @@
         }
 
         //add captured locals
-        for (Symbol fv : localContext.capturedLocals.keySet()) {
+        for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
             if (fv == localContext.self) continue;
             JCTree captured_local = make.Ident(fv).setType(fv.type);
             syntheticInits.append((JCExpression)captured_local);
         }
+            
+        Symbol sym = localContext.needsBridge() ?
+                bridgeLambda(tree, localContext) :
+                localContext.translatedSym;
 
-        if (useIndy) {
-            
-            Symbol sym = localContext.needsBridge() ?
-                    bridgeLambda(tree, localContext) :
-                    localContext.translatedSym;
+        //first determine the static bsm args
+        List<Object> bsm_staticArgs = List.of(
+            tree.targetType.tsym,
+            new Pool.MemberReference(ClassFile.REF_invokeStatic, sym));
 
-            //first determine the static bsm args
-            List<Object> bsm_staticArgs = List.of(
-                tree.targetType.tsym,
-                new Pool.MemberReference(ClassFile.REF_invokeStatic, sym));
+        //then, determine the arguments to the indy call
+        List<JCExpression> indy_args = List.of(Bool(localContext.isRecursive()),
+                Array(syms.objectType, translate(syntheticInits.toList(), localContext.prev).toArray(new JCExpression[syntheticInits.size()])));
 
-            //then, determine the arguments to the indy call
-            List<JCExpression> indy_args = List.of(Bool(localContext.isRecursive()),
-                    Array(syms.objectType, translate(syntheticInits.toList()).toArray(new JCExpression[syntheticInits.size()])));
+        //finally, compute the type of the indy call
+        MethodType indyType =
+                new MethodType(List.of(syms.booleanType, new ArrayType(syms.objectType, syms.arrayClass)),
+                               types.erasure(tree.targetType),
+                               List.<Type>nil(),
+                               syms.methodClass);
 
-            //finally, compute the type of the indy call
-            MethodType indyType =
-                    new MethodType(List.of(syms.booleanType, new ArrayType(syms.objectType, syms.arrayClass)),
-                                   types.erasure(tree.targetType),
-                                   List.<Type>nil(),
-                                   syms.methodClass);
-
-            //build a sam instance using an indy call to the meta-factory
-            result = makeIndyCall(tree, syms.proxyHelper, names.metaFactory, bsm_staticArgs, indyType, indy_args);
-        } else {
-            //build a method reference AST node to the newly translated lambda
-            JCMemberReference mref = make.Reference(ReferenceMode.INVOKE, localContext.translatedSym.name, make.QualIdent(localContext.translatedSym.owner), null, null);
-            mref.sym = localContext.translatedSym;
-            mref.type = tree.targetType;
-
-            //build a sam instance using dynamic proxies
-            result = makeMethodHandleWrapperProxy(mref,
-                                                  tree.targetType,
-                                                  translate(syntheticInits.toList()),
-                                                  localContext.isRecursive());
-        }
+        //build a sam instance using an indy call to the meta-factory
+        result = makeIndyCall(tree, syms.proxyHelper, names.metaFactory, bsm_staticArgs, indyType, indy_args);
     }
 
     @Override
     public void visitReference(JCMemberReference tree) {
-        if (useIndy) {
-            ReferenceTranslationContext localContext = (ReferenceTranslationContext)contextMap.get(tree);
+        ReferenceToMethodTranslationContext localContext = (ReferenceToMethodTranslationContext)context;
 
-            //first determine the method symbol to be used to generate the sam instance
-            //this is either the method reference symbol, or the bridged reference symbol
-            Symbol refSym = localContext.needsBridge() ?
-                bridgeMemberReference(tree, localContext) :
-                tree.sym;
+        //first determine the method symbol to be used to generate the sam instance
+        //this is either the method reference symbol, or the bridged reference symbol
+        Symbol refSym = localContext.needsBridge() ?
+            bridgeMemberReference(tree, localContext) :
+            tree.sym;
 
-            //second, determine the static bsm args
-            List<Object> bsm_staticArgs = List.of(
-                tree.targetType.tsym,
-                new Pool.MemberReference(localContext.referenceKind(), refSym));
+        //second, determine the static bsm args
+        List<Object> bsm_staticArgs = List.of(
+            tree.targetType.tsym,
+            new Pool.MemberReference(localContext.referenceKind(), refSym));
+
+        //third, determine the arguments to the indy call
+        JCExpression qualifierExpr = null;
+        if (localContext.needsBridge() && localContext.isSpecial()) {
+            VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
+                names._this,
+                localContext.owner.enclClass().type, localContext.owner);
+            JCIdent _thisRef = (JCIdent)make.Ident(_this).setType(localContext.owner.enclClass().type);
+            qualifierExpr = _thisRef;
+        } else if (localContext.isInstanceRef()) {
+            qualifierExpr = tree.getQualifierExpression();
+        }
+
+        List<JCExpression> indy_args = List.of(Bool(false));
+        if (qualifierExpr != null) {
+            indy_args = indy_args.append(Array(syms.objectType, qualifierExpr));
+        } else {
+            indy_args = indy_args.append(Null());
+        }
+
+        //finally, compute the type of the indy call
+        MethodType indyType =
+                new MethodType(List.of(syms.booleanType, new ArrayType(syms.objectType, syms.arrayClass)),
+                               types.erasure(tree.targetType),
+                               List.<Type>nil(),
+                               syms.methodClass);
+
+        //build a sam instance using an indy call to the meta-factory
+        result = makeIndyCall(tree, syms.proxyHelper, names.metaFactory, bsm_staticArgs, indyType, indy_args);
+
+        //if we had a static reference with non-static qualifier, add a let
+        //expression to force the evaluation of the qualifier expr
+        if (localContext.needsReceiverEval()) {
+            VarSymbol rec = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner);
+            JCVariableDecl recDef = make.VarDef(rec, tree.getQualifierExpression());
+            result = make.LetExpr(recDef, result).setType(types.erasure(tree.targetType));
+        }
+    }
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="Translation helper methods">
+    /**
+     * Bridges a lambda static method - this is needed whenever the signature of the
+     * erased SAM descriptor declaration does not match with the signature of the
+     * translated lambda static method. The body of the bridge will simply contain a
+     * method call to the symbol associated with the lambda static method to be bridged.
+     * Note: an alternative would have been to use erased types in the lambda static method
+     * and to add explicit cast to the non-erased types - but, in doing so, we loose
+     * immutability of the attributed lambda body AST.
+     */
+    private Symbol bridgeLambda(JCLambda tree, LambdaToMethodTranslationContext localContext) {
+        Type samDesc = types.erasure(types.findDescriptor(tree.targetType.tsym).type);
+
+        //generate the parameter list for the bridged member reference - the
+        //bridge signature will match the signature of the target sam descriptor
+        ListBuffer<JCExpression> args = ListBuffer.lb();
+        ListBuffer<JCVariableDecl> params = ListBuffer.lb();
+        int i = 0;
+        
+        //add captured this, captured locals and params
+        for (Symbol thisSym : localContext.getSymbolMap(CAPTURED_THIS, CAPTURED_VAR, PARAM).values()) {
+            VarSymbol vsym = new VarSymbol(0, names.fromString("x$" + i++), thisSym.type, localContext.bridgeSym);
+            params.append(make.VarDef(vsym, null));
+            args.append(make.Ident(vsym));
+        }
+
+        //generate the bridge method declaration
+        JCMethodDecl bridgeDecl = make.MethodDef(make.Modifiers(STATIC | SYNTHETIC),
+                localContext.bridgeSym.name,
+                make.QualIdent(samDesc.getReturnType().tsym),
+                List.<JCTypeParameter>nil(),
+                params.toList(),
+                samDesc.getThrownTypes() == null ?
+                    List.<JCExpression>nil() :
+                    make.Types(samDesc.getThrownTypes()),
+                null,
+                null);
+        bridgeDecl.sym = (MethodSymbol)localContext.bridgeSym;
+        bridgeDecl.type = localContext.bridgeSym.type = types.createMethodTypeWithParameters(samDesc, TreeInfo.types(params.toList()));
             
-            //third, determine the arguments to the indy call
-            JCExpression qualifierExpr = null;
-            if (localContext.needsBridge() && localContext.isSpecial()) {
-                VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
-                    names._this,
-                    localContext.owner.enclClass().type, localContext.owner);
-                JCIdent _thisRef = (JCIdent)make.Ident(_this).setType(localContext.owner.enclClass().type);
-                qualifierExpr = _thisRef;
-            } else if (localContext.isInstanceRef()) {
-                qualifierExpr = tree.getQualifierExpression();
-            }
-            
-            List<JCExpression> indy_args = List.of(Bool(false));
-            if (qualifierExpr != null) {
-                indy_args = indy_args.append(Array(syms.objectType, qualifierExpr));
-            } else {
-                indy_args = indy_args.append(Null());
-            }
+        //bridge method body generation - this is a method call to the bridged lambda method
 
-            //finally, compute the type of the indy call
-            MethodType indyType =
-                    new MethodType(List.of(syms.booleanType, new ArrayType(syms.objectType, syms.arrayClass)),
-                                   types.erasure(tree.targetType),
-                                   List.<Type>nil(),
-                                   syms.methodClass);
+        //create the qualifier expression
+        JCFieldAccess select = make.Select(
+                make.Type(localContext.bridgeSym.owner.type),
+                localContext.translatedSym.name);
+        select.sym = localContext.translatedSym;
+        select.type = localContext.translatedSym.type;
 
-            //build a sam instance using an indy call to the meta-factory
-            result = makeIndyCall(tree, syms.proxyHelper, names.metaFactory, bsm_staticArgs, indyType, indy_args);
-
-            //if we had a static reference with non-static qualifier, add a let
-            //expression to force the evaluation of the qualifier expr
-            if (localContext.needsReceiverEval()) {
-                VarSymbol rec = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner);
-                JCVariableDecl recDef = make.VarDef(rec, tree.getQualifierExpression());
-                result = make.LetExpr(recDef, result).setType(types.erasure(tree.targetType));
-            }
-        } else {
-            //translate using either dynamic proxies or MethodHandleProxies
-            super.visitReference(tree);
-        }
+        //create the method call expression
+        JCMethodInvocation apply = make.Apply(List.<JCExpression>nil(), select, args.toList(), false);
+        apply.type = samDesc.getReturnType();
+        
+        //the body is either a return expression containing a method call,
+        //or the method call itself, depending on whether the return type of
+        //the bridge is non-void/void.
+        bridgeDecl.body = make.Block(0, List.<JCStatement>of((apply.type.tag != TypeTags.VOID) ?
+            make.Return(apply) :
+            make.Exec(apply)));
+        
+        trans_static = trans_static.prepend(bridgeDecl);
+        return bridgeDecl.sym;
     }
 
     /**
@@ -310,7 +300,7 @@
      * The body of the bridge will simply contain a method/constructor call
      * to the symbol associated with the method reference to be bridged.
      */
-    Symbol bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) {
+    private Symbol bridgeMemberReference(JCMemberReference tree, ReferenceToMethodTranslationContext localContext) {
         Type samDesc = types.erasure(types.findDescriptor(tree.targetType.tsym).type);
 
         //generate the parameter list for the bridged member reference - the
@@ -411,177 +401,71 @@
         }
         return bridgeDecl.sym;
     }
-    
+
     /**
-     * Bridges a lambda static method - this is needed whenever the signature of the
-     * erased SAM descriptor declaration does not match with the signature of the
-     * translated lambda static method. The body of the bridge will simply contain a
-     * method call to the symbol associated with the lambda static method to be bridged.
-     * Note: an alternative would have been to use erased types in the lambda static method
-     * and to add explicit cast to the non-erased types - but, in doing so, we loose
-     * immutability of the attributed lambda body AST.
+     * Generate an indy method call with given name, type and static bootstrap arguments types
      */
-    Symbol bridgeLambda(JCLambda tree, LambdaTranslationContext localContext) {
-        Type samDesc = types.erasure(types.findDescriptor(tree.targetType.tsym).type);
+    private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName, List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs) {
+        List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
+                                         syms.stringType,
+                                         syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
 
-        //generate the parameter list for the bridged member reference - the
-        //bridge signature will match the signature of the target sam descriptor
-        ListBuffer<JCExpression> args = ListBuffer.lb();
-        ListBuffer<JCVariableDecl> params = ListBuffer.lb();
-        int i = 0;
-        
-        for (Symbol thisSym : localContext.capturedThis.values()) {
-            VarSymbol vsym = new VarSymbol(0, names.fromString("x$" + i++), thisSym.type, localContext.bridgeSym);
-            params.append(make.VarDef(vsym, null));
-            args.append(make.Ident(vsym));
-        }
-        //add captured locals
-        for (Symbol fv : localContext.capturedLocals.values()) {
-            VarSymbol vsym = new VarSymbol(0, names.fromString("x$" + i++), fv.type, localContext.bridgeSym);
-            params.append(make.at(tree.pos).VarDef(vsym, null));
-            args.append(make.Ident(vsym));
-        }
-        //add lambda parameter types
-        for (Type p : samDesc.getParameterTypes()) {
-            VarSymbol vsym = new VarSymbol(0, names.fromString("x$" + i++), p, localContext.translatedSym);
-            params.append(make.VarDef(vsym, null));
-            args.append(make.Ident(vsym));
+        Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
+                bsmName, bsm_staticArgs, List.<Type>nil());
+
+        DynamicMethodSymbol dynSym =
+                new DynamicMethodSymbol(names.lambda,
+                                        syms.noSymbol,
+                                        bsm.isStatic() ? ClassFile.REF_invokeStatic : ClassFile.REF_invokeVirtual,
+                                        (MethodSymbol)bsm,
+                                        indyType,
+                                        staticArgs.toArray());
+
+        JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
+        qualifier.sym = dynSym;
+        qualifier.type = indyType.getReturnType();
+
+        JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, indyArgs, false);
+        proxyCall.type = indyType.getReturnType();
+        return proxyCall;
+    }
+    //where
+        private List<Type> bsmStaticArgToTypes(List<Object> args) {
+            ListBuffer<Type> argtypes = ListBuffer.lb();
+            for (Object arg : args) {
+                argtypes.append(bsmStaticArgToType(arg));
+            }
+            return argtypes.toList();
         }
 
-        //generate the bridge method declaration
-        JCMethodDecl bridgeDecl = make.MethodDef(make.Modifiers(STATIC | SYNTHETIC),
-                localContext.bridgeSym.name,
-                make.QualIdent(samDesc.getReturnType().tsym),
-                List.<JCTypeParameter>nil(),
-                params.toList(),
-                tree.sym.type.getThrownTypes() == null ?
-                    List.<JCExpression>nil() :
-                    make.Types(tree.sym.type.getThrownTypes()),
-                null,
-                null);
-        bridgeDecl.sym = (MethodSymbol)localContext.bridgeSym;
-        bridgeDecl.type = localContext.bridgeSym.type = types.createMethodTypeWithParameters(samDesc, TreeInfo.types(params.toList()));
-            
-        //bridge method body generation - this is a method call to the bridged lambda method
-
-        //create the qualifier expression
-        JCFieldAccess select = make.Select(
-                make.Type(localContext.bridgeSym.owner.type),
-                localContext.translatedSym.name);
-        select.sym = localContext.translatedSym;
-        select.type = localContext.translatedSym.type;
-
-        //create the method call expression
-        JCMethodInvocation apply = make.Apply(List.<JCExpression>nil(), select, args.toList(), false);
-        apply.type = samDesc.getReturnType();
-        
-        //the body is either a return expression containing a method call,
-        //or the method call itself, depending on whether the return type of
-        //the bridge is non-void/void.
-        bridgeDecl.body = make.Block(0, List.<JCStatement>of((apply.type.tag != TypeTags.VOID) ?
-            make.Return(apply) :
-            make.Exec(apply)));
-        
-        trans_static = trans_static.prepend(bridgeDecl);
-        return bridgeDecl.sym;
-    }
-
-    @Override
-    public void visitIdent(JCIdent tree) {
-        if (context == null || !lambdaSymbolFilter.accepts(tree.sym)) {
-            super.visitIdent(tree);
-        } else {
-            if (context.lambdaParams.containsKey(tree.sym)) {
-                Symbol translatedSym = context.lambdaParams.get(tree.sym);
-                result = make.Ident(translatedSym).setType(tree.type);
-            } else if (context.lambdaLocals.containsKey(tree.sym)) {
-                Symbol translatedSym = context.lambdaLocals.get(tree.sym);
-                result = make.Ident(translatedSym).setType(tree.type);
-            } else if (context.capturedLocals.containsKey(tree.sym)) {
-                Symbol translatedSym = context.capturedLocals.get(tree.sym);
-                result = make.Ident(translatedSym).setType(tree.type);
+        private Type bsmStaticArgToType(Object arg) {
+            Assert.checkNonNull(arg);
+            if (arg instanceof ClassSymbol) {
+                return syms.classType;
+            } else if (arg instanceof Integer) {
+                return syms.intType;
+            } else if (arg instanceof Long) {
+                return syms.longType;
+            } else if (arg instanceof Float) {
+                return syms.floatType;
+            } else if (arg instanceof Double) {
+                return syms.doubleType;
+            } else if (arg instanceof String) {
+                return syms.stringType;
+            } else if (arg instanceof Pool.MemberReference) {
+                return syms.methodHandleType;
+            } else if (arg instanceof MethodType) {
+                return syms.methodTypeType;
             } else {
-                if (tree.sym.owner.kind == TYP) {
-                    for (Map.Entry<Symbol, Symbol> encl_entry : context.capturedThis.entrySet()) {
-                        if (tree.sym.isMemberOf((ClassSymbol)encl_entry.getKey(), types)) {
-                            result = make.Select(make.Ident(encl_entry.getValue()), tree.sym).setType(tree.type);
-                            return;
-                        }
-                    }
-                }
-                //access to untranslated symbols (i.e. compile-time constants,
-                //members defined inside the lambda body, etc.) )
-                super.visitIdent(tree);
+                Assert.error("bad static arg " + arg.getClass());
+                return null;
             }
         }
-    }
-    
-    @Override
-    public void visitSelect(JCFieldAccess tree) {
-        if (context != null && lambdaSymbolFilter.accepts(tree.sym) &&
-                tree.name == names._this &&
-                context.capturedThis.containsKey(tree.selected.type.tsym)) {
-            JCExpression selected = translate(tree.selected);
-            result = make.Ident(context.capturedThis.get(selected.type.tsym));
-        } else {
-            super.visitSelect(tree);
-        }
-    }
+    // </editor-fold>
 
-    /**
-     *  This is used to filter out those identifiers that needs to be adjusted
-     *  when translating away lambda expressions
-     */
-    Filter<Symbol> lambdaSymbolFilter = new Filter<Symbol>() {
-        public boolean accepts(Symbol sym) {
-            return !sym.isStatic() &&
-                    (sym.kind == VAR || sym.kind == MTH) &&
-                    sym.name != names._super && sym.name != names.init;
-        }
-    };
-
-    @Override
-    public void visitVarDef(JCVariableDecl tree) {
-        if (context != null && context.lambdaLocals.containsKey(tree.sym)) {
-            JCExpression init = translate(tree.init);
-            result = make.VarDef((VarSymbol)context.lambdaLocals.get(tree.sym), init);
-        } else {
-            super.visitVarDef(tree);
-        }
-    }
-
-    /**
-     * This visitor collects information about translation of a lambda expression.
-     * More specifically, it keeps track of the enclosing contexts and captured locals
-     * accessed by the lambda being translated (as well as other useful info).
-     */
-    class LambdaAnalyzer extends TreeScanner {
-
-        class Frame {
-            final JCTree tree;
-            List<Symbol> locals;
-
-            public Frame(JCTree tree) {
-                this.tree = tree;
-            }
-
-            void addLocal(Symbol sym) {
-                if (locals == null) {
-                    locals = List.nil();
-                }
-                locals = locals.prepend(sym);
-            }
-        }
-
-        /** current lambda translation context */
-        LambdaTranslationContext context = null;
-
-        /** the frame stack - used to reconstruct translation info about enclosing scopes */
-        List<Frame> frameStack = List.nil();
-
-        /** pending local variable with lambda initializer (can be used for recursion) */
-        Symbol self = null;
-
+    // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
+    class LambdaToMethodAnalyzer extends LambdaAnalyzer {
+        
         /** keep the count of lambda expression (used to generate unambiguous names) */
         int lambdaCount = 0;
 
@@ -590,414 +474,84 @@
         }
 
         @Override
-        public void visitClassDef(JCClassDecl tree) {
-            List<Frame> prevStack = frameStack;
-            try {
-                if (frameStack.nonEmpty() && frameStack.head.tree.getTag() == JCTree.LAMBDA) {
-                    tree.sym.owner = owner();
-                    ((ClassType)tree.sym.type).setEnclosingType(Type.noType);
+        TranslationContext makeLambdaContext(JCLambda tree) {
+            return new LambdaToMethodTranslationContext(tree);
+        }
+
+        @Override
+        TranslationContext makeReferenceContext(JCMemberReference tree) {
+            return new ReferenceToMethodTranslationContext(tree);
+        }
+        
+        class LambdaToMethodTranslationContext extends LambdaTranslationContext {
+
+            /** the synthetic symbol for the method hoisting the translated lambda */
+            Symbol translatedSym;
+
+            /** the synthetic symbol for the method hoisting the bridged lambda */
+            Symbol bridgeSym;
+
+            LambdaToMethodTranslationContext(JCLambda tree) {
+                super(tree);
+                this.translatedSym = makeSyntheticMethod(STATIC, lambdaName(), null, owner.outermostClass());
+                if (needsBridge()) {
+                    this.bridgeSym = makeSyntheticMethod(STATIC,
+                            lambdaName().append(names.fromString("$bridge")), null, owner.outermostClass());
                 }
-                frameStack = frameStack.prepend(new Frame(tree));
-                super.visitClassDef(tree);
             }
-            finally {
-                frameStack = prevStack;
+
+            protected boolean needsBridge() {
+                return !types.isSameType(
+                        types.erasure(types.findDescriptor(tree.targetType)),
+                        types.erasure(types.findDescriptor(tree.targetType.tsym).type));
+            }
+
+            @Override
+            protected Symbol translate(String name, Symbol sym, LambdaSymbolKind skind) {
+                return makeSyntheticVar(0, name, sym.type, translatedSym);
             }
         }
 
-        /**
-         * Return a valid owner given the current declaration stack
-         * (required to skip synthetic lambda symbols)
-         */
-        Symbol owner() {
-            for (Frame block : frameStack) {
-                switch (block.tree.getTag()) {
-                    case JCTree.CLASSDEF:
-                        return ((JCClassDecl)block.tree).sym;
-                    case JCTree.METHODDEF:
-                        return ((JCMethodDecl)block.tree).sym;
+        class ReferenceToMethodTranslationContext extends ReferenceTranslationContext {
+
+            Symbol bridgeSym;
+
+            ReferenceToMethodTranslationContext(JCMemberReference tree) {
+                super(tree);
+                if (needsBridge()) {
+                    this.bridgeSym = makeSyntheticMethod(isSpecial() ? 0 : STATIC,
+                            lambdaName().append(names.fromString("$bridge")), null,
+                            isSpecial() ? owner.enclClass() : owner.outermostClass());
                 }
             }
-            Assert.error();
-            return null;
-        }
 
-        /**
-         * Return the declaration corresponding to a symbol in the enclosing
-         * scope; the depth parameter is used to filter out symbols defined
-         * in nested scopes (which do not need to undergo capture).
-         */
-        JCTree capturedDecl(int depth, Symbol sym) {
-            int currentDepth = frameStack.size() - 1;
-            for (Frame block : frameStack) {
-                switch (block.tree.getTag()) {
-                    case JCTree.CLASSDEF:
-                        ClassSymbol clazz = ((JCClassDecl)block.tree).sym;
-                        if (sym.isMemberOf(clazz, types)) {
-                            return currentDepth > depth ? null : block.tree;
-                        }
-                        break;
-                    case JCTree.BLOCK:
-                    case JCTree.METHODDEF:
-                    case JCTree.LAMBDA:
-                        if (block.locals != null && block.locals.contains(sym)) {
-                            return currentDepth > depth ? null : block.tree;
-                        }
-                        break;
-                    default:
-                        Assert.error("bad decl kind " + block.tree.getTag());
-                }
-                currentDepth--;
-            }
-            return null;
-        }
-
-        @Override
-        public void visitReference(JCMemberReference tree) {
-            contextMap.put(tree, new ReferenceTranslationContext(tree, lambdaName(), owner(), frameStack.size() - 1, context));
-        }
-
-        @Override
-        public void visitLambda(JCLambda tree) {
-            LambdaTranslationContext prevContext = context;
-            List<Frame> prevStack = frameStack;
-            try {
-                context = new LambdaTranslationContext(tree, lambdaName(), owner(), self, frameStack.size() - 1, context);
-                frameStack = frameStack.prepend(new Frame(tree));
-                for (JCVariableDecl param : tree.params) {
-                    context.addParam(param.sym);
-                    frameStack.head.addLocal(param.sym);
-                }
-                contextMap.put(tree, context);
-                scan(tree.body);
-            }
-            finally {
-                context = prevContext;
-                frameStack = prevStack;
-            }
-        }
-
-        @Override
-        public void visitIdent(JCIdent tree) {
-            if (context == null || !lambdaSymbolFilter.accepts(tree.sym)) {
-                super.visitIdent(tree);
-            } else {
-                if (tree.sym.kind == VAR &&
-                        tree.sym.owner.kind == MTH &&
-                        tree.type.constValue() == null) {
-                    TranslationContext localContext = context;
-                    while (localContext != null) {
-                        if (localContext.tree.getTag() == JCTree.LAMBDA) {
-                            JCTree block = capturedDecl(localContext.depth, tree.sym);
-                            if (block == null) break;
-                            ((LambdaTranslationContext)localContext).addCapturedVarIfNeeded(tree.sym);
-                        }
-                        localContext = localContext.prev;
-                    }
-                } else if (tree.sym.owner.kind == TYP) {
-                    TranslationContext localContext = context;
-                    while (localContext != null) {
-                        if (localContext.tree.getTag() == JCTree.LAMBDA) {
-                            JCClassDecl clazz = (JCClassDecl)capturedDecl(localContext.depth, tree.sym);
-                            if (clazz == null) break;
-                            ((LambdaTranslationContext)localContext).addEnclosingRefIfNeeded(clazz.sym);
-                        }
-                        localContext = localContext.prev;
-                    }
+            /**
+             * Get the opcode associated with this method reference
+             */
+            int referenceKind() {
+                Symbol refSym = needsBridge() ? bridgeSym : tree.sym;
+                if (tree.getQualifierExpression().getTag() == JCTree.IDENT && !needsBridge() && isSpecial()) {
+                    return Pool.MemberReference.specialRefKind(refSym.isConstructor());
+                } else if (refSym.isConstructor()) {
+                    return Pool.MemberReference.specialRefKind(refSym.isConstructor());
+                } else {
+                    return Pool.MemberReference.methodRefKind(refSym.isStatic(), refSym.enclClass().isInterface());
                 }
             }
-        }
 
-        @Override
-        public void visitSelect(JCFieldAccess tree) {
-            if (context != null && lambdaSymbolFilter.accepts(tree.sym) && tree.name == names._this) {
-                TranslationContext localContext = context;
-                while (localContext != null) {
-                    if (localContext.tree.getTag() == JCTree.LAMBDA) {
-                        JCClassDecl clazz = (JCClassDecl)capturedDecl(localContext.depth, tree.sym);
-                        if (clazz == null) break;
-                        ((LambdaTranslationContext)localContext).addEnclosingRefIfNeeded(clazz.sym);
-                    }
-                    localContext = localContext.prev;
-                }
-                scan(tree.selected);
-            } else {
-                super.visitSelect(tree);
-            }
-        }
-
-        @Override
-        public void visitBlock(JCBlock tree) {
-            List<Frame> prevStack = frameStack;
-            try {
-                if (frameStack.nonEmpty() && frameStack.head.tree.getTag() == JCTree.CLASSDEF) {
-                    frameStack = frameStack.prepend(new Frame(tree));
-                }
-                super.visitBlock(tree);
-            }
-            finally {
-                frameStack = prevStack;
-            }
-        }
-
-        @Override
-        public void visitMethodDef(JCMethodDecl tree) {
-            List<Frame> prevStack = frameStack;
-            try {
-                frameStack = frameStack.prepend(new Frame(tree));
-                super.visitMethodDef(tree);
-            }
-            finally {
-                frameStack = prevStack;
-            }
-        }
-
-        @Override
-        public void visitVarDef(JCVariableDecl tree) {
-            if (frameStack.head.tree.getTag() == JCTree.LAMBDA) {
-                context.addLocalVar(tree.sym);
-            }
-            Symbol prevSelf = self;
-            try {
-                if (tree.init != null &&
-                        tree.init.getTag() == JCTree.LAMBDA) {
-                    self = tree.sym;
-                }
-                if (tree.sym.owner.kind == MTH) {
-                    frameStack.head.addLocal(tree.sym);
-                }
-                super.visitVarDef(tree);
-            }
-            finally {
-                self = prevSelf;
+            /**
+             * Does this reference needs a bridge (i.e. in case the signature
+             * of the referenced symbol does not match the signature of the sam
+             * descriptor
+             */
+            protected boolean needsBridge() {
+                boolean sigMismatch = !types.isSameType(
+                        types.erasure(types.findDescriptor(tree.targetType.tsym).type),
+                        types.erasure(types.memberType(tree.targetType, tree.sym)));
+                return (isUnbound() || isSpecial() ||
+                        sigMismatch);
             }
         }
     }
-
-    /**
-     * This class is used to store important information regarding translation of
-     * lambda expression/method references (see subclasses).
-     */
-    static abstract class TranslationContext<T extends JCTree> {
-
-        /** the underlying (untranslated) tree */
-        T tree;
-        
-        /** the synthetic symbol for bridging the SAM method signature */
-        Symbol bridgeSym;
-
-        /** points to the adjusted enclosing scope in which this lambda/mref expression occurs */
-        Symbol owner;
-
-        /** the depth of this lambda expression in the frame stack */
-        int depth;
-
-        /** the enclosing translation context (set for nested lambdas/mref) */
-        TranslationContext prev;
-
-        TranslationContext(T tree,
-                           Symbol owner,
-                           int depth,
-                           TranslationContext prev) {
-            this.tree = tree;
-            this.owner = owner;
-            this.depth = depth;
-            this.prev = prev;
-        }
-        
-        final Symbol makeSyntheticMethod(long flags, Name name, Symbol owner) {
-            return new MethodSymbol(flags | SYNTHETIC, name, null, owner);
-        }
-        
-        abstract boolean needsBridge();
-    }
-
-    /**
-     * This class retains all the useful information about a lambda expression;
-     * the contents of this class are filled by the LambdaAnalyzer visitor,
-     * and the used by the main translation routines in order to adjust references
-     * to captured locals/members, etc.
-     */
-    final class LambdaTranslationContext extends TranslationContext<JCLambda> {
-        
-        /** the synthetic symbol for the static method hoisting the translated lambda */
-        Symbol translatedSym;
-        
-        /** variable in the enclosing context to which this lambda is assigned */
-        Symbol self;
-        
-        /** map from original to translated lambda parameters */
-        Map<Symbol, Symbol> lambdaParams = new LinkedHashMap<Symbol, Symbol>();
-
-        /** map from original to translated lambda locals */
-        Map<Symbol, Symbol> lambdaLocals = new LinkedHashMap<Symbol, Symbol>();
-
-        /** map from variables in enclosing scope to translated synthetic parameters */
-        Map<Symbol, Symbol> capturedLocals  = new LinkedHashMap<Symbol, Symbol>();
-
-        /** map from class symbols to translated synthetic parameters (for captured member access) */
-        Map<Symbol, Symbol> capturedThis = new LinkedHashMap<Symbol, Symbol>();
-
-        LambdaTranslationContext(JCLambda lambdaTree,
-                           Name name,
-                           Symbol owner,
-                           Symbol self,
-                           int depth,
-                           TranslationContext prev) {
-            super(lambdaTree, owner, depth, prev);
-            this.translatedSym = makeSyntheticMethod(STATIC, name, owner.outermostClass());
-            this.self = self;
-            if (needsBridge()) {
-                this.bridgeSym = makeSyntheticMethod(STATIC, name.append(names.fromString("$bridge")), owner.outermostClass());
-            }
-        }
-
-        /**
-         * Add a captured local variable to this context (if not captured yet)
-         */
-        void addCapturedVarIfNeeded(Symbol sym) {
-            if (!capturedLocals.containsKey(sym)) {
-                Symbol trans_loc =
-                        new VarSymbol(PARAMETER | SYNTHETIC, sym.name, sym.type, translatedSym);
-                capturedLocals.put(sym, trans_loc);
-            }
-        }
-
-        /**
-         * Add a captured enclosing scope to this context (if not captured yet)
-         */
-        void addEnclosingRefIfNeeded(ClassSymbol csym) {
-            if (!capturedThis.containsKey(csym)) {
-                VarSymbol _encl$i = new VarSymbol(PARAMETER | SYNTHETIC,
-                            names.fromString("encl$" + capturedThis.size()),
-                            csym.type, translatedSym);
-                capturedThis.put(csym, _encl$i);
-            }
-        }
-
-        /**
-         * Add a local variable to this context (i.e. variable declared inside the
-         * lambda associated with this context)
-         */
-        void addLocalVar(Symbol sym) {
-            Symbol trans_loc =
-                    new VarSymbol(SYNTHETIC, sym.name, sym.type, translatedSym);
-            lambdaLocals.put(sym, trans_loc);
-        }
-
-        /**
-         * Add a parameter to this context (a parameter of the lambda associated
-         * with this context)
-         */
-        void addParam(Symbol sym) {
-            Symbol trans_param =
-                    new VarSymbol(PARAMETER | SYNTHETIC, sym.name, sym.type, translatedSym);
-            lambdaParams.put(sym, trans_param);
-        }
-
-        /**
-         * Does the lambda associated with this context refers to itself?
-         */
-        boolean isRecursive() {
-            return self != null &&
-                    capturedLocals.containsKey(self);
-        }
-
-        @Override
-        boolean needsBridge() {
-            return !types.isSameType(
-                    types.erasure(types.findDescriptor(tree.targetType)),
-                    types.erasure(types.findDescriptor(tree.targetType.tsym).type));
-        }
-    }
-
-    /**
-     * This class retains all the useful information about a method reference;
-     * the contents of this class are filled by the LambdaAnalyzer visitor,
-     * and the used by the main translation routines in order to adjust method
-     * references (i.e. in case a bridge is needed)
-     */
-    final class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
-
-        ReferenceTranslationContext(JCMemberReference refTree,
-                           Name name,
-                           Symbol owner,
-                           int depth,
-                           TranslationContext prev) {
-            super(refTree, owner, depth, prev);
-            if (needsBridge()) {
-                this.bridgeSym = makeSyntheticMethod(isSpecial() ? 0 : STATIC,
-                        name.append(names.fromString("$bridge")),
-                        isSpecial() ? owner.enclClass() : owner.outermostClass());
-            }
-        }
-
-        /**
-         * Get the opcode associated with this method reference
-         */
-        int referenceKind() {
-            Symbol refSym = needsBridge() ? bridgeSym : tree.sym;
-            if (tree.getQualifierExpression().getTag() == JCTree.IDENT && !needsBridge() && isSpecial()) {
-                return Pool.MemberReference.specialRefKind(refSym.isConstructor());
-            } else if (refSym.isConstructor()) {
-                return Pool.MemberReference.specialRefKind(refSym.isConstructor());
-            } else {
-                return Pool.MemberReference.methodRefKind(refSym.isStatic(), refSym.enclClass().isInterface());
-            }
-        }
-
-        /**
-         * Does this reference needs a bridge (i.e. in case the signature
-         * of the referenced symbol does not match the signature of the sam
-         * descriptor
-         */
-        boolean needsBridge() {
-            boolean sigMismatch = !types.isSameType(
-                    types.erasure(types.findDescriptor(tree.targetType.tsym).type),
-                    types.erasure(types.memberType(tree.targetType, tree.sym)));
-            return (isUnbound() || isSpecial() ||
-                    sigMismatch);
-        }
-
-        /**
-         * Is this an unbound reference? An unbound reference is either a
-         * (i) instance method reference with static qualifier or a (ii) inner
-         * class constructor reference
-         */
-        boolean isUnbound() {
-            return tree.getMode() == ReferenceMode.INVOKE ?
-                (!tree.sym.isStatic() && TreeInfo.isStaticSelector(tree.getQualifierExpression(), names)) :
-                (tree.sym.owner.type.getEnclosingType() != Type.noType);
-        }
-
-        /**
-         * Is this an instance method reference with a non-static qualifier?
-         */
-        boolean isInstanceRef() {
-            return tree.getMode() == ReferenceMode.INVOKE &&
-                    !TreeInfo.isStaticSelector(tree.getQualifierExpression(), names) &&
-                    !tree.sym.isStatic();
-        }
-
-        /**
-         * Is this a static reference with a non-static qualifier (which needs
-         * to be evaluated separately) ?
-         */
-        boolean needsReceiverEval() {
-            return tree.getMode() == ReferenceMode.INVOKE &&
-                !TreeInfo.isStaticSelector(tree.getQualifierExpression(), names) &&
-                tree.sym.isStatic();
-        }
-        
-        /**
-         * Is this a static reference with a non-static qualifier (which needs
-         * to be evaluated separately) ?
-         */
-        boolean isSpecial() {
-            Name name = TreeInfo.name(tree.getQualifierExpression());
-            return !tree.sym.isStatic() &&
-                    name != null &&
-                    (name == names._super || name == names._this);
-        }
-    }
+    // </editor-fold>
 }
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Wed Oct 26 16:41:55 2011 +0100
@@ -25,15 +25,23 @@
 
 package com.sun.tools.javac.comp;
 
+import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
+import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.jvm.*;
-import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.comp.LambdaTranslator.LambdaAnalyzer.*;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.*;
 
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.tree.JCTree.*;
-import com.sun.tools.javac.code.Type.*;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import static com.sun.tools.javac.code.Flags.*;
+import static com.sun.tools.javac.code.Kinds.*;
+import static com.sun.tools.javac.comp.LambdaTranslator.LambdaSymbolKind.*;
 
 /** This is a common superclass for the lambda translators which factors
  * some of the shared translation-related routines.
@@ -51,43 +59,171 @@
     protected TreeMaker make;
     protected Types types;
     protected Env<AttrContext> attrEnv;
+    
+    /** list of static methods corresponding to translated static methods
+     *  such as lambdas, and member reference bridges */
+    protected ListBuffer<JCTree> trans_static;
+    
+    /** list of static methods corresponding to translated instance methods
+     *  used for special reference bridges (super/this) */
+    protected ListBuffer<JCTree> trans_instance;
+    
+    /** the analyzer scanner */
+    protected LambdaAnalyzer analyzer;
+    
+    /** map from lambda trees to translation contexts */
+    protected Map<JCTree, TranslationContext<?>> contextMap;
+    
+    /** current translation context (visitor argument) */
+    protected TranslationContext<?> context;
 
-    /** turns method handles into SAM instances using an internal API */
-    protected boolean useProxy;
-
-    protected LambdaTranslator(Context context) {
+    // <editor-fold defaultstate="collapsed" desc="Instantiating">
+    protected LambdaTranslator(Context context, LambdaAnalyzer analyzer) {
         names = Names.instance(context);
         syms = Symtab.instance(context);
         rs = Resolve.instance(context);
         make = TreeMaker.instance(context);
         types = Types.instance(context);
-        Options options = Options.instance(context);
-        useProxy = options.isSet("useProxy");
+        this.analyzer = makeAnalyzer();
+    }
+    
+    protected abstract LambdaAnalyzer makeAnalyzer();
+    // </editor-fold>
+
+    // <editor-fold defaultstate="collapsed" desc="visitor methods">
+    @Override
+    public <T extends JCTree> T translate(T tree) {
+        TranslationContext<?> newContext = contextMap.get(tree);
+        return translate(tree, newContext != null ? newContext : context);
+    }
+    
+    public <T extends JCTree> T translate(T tree, TranslationContext<?> newContext) {
+        TranslationContext<?> prevContext = context;
+        try {
+            context = newContext;
+            return super.translate(tree);
+        }
+        finally {
+            context = prevContext;
+        }
+    }
+
+    public <T extends JCTree> List<T> translate(List<T> trees, TranslationContext<?> newContext) {
+        ListBuffer<T> buf = ListBuffer.lb();
+        for (T tree : trees) {
+            buf.append(translate(tree, newContext));
+        }
+        return buf.toList();
     }
 
     public JCTree translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
         this.make = make;
         this.attrEnv = env;
+        this.context = null;
+        this.contextMap = new HashMap<JCTree, TranslationContext<?>>();
         return translate(cdef);
     }
+    
+    @Override
+    public void visitClassDef(JCClassDecl tree) {
+        if (tree.sym.owner.kind == PCK) {
+            trans_static = ListBuffer.lb();
+            //analyze class
+            analyzer.analyzeClass(tree);
+        }
+        ListBuffer<JCTree> prevTranslatedInstance = trans_instance;
+        try {
+            trans_instance = ListBuffer.lb();
+            super.visitClassDef(tree);
+            if (tree.sym.owner.kind == PCK) {
+                //if this is a toplevel class, add all translated statics here
+                tree.defs = tree.defs.appendList(trans_static.toList());
+                for (JCTree lambda : trans_static) {
+                    tree.sym.members().enter(((JCMethodDecl)lambda).sym);
+                }
+            }
+            //add all translated instance methods here
+            tree.defs = tree.defs.appendList(trans_instance.toList());
+            for (JCTree lambda : trans_instance) {
+                tree.sym.members().enter(((JCMethodDecl)lambda).sym);
+            }
+            result = tree;
+        }
+        finally {
+            trans_instance = prevTranslatedInstance;
+        }
+    }
+    
+    @Override
+    public void visitIdent(JCIdent tree) {
+        if (context == null || !analyzer.lambdaSymbolFilter.accepts(tree.sym)) {
+            super.visitIdent(tree);
+        } else {
+            LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context;
+            if (lambdaContext.getSymbolMap(PARAM).containsKey(tree.sym)) {
+                Symbol translatedSym = lambdaContext.getSymbolMap(PARAM).get(tree.sym);
+                result = make.Ident(translatedSym).setType(tree.type);
+            } 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(CAPTURED_VAR).containsKey(tree.sym)) {
+                Symbol translatedSym = lambdaContext.getSymbolMap(CAPTURED_VAR).get(tree.sym);
+                result = make.Ident(translatedSym).setType(tree.type);
+            } else {
+                if (tree.sym.owner.kind == Kinds.TYP) {
+                    for (Map.Entry<Symbol, Symbol> encl_entry : lambdaContext.getSymbolMap(CAPTURED_THIS).entrySet()) {
+                        if (tree.sym.isMemberOf((ClassSymbol)encl_entry.getKey(), types)) {
+                            JCExpression enclRef = make.Ident(encl_entry.getValue());
+                            result = tree.sym.name == names._this ?
+                                    enclRef.setType(tree.type) :
+                                    make.Select(enclRef, tree.sym).setType(tree.type);
+                            return;
+                        }
+                    }
+                }
+                //access to untranslated symbols (i.e. compile-time constants,
+                //members defined inside the lambda body, etc.) )
+                super.visitIdent(tree);
+            }
+        }
+    }
+    
+    @Override
+    public void visitSelect(JCFieldAccess tree) {
+        LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context;
+        if (lambdaContext != null && analyzer.lambdaSymbolFilter.accepts(tree.sym) &&
+                tree.name == names._this &&
+                lambdaContext.getSymbolMap(CAPTURED_THIS).containsKey(tree.selected.type.tsym)) {
+            JCExpression selected = translate(tree.selected);
+            result = make.Ident(lambdaContext.getSymbolMap(CAPTURED_THIS).get(selected.type.tsym));
+        } else {
+            super.visitSelect(tree);
+        }
+    }
 
     @Override
-    public void visitReference(JCMemberReference tree) {
-        result = useProxy ?
-            makeMethodHandleWrapperProxy(tree, tree.type, null, false) :
-            makeMethodHandleWrapper292(tree, tree.type);
+    public void visitVarDef(JCVariableDecl tree) {
+        LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context;
+        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 {
+            super.visitVarDef(tree);
+        }
     }
+    // </editor-fold>
 
+    // <editor-fold defaultstate="collapsed" desc="Translation helper methods">
     /**
      * Generate desugared code for the lambda body; for expression lambdas
      * a synthetic return statement might be added (if lambda can complete
      * normally). Also, a return statement is added if the return type of
      * he SAM descriptor is 'java.lang.Void' and the lambda expression is 'void'.
      */
-    JCBlock makeLambdaBody(JCLambda tree) {
+    JCBlock makeLambdaBody(JCLambda tree, Type restype) {
         JCReturn defaultRet = null;
         if (tree.canCompleteNormally &&
-                types.isSameType(tree.sym.type.getReturnType(), types.boxedClass(syms.voidType).type)) {
+                types.isSameType(restype, types.boxedClass(syms.voidType).type)) {
             //there's no return statement and the lambda (possibly inferred)
             //return type is java.lang.Void; sets the NEEDS_RETURN flag in
             //order to tell code generation to emit a synthetic return statement
@@ -110,114 +246,21 @@
         }
         return body;
     }
-
-    /**
-     * Create a wrapper instance around a method handle using an internal API
-     * leveraging dynamic proxy classes. This routine handles recursive bodies
-     * (needed to support lambda that calls themselves) - as well as synthetic
-     * arguments that are bound to the underlying method handle.
-     */
-    JCExpression makeMethodHandleWrapperProxy(JCMemberReference mref, Type type, List<JCExpression> args, boolean recursive) {
-        List<Type> argtypes = List.of(types.erasure(syms.classType),
-                syms.methodHandleType, syms.booleanType, new ArrayType(syms.objectType, syms.arrayClass));
-        
-        Symbol msym = rs.resolveInternalMethod(mref.pos(), attrEnv, syms.proxyHelper,
-                names.makeProxy, argtypes, List.<Type>nil());
-
-        JCFieldAccess qualifier = make.Select(make.QualIdent(syms.proxyHelper.tsym), names.makeProxy);
-        qualifier.sym = msym;
-        qualifier.type = msym.type;
-
-        List<JCExpression> proxyCallArgs = List.of(Class(type), mref,
-                make.Literal(TypeTags.BOOLEAN, recursive ? 1 : 0).setType(syms.booleanType));
-        if (args != null) {
-            proxyCallArgs = proxyCallArgs.appendList(args);
-        }
-        JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, proxyCallArgs, false);
-        proxyCall.varargsElement = syms.objectType;
-        proxyCall.type = types.erasure(qualifier.type);
-        return proxyCall;
+    
+    MethodSymbol makeSyntheticMethod(long flags, String name, Type type, Symbol owner) {
+        return new MethodSymbol(flags, names.fromString(name), type, owner);
     }
 
-    JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName, List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs) {
-        List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
-                                         syms.stringType,
-                                         syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
+    MethodSymbol makeSyntheticMethod(long flags, Name name, Type type, Symbol owner) {
+        return new MethodSymbol(flags | SYNTHETIC, name, type, owner);
+    }
 
-        Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
-                bsmName, bsm_staticArgs, List.<Type>nil());
+    VarSymbol makeSyntheticVar(long flags, String name, Type type, Symbol owner) {
+        return makeSyntheticVar(flags, names.fromString(name), type, owner);
+    }
 
-        DynamicMethodSymbol dynSym =
-                new DynamicMethodSymbol(names.lambda,
-                                        syms.noSymbol,
-                                        bsm.isStatic() ? ClassFile.REF_invokeStatic : ClassFile.REF_invokeVirtual,
-                                        (MethodSymbol)bsm,
-                                        indyType,
-                                        staticArgs.toArray());
-
-        JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
-        qualifier.sym = dynSym;
-        qualifier.type = indyType.getReturnType();
-
-        JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, indyArgs, false);
-        proxyCall.type = indyType.getReturnType();
-        return proxyCall;
-    }
-    //where
-        List<Type> bsmStaticArgToTypes(List<Object> args) {
-            ListBuffer<Type> argtypes = ListBuffer.lb();
-            for (Object arg : args) {
-                argtypes.append(bsmStaticArgToType(arg));
-            }
-            return argtypes.toList();
-        }
-
-        Type bsmStaticArgToType(Object arg) {
-            Assert.checkNonNull(arg);
-            if (arg instanceof ClassSymbol) {
-                return syms.classType;
-            } else if (arg instanceof Integer) {
-                return syms.intType;
-            } else if (arg instanceof Long) {
-                return syms.longType;
-            } else if (arg instanceof Float) {
-                return syms.floatType;
-            } else if (arg instanceof Double) {
-                return syms.doubleType;
-            } else if (arg instanceof String) {
-                return syms.stringType;
-            } else if (arg instanceof Pool.MemberReference) {
-                return syms.methodHandleType;
-            } else if (arg instanceof MethodType) {
-                return syms.methodTypeType;
-            } else {
-                Assert.error("bad static arg " + arg.getClass());
-                return null;
-            }
-        }
-
-    /**
-     * Create a wrapper instance around a method handle using 292 API
-     * (MethodHandleProxies). This variant is slightly more unstable than
-     * the one using internal API - it also does not offer support for
-     * recursive method handles/bound arguments list.
-     */
-    JCExpression makeMethodHandleWrapper292(JCMemberReference mref, Type type) {
-        List<Type> argtypes = List.of(types.erasure(syms.classType),
-                syms.methodHandleType);
-
-        Symbol msym = rs.resolveInternalMethod(mref.pos(), attrEnv, syms.methodHandleProxies,
-                names.asInterfaceInstance, argtypes, List.<Type>nil());
-
-        JCFieldAccess qualifier =
-                make.Select(make.QualIdent(syms.methodHandleProxies.tsym), names.asInterfaceInstance);
-        qualifier.sym = msym;
-        qualifier.type = msym.type;
-
-        JCMethodInvocation proxyCall =
-                make.Apply(List.<JCExpression>nil(), qualifier, List.of(Class(type), mref), false);
-        proxyCall.type = types.erasure(qualifier.type);
-        return proxyCall;
+    VarSymbol makeSyntheticVar(long flags, Name name, Type type, Symbol owner) {
+        return new VarSymbol(flags | SYNTHETIC, name, type, owner);
     }
 
     /**
@@ -243,4 +286,427 @@
     JCExpression Array(Type elemtype, JCExpression... elems) {
         return make.NewArray(make.Type(elemtype), List.<JCExpression>nil(), List.from(elems)).setType(new ArrayType(elemtype, syms.arrayClass));
     }
+    // </editor-fold>
+    
+    // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
+    /*
+     * This visitor collects information about translation of a lambda expression.
+     * More specifically, it keeps track of the enclosing contexts and captured locals
+     * accessed by the lambda being translated (as well as other useful info).
+     */
+    protected abstract class LambdaAnalyzer extends TreeScanner {
+
+        class Frame {
+            final JCTree tree;
+            List<Symbol> locals;
+
+            public Frame(JCTree tree) {
+                this.tree = tree;
+            }
+
+            void addLocal(Symbol sym) {
+                if (locals == null) {
+                    locals = List.nil();
+                }
+                locals = locals.prepend(sym);
+            }
+        }
+
+        /** the frame stack - used to reconstruct translation info about enclosing scopes */
+        List<Frame> frameStack;
+
+        /** pending local variable with lambda initializer (can be used for recursion) */
+        Symbol self = null;
+    
+        abstract TranslationContext makeLambdaContext(JCLambda tree);
+        
+        abstract TranslationContext makeReferenceContext(JCMemberReference tree);
+        
+        protected void analyzeClass(JCClassDecl tree) {
+            self = null;
+            frameStack = List.nil();
+            contextMap = new HashMap<JCTree, TranslationContext<?>>();
+            scan(tree);
+        }
+
+        @Override
+        public void visitClassDef(JCClassDecl tree) {
+            List<Frame> prevStack = frameStack;
+            try {
+                if (frameStack.nonEmpty() && frameStack.head.tree.getTag() == JCTree.LAMBDA) {
+                    tree.sym.owner = owner();
+                    ((ClassType)tree.sym.type).setEnclosingType(Type.noType);
+                }
+                frameStack = frameStack.prepend(new Frame(tree));
+                super.visitClassDef(tree);
+            }
+            finally {
+                frameStack = prevStack;
+            }
+        }
+
+        /**
+         * Return a valid owner given the current declaration stack
+         * (required to skip synthetic lambda symbols)
+         */
+        Symbol owner() {
+            for (Frame block : frameStack) {
+                switch (block.tree.getTag()) {
+                    case JCTree.CLASSDEF:
+                        return ((JCClassDecl)block.tree).sym;
+                    case JCTree.METHODDEF:
+                        return ((JCMethodDecl)block.tree).sym;
+                }
+            }
+            Assert.error();
+            return null;
+        }
+
+        /**
+         * Return the declaration corresponding to a symbol in the enclosing
+         * scope; the depth parameter is used to filter out symbols defined
+         * in nested scopes (which do not need to undergo capture).
+         */
+        JCTree capturedDecl(int depth, Symbol sym) {
+            int currentDepth = frameStack.size() - 1;
+            for (Frame block : frameStack) {
+                switch (block.tree.getTag()) {
+                    case JCTree.CLASSDEF:
+                        ClassSymbol clazz = ((JCClassDecl)block.tree).sym;
+                        if (sym.isMemberOf(clazz, types)) {
+                            return currentDepth > depth ? null : block.tree;
+                        }
+                        break;
+                    case JCTree.BLOCK:
+                    case JCTree.METHODDEF:
+                    case JCTree.LAMBDA:
+                        if (block.locals != null && block.locals.contains(sym)) {
+                            return currentDepth > depth ? null : block.tree;
+                        }
+                        break;
+                    default:
+                        Assert.error("bad decl kind " + block.tree.getTag());
+                }
+                currentDepth--;
+            }
+            return null;
+        }
+        
+        TranslationContext<?> context() {
+            for (Frame frame : frameStack) {
+                TranslationContext<?> context = contextMap.get(frame.tree);
+                if (context != null) {
+                    return context;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public void visitReference(JCMemberReference tree) {
+            contextMap.put(tree, makeReferenceContext(tree));
+        }
+
+        @Override
+        public void visitLambda(JCLambda tree) {
+            List<Frame> prevStack = frameStack;
+            try {
+                LambdaTranslationContext context = (LambdaTranslationContext)makeLambdaContext(tree);
+                frameStack = frameStack.prepend(new Frame(tree));
+                for (JCVariableDecl param : tree.params) {
+                    context.addSymbol(param.sym, PARAM);
+                    frameStack.head.addLocal(param.sym);
+                }
+                contextMap.put(tree, context);
+                scan(tree.body);
+            }
+            finally {
+                frameStack = prevStack;
+            }
+        }
+
+        @Override
+        public void visitIdent(JCIdent tree) {
+            if (context() == null || !lambdaSymbolFilter.accepts(tree.sym)) {
+                super.visitIdent(tree);
+            } else {
+                if (tree.sym.kind == VAR &&
+                        tree.sym.owner.kind == MTH &&
+                        tree.type.constValue() == null) {
+                    TranslationContext<?> localContext = context();
+                    while (localContext != null) {
+                        if (localContext.tree.getTag() == JCTree.LAMBDA) {
+                            JCTree block = capturedDecl(localContext.depth, tree.sym);
+                            if (block == null) break;
+                            ((LambdaTranslationContext)localContext).addSymbol(tree.sym, CAPTURED_VAR);
+                        }
+                        localContext = localContext.prev;
+                    }
+                } else if (tree.sym.owner.kind == TYP) {
+                    TranslationContext<?> localContext = context();
+                    while (localContext != null) {
+                        if (localContext.tree.getTag() == JCTree.LAMBDA) {
+                            JCClassDecl clazz = (JCClassDecl)capturedDecl(localContext.depth, tree.sym);
+                            if (clazz == null) break;
+                            ((LambdaTranslationContext)localContext).addSymbol(clazz.sym, CAPTURED_THIS);
+                        }
+                        localContext = localContext.prev;
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void visitSelect(JCFieldAccess tree) {
+            if (context() != null && lambdaSymbolFilter.accepts(tree.sym) && tree.name == names._this) {
+                TranslationContext<?> localContext = context();
+                while (localContext != null) {
+                    if (localContext.tree.getTag() == JCTree.LAMBDA) {
+                        JCClassDecl clazz = (JCClassDecl)capturedDecl(localContext.depth, tree.sym);
+                        if (clazz == null) break;
+                        ((LambdaTranslationContext)localContext).addSymbol(clazz.sym, CAPTURED_THIS);
+                    }
+                    localContext = localContext.prev;
+                }
+                scan(tree.selected);
+            } else {
+                super.visitSelect(tree);
+            }
+        }
+
+        @Override
+        public void visitBlock(JCBlock tree) {
+            List<Frame> prevStack = frameStack;
+            try {
+                if (frameStack.nonEmpty() && frameStack.head.tree.getTag() == JCTree.CLASSDEF) {
+                    frameStack = frameStack.prepend(new Frame(tree));
+                }
+                super.visitBlock(tree);
+            }
+            finally {
+                frameStack = prevStack;
+            }
+        }
+
+        @Override
+        public void visitMethodDef(JCMethodDecl tree) {
+            List<Frame> prevStack = frameStack;
+            try {
+                frameStack = frameStack.prepend(new Frame(tree));
+                super.visitMethodDef(tree);
+            }
+            finally {
+                frameStack = prevStack;
+            }
+        }
+
+        @Override
+        public void visitVarDef(JCVariableDecl tree) {
+            if (frameStack.head.tree.getTag() == JCTree.LAMBDA) {
+                ((LambdaTranslationContext)context()).addSymbol(tree.sym, LOCAL_VAR);
+            }
+            Symbol prevSelf = self;
+            try {
+                if (tree.init != null &&
+                        tree.init.getTag() == JCTree.LAMBDA) {
+                    self = tree.sym;
+                }
+                if (tree.sym.owner.kind == MTH) {
+                    frameStack.head.addLocal(tree.sym);
+                }
+                super.visitVarDef(tree);
+            }
+            finally {
+                self = prevSelf;
+            }
+        }
+        
+        /**
+         *  This is used to filter out those identifiers that needs to be adjusted
+         *  when translating away lambda expressions
+         */
+        protected final Filter<Symbol> lambdaSymbolFilter = new Filter<Symbol>() {
+            public boolean accepts(Symbol sym) {
+                return (sym.kind == VAR || sym.kind == MTH) &&
+                        !sym.isStatic() &&
+                        sym.name != names._super && sym.name != names.init;
+            }
+        };
+        
+        /**
+         * This class is used to store important information regarding translation of
+         * lambda expression/method references (see subclasses).
+         */
+        protected abstract class TranslationContext<T extends JCTree> {
+
+            /** the underlying (untranslated) tree */
+            T tree;
+
+            /** points to the adjusted enclosing scope in which this lambda/mref expression occurs */
+            Symbol owner;        
+
+            /** the depth of this lambda expression in the frame stack */
+            int depth;
+
+            /** the enclosing translation context (set for nested lambdas/mref) */
+            TranslationContext<?> prev;
+
+            TranslationContext(T tree) {
+                this.tree = tree;
+                this.owner = owner();
+                this.depth = frameStack.size() - 1;
+                this.prev = context();
+            }
+        }
+
+        /**
+         * This class retains all the useful information about a lambda expression;
+         * the contents of this class are filled by the LambdaAnalyzer visitor,
+         * and the used by the main translation routines in order to adjust references
+         * to captured locals/members, etc.
+         */
+        protected abstract class LambdaTranslationContext extends TranslationContext<JCLambda> {
+
+            /** variable in the enclosing context to which this lambda is assigned */
+            Symbol self;
+
+            /** map from original to translated lambda parameters */
+            private Map<Symbol, Symbol> lambdaParams = new LinkedHashMap<Symbol, Symbol>();
+
+            /** map from original to translated lambda locals */
+            private Map<Symbol, Symbol> lambdaLocals = new LinkedHashMap<Symbol, Symbol>();
+
+            /** map from variables in enclosing scope to translated synthetic parameters */
+            private Map<Symbol, Symbol> capturedLocals  = new LinkedHashMap<Symbol, Symbol>();
+
+            /** map from class symbols to translated synthetic parameters (for captured member access) */
+            private Map<Symbol, Symbol> capturedThis = new LinkedHashMap<Symbol, Symbol>();
+
+            protected LambdaTranslationContext(JCLambda tree) {
+                super(tree);
+                this.self = LambdaAnalyzer.this.self;
+            }
+
+            protected abstract Symbol translate(String name, Symbol sym, LambdaSymbolKind skind);
+
+            /**
+             * Does the lambda associated with this context refers to itself?
+             */
+            protected boolean isRecursive() {
+                return self != null &&
+                        capturedLocals.containsKey(self);
+            }
+
+            protected void addSymbol(Symbol sym, LambdaSymbolKind skind) {
+                Map<Symbol, Symbol> transMap = null;
+                String preferredName;
+                switch (skind) {
+                    case CAPTURED_THIS:
+                        transMap = capturedThis;
+                        preferredName = "encl$" + capturedThis.size();
+                        break;
+                    case CAPTURED_VAR:
+                        transMap = capturedLocals;
+                        preferredName = "cap$" + capturedLocals.size();
+                        break;
+                    case LOCAL_VAR:
+                        transMap = lambdaLocals;
+                        preferredName = sym.name.toString();
+                        break;
+                    case PARAM:
+                        transMap = lambdaParams;
+                        preferredName = sym.name.toString();
+                        break;
+                    default: throw new AssertionError();
+                }
+                if (!transMap.containsKey(sym))
+                    transMap.put(sym, translate(preferredName, sym, skind));
+            }
+
+            protected Map<Symbol, Symbol> getSymbolMap(LambdaSymbolKind... skinds) {
+                LinkedHashMap<Symbol, Symbol> translationMap = new LinkedHashMap<Symbol, Symbol>();
+                for (LambdaSymbolKind skind : skinds) {
+                    switch (skind) {
+                        case CAPTURED_THIS:
+                            translationMap.putAll(capturedThis);
+                            break;
+                        case CAPTURED_VAR:
+                            translationMap.putAll(capturedLocals);
+                            break;
+                        case LOCAL_VAR:
+                            translationMap.putAll(lambdaLocals);
+                            break;
+                        case PARAM:
+                            translationMap.putAll(lambdaParams);
+                            break;
+                        default: throw new AssertionError();
+                    }
+                }
+                return translationMap;
+            }
+        }
+
+        /**
+         * This class retains all the useful information about a method reference;
+         * the contents of this class are filled by the LambdaAnalyzer visitor,
+         * and the used by the main translation routines in order to adjust method
+         * references (i.e. in case a bridge is needed)
+         */
+        protected abstract class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
+
+            protected ReferenceTranslationContext(JCMemberReference tree) {
+                super(tree);
+            }
+
+            /**
+             * Is this an unbound reference? An unbound reference is either a
+             * (i) instance method reference with static qualifier or a (ii) inner
+             * class constructor reference
+             */
+            boolean isUnbound() {
+                return tree.getMode() == ReferenceMode.INVOKE ?
+                    (!tree.sym.isStatic() && TreeInfo.isStaticSelector(tree.getQualifierExpression(), names)) :
+                    (tree.sym.owner.type.getEnclosingType() != Type.noType);
+            }
+
+            /**
+             * Is this an instance method reference with a non-static qualifier?
+             */
+            boolean isInstanceRef() {
+                return tree.getMode() == ReferenceMode.INVOKE &&
+                        !TreeInfo.isStaticSelector(tree.getQualifierExpression(), names) &&
+                        !tree.sym.isStatic();
+            }
+
+            /**
+             * Is this a static reference with a non-static qualifier (which needs
+             * to be evaluated separately) ?
+             */
+            boolean needsReceiverEval() {
+                return tree.getMode() == ReferenceMode.INVOKE &&
+                    !TreeInfo.isStaticSelector(tree.getQualifierExpression(), names) &&
+                    tree.sym.isStatic();
+            }
+
+            /**
+             * Is this a static reference with a non-static qualifier (which needs
+             * to be evaluated separately) ?
+             */
+            boolean isSpecial() {
+                Name name = TreeInfo.name(tree.getQualifierExpression());
+                return !tree.sym.isStatic() &&
+                        name != null &&
+                        (name == names._super || name == names._this);
+            }
+        }
+        // </editor-fold>
+    }
+    // </editor-fold>
+
+    protected enum LambdaSymbolKind {
+        CAPTURED_VAR,
+        CAPTURED_THIS,
+        LOCAL_VAR,
+        PARAM;
+    }
 }
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Oct 26 16:41:55 2011 +0100
@@ -2139,17 +2139,9 @@
     }
 
     Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t, boolean isSuperCall) {
-        final Type thisType;
-        if ((t.tsym.owner.kind & (MTH|VAR)) != 0) {
-            do {
-                //lambda should never be picked as implicit this
-                t = t.getEnclosingType();
-            }
-            while ((t.tsym.flags() & LAMBDA) != 0);
-            thisType = resolveSelf(pos, env, t.tsym, names._this).type;
-        } else {
-            thisType = resolveSelfContaining(pos, env, t.tsym, isSuperCall).type;
-        }
+        Type thisType = (((t.tsym.owner.kind & (MTH|VAR)) != 0)
+                 ? resolveSelf(pos, env, t.getEnclosingType().tsym, names._this)
+                 : resolveSelfContaining(pos, env, t.tsym, isSuperCall)).type;
         if (env.info.isSelfCall && thisType.tsym == env.enclClass.sym)
             log.error(pos, "cant.ref.before.ctor.called", "this");
         return thisType;
--- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Wed Oct 26 16:41:55 2011 +0100
@@ -455,11 +455,11 @@
         result = tree;
     }
 
-    Symbol currentMethod = null;
+    JCTree currentMethod = null;
     public void visitMethodDef(JCMethodDecl tree) {
-        Symbol previousMethod = currentMethod;
+        JCTree previousMethod = currentMethod;
         try {
-            currentMethod = tree.sym;
+            currentMethod = tree;
             tree.restype = translate(tree.restype, null);
             tree.typarams = List.nil();
             tree.params = translateVarDefs(tree.params);
@@ -524,10 +524,10 @@
     }
 
     public void visitLambda(JCLambda tree) {
-        Symbol prevMethod = currentMethod;
+        JCTree prevMethod = currentMethod;
         Type prevPt = pt;
         try {
-            currentMethod = tree.sym;
+            currentMethod = tree;
             pt = null;
             tree.type = erasure(tree.type);
             super.visitLambda(tree);
@@ -589,7 +589,10 @@
     }
 
     public void visitReturn(JCReturn tree) {
-        tree.expr = translate(tree.expr, currentMethod.erasure(types).getReturnType());
+        Type methType = tree.getTag() == JCTree.LAMBDA ?
+                types.findDescriptor(((JCLambda)currentMethod).targetType) :
+                currentMethod.type;
+        tree.expr = translate(tree.expr, types.erasure(methType).getReturnType());
         result = tree;
     }
 
--- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Oct 26 16:41:55 2011 +0100
@@ -24,10 +24,6 @@
  */
 
 package com.sun.tools.javac.jvm;
-import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
-import java.util.*;
-
-import javax.lang.model.element.ElementKind;
 
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -42,7 +38,8 @@
 import com.sun.tools.javac.jvm.Items.*;
 import com.sun.tools.javac.jvm.Pool.*;
 import com.sun.tools.javac.tree.JCTree.*;
-import java.lang.ref.Reference;
+
+import java.util.*;
 
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.*;
@@ -125,7 +122,6 @@
             : options.isSet(G_CUSTOM, "vars");
         genCrt = options.isSet(XJCOV);
         debugCode = options.isSet("debugcode");
-        allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
 
         generateIproxies =
             target.requiresIproxy() ||
@@ -162,7 +158,6 @@
     private final boolean varDebugInfo;
     private final boolean genCrt;
     private final boolean debugCode;
-    private final boolean allowInvokedynamic;
 
     /** Default limit of (approximate) size of finalizer to inline.
      *  Zero means always use jsr.  100 or greater means never use
@@ -2192,72 +2187,8 @@
     }
 
     public void visitReference(JCMemberReference tree) {
-        Symbol refSym = tree.sym;
-        final boolean isStatic = refSym.isStatic();
-        JCExpression base = tree.expr;
-        switch (tree.mode) {
-            case INVOKE:
-                refSym = binaryQualifier(refSym, base.type);
-                refSym = Pool.delegateSymbol((MethodSymbol)refSym);
-                break;
-            case NEW:
-                refSym = Pool.delegateSymbol((MethodSymbol)refSym);
-                break;
-            default:
-                throw new AssertionError();
-        }
-        if (base != null && TreeInfo.isStaticSelector(base, names)) {
-            base = null;  // ignore a type prefix, e.g., String.valueOf
-        }
-        if (base != null && isStatic) {
-            // Evaluate the expression and then ignore it.
-            if (base.getTag() != JCTree.IDENT) {
-                //System.out.println("  executable base: "+base);
-                genExpr(base, base.type).exec();
-            }
-            base = null;
-        }
-
-        MemberReference refValue = new MemberReference(computeRefKind(tree), refSym);
-        Item con = items.makeImmediateItem(syms.methodHandleType, refValue);
-        if (base == null) {
-            result = con;  // it's just the pure constant
-        } else {
-            // Execute conMH.bindTo(baseExpr)
-            //System.out.println("Gen: bound MH base="+base);
-            con.load();
-            genExpr(base, base.type).load();
-            callMethod(tree.pos(), syms.methodHandleType, names.bindTo, List.of(syms.objectType), false);
-            result = items.makeStackItem(syms.methodHandleType);
-        }
-    }
-
-    private int computeRefKind(JCMemberReference tree) {
-        boolean isStatic = tree.sym.isStatic();
-        switch (tree.mode) {
-            case INVOKE:
-            {
-                boolean isInterface = tree.sym.owner.isInterface();
-                int refKind = MemberReference.methodRefKind(isStatic, isInterface);
-                if (refKind != ClassFile.REF_invokeVirtual)
-                    return refKind;
-                if ((tree.sym.flags() & PRIVATE) != 0)
-                    return ClassFile.REF_invokeSpecial;
-                JCExpression base = tree.expr;
-                if (base != null) {
-                    Symbol bsym = TreeInfo.symbol(base);
-                    // Are we selecting via super?
-                    if (bsym != null && bsym.name == names._super)
-                        return ClassFile.REF_invokeSpecial;
-                }
-                return ClassFile.REF_invokeVirtual;
-            }
-            case NEW:
-                // JVM always supplies a freshly built receiver
-                return ClassFile.REF_newInvokeSpecial;
-            default:
-                throw new AssertionError();
-        }
+        //should have been desugared in LambdaTranslator
+        throw new AssertionError();
     }
 
     public void visitLiteral(JCLiteral tree) {
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Wed Oct 26 16:41:55 2011 +0100
@@ -37,7 +37,6 @@
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.code.Type.MethodType;
 import com.sun.tools.javac.code.Scope.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.source.tree.*;
@@ -1461,7 +1460,6 @@
         }
         public List<JCVariableDecl> params;
         public JCTree body;
-        public Symbol sym;
         public Type targetType;
         public boolean canCompleteNormally = true;
         public List<Type> inferredThrownTypes;
--- a/test/tools/javac/lambda/BadBreakContinue.out	Fri Sep 09 17:56:23 2011 +0100
+++ b/test/tools/javac/lambda/BadBreakContinue.out	Wed Oct 26 16:41:55 2011 +0100
@@ -2,8 +2,8 @@
 BadBreakContinue.java:38:21: compiler.err.cont.inside.lambda
 BadBreakContinue.java:40:27: compiler.err.break.inside.lambda
 BadBreakContinue.java:41:27: compiler.err.cont.inside.lambda
-BadBreakContinue.java:46:29: compiler.err.undef.label: loop
-BadBreakContinue.java:47:29: compiler.err.undef.label: loop
-BadBreakContinue.java:49:35: compiler.err.undef.label: loop
-BadBreakContinue.java:50:35: compiler.err.undef.label: loop
+BadBreakContinue.java:46:29: compiler.err.break.inside.lambda
+BadBreakContinue.java:47:29: compiler.err.cont.inside.lambda
+BadBreakContinue.java:49:35: compiler.err.break.inside.lambda
+BadBreakContinue.java:50:35: compiler.err.cont.inside.lambda
 8 errors
--- a/test/tools/javac/lambda/BadStatementInLambda02.out	Fri Sep 09 17:56:23 2011 +0100
+++ b/test/tools/javac/lambda/BadStatementInLambda02.out	Wed Oct 26 16:41:55 2011 +0100
@@ -1,2 +1,2 @@
-BadStatementInLambda02.java:37:42: compiler.err.cant.resolve: kindname.class, NonExistentClass, , 
+BadStatementInLambda02.java:37:42: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, BadStatementInLambda02, null)
 1 error
--- a/test/tools/javac/lambda/LambdaCapture01.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/test/tools/javac/lambda/LambdaCapture01.java	Wed Oct 26 16:41:55 2011 +0100
@@ -56,8 +56,8 @@
     //Simple local capture
     void test1() {
         final int N = 1;
-        int x = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + N, 3);
-        assertTrue(4 == x);
+        int res = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + N, 3);
+        assertTrue(4 == res);
     }
 
     //Local capture with multiple scopes (anon class)
@@ -66,8 +66,8 @@
         new Tester() {
             public void test() {
                 final int M = 2;
-                int x = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + N + M, 3);
-                assertTrue(6 == x);
+                int res = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + N + M, 3);
+                assertTrue(6 == res);
             }
         }.test();
     }
@@ -78,8 +78,8 @@
         class MyTester implements Tester {
             public void test() {
                 final int M = 2;
-                int x = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + N + M, 3);
-                assertTrue(6 == x);
+                int res = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + N + M, 3);
+                assertTrue(6 == res);
             }
         }
         new MyTester().test();
@@ -88,10 +88,10 @@
     //access to field from enclosing scope
     void test4() {
         final int N = 4;
-        int x1 = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + n + N, 3);
-        assertTrue(12 == x1);
-        int x2 = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + LambdaCapture01.this.n + N, 3);
-        assertTrue(12 == x2);
+        int res1 = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + n + N, 3);
+        assertTrue(12 == res1);
+        int res2 = LambdaCapture01.<Integer,Integer>exec((Integer x) -> x + LambdaCapture01.this.n + N, 3);
+        assertTrue(12 == res2);
     }
 
     public static void main(String[] args) {
--- a/test/tools/javac/lambda/LambdaCapture02.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/test/tools/javac/lambda/LambdaCapture02.java	Wed Oct 26 16:41:55 2011 +0100
@@ -56,8 +56,8 @@
     //Simple local capture
     void test1() {
         final Integer N = 1;
-        int x = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + N, 3);
-        assertTrue(4 == x);
+        int res = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + N, 3);
+        assertTrue(4 == res);
     }
 
     //Local capture with multiple scopes (anon class)
@@ -66,8 +66,8 @@
         new Tester() {
             public void test() {
                 final Integer M = 2;
-                int x = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + N + M, 3);
-                assertTrue(6 == x);
+                int res = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + N + M, 3);
+                assertTrue(6 == res);
             }
         }.test();
     }
@@ -78,8 +78,8 @@
         class MyTester implements Tester {
             public void test() {
                 final Integer M = 2;
-                int x = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + N + M, 3);
-                assertTrue(6 == x);
+                int res = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + N + M, 3);
+                assertTrue(6 == res);
             }
         }
         new MyTester().test();
@@ -88,10 +88,10 @@
     //access to field from enclosing scope
     void test4() {
         final Integer N = 4;
-        int x1 = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + n + N, 3);
-        assertTrue(12 == x1);
-        int x2 = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + LambdaCapture02.this.n + N, 3);
-        assertTrue(12 == x2);
+        int res1 = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + n + N, 3);
+        assertTrue(12 == res1);
+        int res2 = LambdaCapture02.<Integer,Integer>exec((Integer x) -> x + LambdaCapture02.this.n + N, 3);
+        assertTrue(12 == res2);
     }
 
     public static void main(String[] args) {
--- a/test/tools/javac/lambda/LambdaCapture03.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/test/tools/javac/lambda/LambdaCapture03.java	Wed Oct 26 16:41:55 2011 +0100
@@ -61,8 +61,8 @@
                   class B {
                        void test() {
                            final Integer N3 = 3;
-                           int x = LambdaCapture03.exec((Integer x) -> x + n1 + n2 + N1 + N2 + N3, 30);
-                           assertTrue(x == 66);
+                           int res = LambdaCapture03.exec((Integer x) -> x + n1 + n2 + N1 + N2 + N3, 30);
+                           assertTrue(res == 66);
                        }
                   }
                   new B().test();
@@ -80,8 +80,8 @@
                 new Tester() {
                     public void test() {
                         final Integer N3 = 3;
-                        int x = LambdaCapture03.exec((Integer x) -> x + n1 + n2 + N1 + N2 + N3, 30);
-                        assertTrue(x == 66);
+                        int res = LambdaCapture03.exec((Integer x) -> x + n1 + n2 + N1 + N2 + N3, 30);
+                        assertTrue(res == 66);
                     }
                 }.test();
             }
--- a/test/tools/javac/lambda/LambdaConv01.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/test/tools/javac/lambda/LambdaConv01.java	Wed Oct 26 16:41:55 2011 +0100
@@ -67,8 +67,8 @@
         TU<Number, Integer> f2 = (Integer x) -> x;
         assertTrue(3 == f2.foo(3));
         //Method resolution with boxing:
-        int x = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
-        assertTrue(3 == x);
+        int res = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
+        assertTrue(3 == res);
         //Runtime exception transparency:
         try {
             LambdaConv01.<Integer,Object>exec((Object x) -> x.hashCode(), null);
@@ -86,8 +86,8 @@
         TU<Number, Integer> f2 = (Integer x) -> x;
         assertTrue(3 == f2.foo(3));
         //Method resolution with boxing:
-        int x = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
-        assertTrue(3 == x);
+        int res = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
+        assertTrue(3 == res);
         //Runtime exception transparency:
         try {
             LambdaConv01.<Integer,Object>exec((Object x) -> x.hashCode(), null);
@@ -105,8 +105,8 @@
         TU<Number, Integer> f2 = (Integer x) -> x;
         assertTrue(3 == f2.foo(3));
         //Method resolution with boxing:
-        int x = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
-        assertTrue(3 == x);
+        int res = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
+        assertTrue(3 == res);
         //Runtime exception transparency:
         try {
             LambdaConv01.<Integer,Object>exec((Object x) -> x.hashCode(), null);
@@ -124,8 +124,8 @@
         TU<Number, Integer> f2 = (Integer x) -> x;
         assertTrue(3 == f2.foo(3));
         //Method resolution with boxing:
-        int x = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
-        assertTrue(3 == x);
+        int res = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
+        assertTrue(3 == res);
         //Runtime exception transparency:
         try {
             LambdaConv01.<Integer,Object>exec((Object x) -> x.hashCode(), null);
--- a/test/tools/javac/lambda/LambdaScope01.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/test/tools/javac/lambda/LambdaScope01.java	Wed Oct 26 16:41:55 2011 +0100
@@ -55,7 +55,7 @@
 
     public void test1() {
         try {
-            int x = LambdaScope01.<Integer,Integer>exec((Integer x) -> x * hashCode(), 3);
+            int res = LambdaScope01.<Integer,Integer>exec((Integer x) -> x * hashCode(), 3);
         }
         catch (RuntimeException e) {
             assertTrue(true); //should throw
@@ -64,8 +64,8 @@
 
     public void test2() {
         final int n = 10;
-        int x = LambdaScope01.<Integer,Integer>exec((Integer x) -> x + n, 3);
-        assertTrue(13 == x);
+        int res = LambdaScope01.<Integer,Integer>exec((Integer x) -> x + n, 3);
+        assertTrue(13 == res);
     }
 
     public static void main(String[] args) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/LambdaScope04.java	Wed Oct 26 16:41:55 2011 +0100
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2011, 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
+ * @summary check that lambda cannot shadow variables from enclosing scope
+ * @compile/fail/ref=LambdaScope04.out -XDrawDiagnostics LambdaScope04.java
+ */
+
+class LambdaScope04 {
+    
+    interface SAM {
+        void m(Object o);
+    }
+    
+    static SAM field1 = field1->{}; //ok
+    static SAM field2 = param->{ Object field2 = null; }; //ok
+    
+    SAM field3 = field3->{}; //ok
+    SAM field4 = param->{ Object field4 = null; }; //ok
+    
+    {
+        Object local = null;
+        SAM s1 = local->{}; //error
+        SAM s2 = param->{ Object local = null; }; //error
+    }
+    
+    static {
+        Object local = null;
+        SAM s1 = local->{}; //error
+        SAM s2 = param->{ Object local = null; }; //error
+        SAM s3 = field1->{ Object field_2 = null; }; //ok
+    }
+    
+    void testLocalInstance() {
+        Object local = null;
+        SAM s1 = local->{}; //error
+        SAM s2 = param->{ Object local = null; }; //error
+        SAM s3 = field1->{ Object field_2 = null; }; //ok
+    }
+    
+    static void testLocalStatic() {
+        Object local = null;
+        SAM s1 = local->{}; //error
+        SAM s2 = param->{ Object local = null; }; //error
+        SAM s3 = field1->{ Object field_2 = null; }; //ok
+    }
+    
+    void testParamInstance(Object local) {
+        SAM s1 = local->{}; //error
+        SAM s2 = param->{ Object local = null; }; //error
+        SAM s3 = field1->{ Object field_2 = null; }; //ok
+    }
+    
+    static void testParamStatic(Object local) {
+        SAM s1 = local->{}; //error
+        SAM s2 = param->{ Object local = null; }; //error
+        SAM s3 = field1->{ Object field_2 = null; }; //ok
+    }
+    
+    void testForInstance() {
+        for (int local = 0; local != 0 ; local++) {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        }
+    }
+    
+    static void testForStatic(Iterable<Object> elems) {
+        for (int local = 0; local != 0 ; local++) {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        }
+    }
+    
+    void testForEachInstance(Iterable<Object> elems) {
+        for (Object local : elems) {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        }
+    }
+    
+    static void testForEachStatic(Iterable<Object> elems) {
+        for (Object local : elems) {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        }
+    }
+    
+    void testCatchInstance() {
+        try { } catch (Throwable local) {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        }
+    }
+    
+    static void testCatchStatic(Iterable<Object> elems) {
+        try { } catch (Throwable local) {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        }
+    }
+    
+    void testTWRInstance(AutoCloseable res) {
+        try (AutoCloseable local = res) {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        } finally { }
+    }
+    
+    static void testTWRStatic(AutoCloseable res) {
+        try (AutoCloseable local = res) {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        } finally { }
+    }
+    
+    void testBlockLocalInstance() {
+        Object local = null;
+        {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        }
+    }
+    
+    static void testBlockLocalStatic() {
+        Object local = null;
+        {
+            SAM s1 = local->{}; //error
+            SAM s2 = param->{ Object local = null; }; //error
+            SAM s3 = field1->{ Object field_2 = null; }; //ok
+        }
+    }
+    
+    void testSwitchLocalInstance(int i) {
+        switch (i) {
+            case 0: Object local = null;
+            default: {
+                SAM s1 = local->{}; //error
+                SAM s2 = param->{ Object local = null; }; //error
+                SAM s3 = field1->{ Object field_2 = null; }; //ok
+            }
+        }
+    }
+    
+    static void testSwitchLocalStatic(int i) {
+        switch (i) {
+            case 0: Object local = null;
+            default: {
+                SAM s1 = local->{}; //error
+                SAM s2 = param->{ Object local = null; }; //error
+                SAM s3 = field1->{ Object field_2 = null; }; //ok
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/LambdaScope04.out	Wed Oct 26 16:41:55 2011 +0100
@@ -0,0 +1,37 @@
+LambdaScope04.java:44:18: compiler.err.already.defined: local, null
+LambdaScope04.java:45:34: compiler.err.already.defined: local, null
+LambdaScope04.java:50:18: compiler.err.already.defined: local, null
+LambdaScope04.java:51:34: compiler.err.already.defined: local, null
+LambdaScope04.java:57:18: compiler.err.already.defined: local, testLocalInstance()
+LambdaScope04.java:58:34: compiler.err.already.defined: local, testLocalInstance()
+LambdaScope04.java:64:18: compiler.err.already.defined: local, testLocalStatic()
+LambdaScope04.java:65:34: compiler.err.already.defined: local, testLocalStatic()
+LambdaScope04.java:70:18: compiler.err.already.defined: local, testParamInstance(java.lang.Object)
+LambdaScope04.java:71:34: compiler.err.already.defined: local, testParamInstance(java.lang.Object)
+LambdaScope04.java:76:18: compiler.err.already.defined: local, testParamStatic(java.lang.Object)
+LambdaScope04.java:77:34: compiler.err.already.defined: local, testParamStatic(java.lang.Object)
+LambdaScope04.java:83:22: compiler.err.already.defined: local, testForInstance()
+LambdaScope04.java:84:38: compiler.err.already.defined: local, testForInstance()
+LambdaScope04.java:91:22: compiler.err.already.defined: local, testForStatic(java.lang.Iterable<java.lang.Object>)
+LambdaScope04.java:92:38: compiler.err.already.defined: local, testForStatic(java.lang.Iterable<java.lang.Object>)
+LambdaScope04.java:99:22: compiler.err.already.defined: local, testForEachInstance(java.lang.Iterable<java.lang.Object>)
+LambdaScope04.java:100:38: compiler.err.already.defined: local, testForEachInstance(java.lang.Iterable<java.lang.Object>)
+LambdaScope04.java:107:22: compiler.err.already.defined: local, testForEachStatic(java.lang.Iterable<java.lang.Object>)
+LambdaScope04.java:108:38: compiler.err.already.defined: local, testForEachStatic(java.lang.Iterable<java.lang.Object>)
+LambdaScope04.java:115:22: compiler.err.already.defined: local, testCatchInstance()
+LambdaScope04.java:116:38: compiler.err.already.defined: local, testCatchInstance()
+LambdaScope04.java:123:22: compiler.err.already.defined: local, testCatchStatic(java.lang.Iterable<java.lang.Object>)
+LambdaScope04.java:124:38: compiler.err.already.defined: local, testCatchStatic(java.lang.Iterable<java.lang.Object>)
+LambdaScope04.java:131:22: compiler.err.already.defined: local, testTWRInstance(java.lang.AutoCloseable)
+LambdaScope04.java:132:38: compiler.err.already.defined: local, testTWRInstance(java.lang.AutoCloseable)
+LambdaScope04.java:139:22: compiler.err.already.defined: local, testTWRStatic(java.lang.AutoCloseable)
+LambdaScope04.java:140:38: compiler.err.already.defined: local, testTWRStatic(java.lang.AutoCloseable)
+LambdaScope04.java:148:22: compiler.err.already.defined: local, testBlockLocalInstance()
+LambdaScope04.java:149:38: compiler.err.already.defined: local, testBlockLocalInstance()
+LambdaScope04.java:157:22: compiler.err.already.defined: local, testBlockLocalStatic()
+LambdaScope04.java:158:38: compiler.err.already.defined: local, testBlockLocalStatic()
+LambdaScope04.java:167:26: compiler.err.already.defined: local, testSwitchLocalInstance(int)
+LambdaScope04.java:168:42: compiler.err.already.defined: local, testSwitchLocalInstance(int)
+LambdaScope04.java:178:26: compiler.err.already.defined: local, testSwitchLocalStatic(int)
+LambdaScope04.java:179:42: compiler.err.already.defined: local, testSwitchLocalStatic(int)
+36 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/MethodReference30.java	Wed Oct 26 16:41:55 2011 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011, 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
+ * @summary check that non-static qualifier of static method reference is eagerly evaluated
+ */
+
+public class MethodReference30 {
+    
+    static int assertionCount = 0;
+
+    static void assertTrue(boolean cond) {
+        assertionCount++;
+        if (!cond)
+            throw new AssertionError();
+    }
+    
+    interface SAM {
+       void m();
+    }
+
+    MethodReference30() {
+        assertTrue(true);
+    }
+
+   static void m() { }
+
+   public static void main(String[] args) {
+      SAM s = new MethodReference30()#m;
+      assertTrue(assertionCount == 1);
+   }
+}
--- a/test/tools/javac/lambda/sqe/lambdaExpression/LambdaTest4.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/test/tools/javac/lambda/sqe/lambdaExpression/LambdaTest4.java	Wed Oct 26 16:41:55 2011 +0100
@@ -30,6 +30,9 @@
 
 public class LambdaTest4 {
 
+    private String thisStr;
+    private static int count = 0;
+    
     {
         ((Runnable)
             ()-> {
@@ -40,9 +43,6 @@
         ).run();
     }
 
-    private String thisStr;
-    private static int count = 0;
-
     private static void assertTrue(boolean b) {
         if(!b)
             throw new AssertionError();
--- a/test/tools/javac/lambda/sqe/methodReference/BridgeMethod.java	Fri Sep 09 17:56:23 2011 +0100
+++ b/test/tools/javac/lambda/sqe/methodReference/BridgeMethod.java	Wed Oct 26 16:41:55 2011 +0100
@@ -22,9 +22,11 @@
  */
 
 /**
+ * @ignore
  * @test
  * @summary  Test bridge methods in certain SAM conversion
- * @compile -XDuseProxy BridgeMethod.java
+ *     (the test is too fragile as it relies on the shape of the generated class)
+ * @compile BridgeMethod.java
  * @run main BridgeMethod
  */
 
@@ -66,7 +68,7 @@
         System.out.println("methods in SAM conversion of L:");
         for(Method m : methods) //Error: method void m(String) not listed
             System.out.println(m.toGenericString());
-        //assertTrue( methods.length == 2+3 ); //will be uncommented when the Proxy API problem fixed: CR 7067623
+        assertTrue( methods.length == 2+3 ); //will be uncommented when the Proxy API problem fixed: CR 7067623
 
         KM km = BridgeMethod#bar(String);
         //km.m("hi"); //will be uncommented when CR7028808 fixed