LambdaToMethod.java revision 2787:441711fd360d
137535Sdes/*
263012Sdes * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
337535Sdes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
437535Sdes *
537535Sdes * This code is free software; you can redistribute it and/or modify it
637535Sdes * under the terms of the GNU General Public License version 2 only, as
737535Sdes * published by the Free Software Foundation.  Oracle designates this
837535Sdes * particular file as subject to the "Classpath" exception as provided
937535Sdes * by Oracle in the LICENSE file that accompanied this code.
1037535Sdes *
1137535Sdes * This code is distributed in the hope that it will be useful, but WITHOUT
1237535Sdes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1337535Sdes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1437535Sdes * version 2 for more details (a copy is included in the LICENSE file that
1563012Sdes * accompanied this code).
1637535Sdes *
1737535Sdes * You should have received a copy of the GNU General Public License version
1837535Sdes * 2 along with this work; if not, write to the Free Software Foundation,
1937535Sdes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2037535Sdes *
2137535Sdes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2237535Sdes * or visit www.oracle.com if you need additional information or have any
2337535Sdes * questions.
2437535Sdes */
2537535Sdespackage com.sun.tools.javac.comp;
2637535Sdes
2737535Sdesimport com.sun.tools.javac.tree.*;
2837535Sdesimport com.sun.tools.javac.tree.JCTree.*;
2984203Sdillonimport com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
3084203Sdillonimport com.sun.tools.javac.tree.TreeMaker;
3184203Sdillonimport com.sun.tools.javac.tree.TreeTranslator;
3263236Sdesimport com.sun.tools.javac.code.Attribute;
3363236Sdesimport com.sun.tools.javac.code.Scope.WriteableScope;
3463236Sdesimport com.sun.tools.javac.code.Symbol;
3563236Sdesimport com.sun.tools.javac.code.Symbol.ClassSymbol;
3663236Sdesimport com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
3763236Sdesimport com.sun.tools.javac.code.Symbol.MethodSymbol;
3863236Sdesimport com.sun.tools.javac.code.Symbol.TypeSymbol;
3963236Sdesimport com.sun.tools.javac.code.Symbol.VarSymbol;
4063236Sdesimport com.sun.tools.javac.code.Symtab;
4163236Sdesimport com.sun.tools.javac.code.Type;
4263236Sdesimport com.sun.tools.javac.code.Type.MethodType;
4363236Sdesimport com.sun.tools.javac.code.Type.TypeVar;
4463236Sdesimport com.sun.tools.javac.code.Types;
4563236Sdesimport com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
4663236Sdesimport com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
4763236Sdesimport com.sun.tools.javac.jvm.*;
4863236Sdesimport com.sun.tools.javac.util.*;
4990267Sdesimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
5063236Sdesimport com.sun.source.tree.MemberReferenceTree.ReferenceMode;
5163236Sdes
5263236Sdesimport java.util.EnumMap;
5363236Sdesimport java.util.HashMap;
5463236Sdesimport java.util.HashSet;
5563236Sdesimport java.util.LinkedHashMap;
5663236Sdesimport java.util.Map;
5763236Sdesimport java.util.Set;
5863236Sdes
5963236Sdesimport static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*;
6063236Sdesimport static com.sun.tools.javac.code.Flags.*;
6163236Sdesimport static com.sun.tools.javac.code.Kinds.Kind.*;
6263236Sdesimport static com.sun.tools.javac.code.TypeTag.*;
6363236Sdesimport static com.sun.tools.javac.tree.JCTree.Tag.*;
6437535Sdesimport javax.lang.model.type.TypeKind;
6560737Sume
6637535Sdes/**
6763012Sdes * This pass desugars lambda expressions into static methods
6837535Sdes *
6963012Sdes *  <p><b>This is NOT part of any supported API.
7060376Sdes *  If you write code that depends on this, you do so at your own risk.
7160189Sdes *  This code and its internal interfaces are subject to change or
7237608Sdes *  deletion without notice.</b>
7337535Sdes */
7437535Sdespublic class LambdaToMethod extends TreeTranslator {
7537535Sdes
7660376Sdes    private Attr attr;
7737535Sdes    private JCDiagnostic.Factory diags;
7837535Sdes    private Log log;
7937535Sdes    private Lower lower;
8040939Sdes    private Names names;
8141862Sdes    private Symtab syms;
8237535Sdes    private Resolve rs;
8363012Sdes    private TreeMaker make;
8463012Sdes    private Types types;
8537535Sdes    private TransTypes transTypes;
8663012Sdes    private Env<AttrContext> attrEnv;
8763012Sdes
8863012Sdes    /** the analyzer scanner */
8963012Sdes    private LambdaAnalyzerPreprocessor analyzer;
9063012Sdes
9163012Sdes    /** map from lambda trees to translation contexts */
9263012Sdes    private Map<JCTree, TranslationContext<?>> contextMap;
9387317Sdes
9463012Sdes    /** current translation context (visitor argument) */
9560196Sdes    private TranslationContext<?> context;
9663012Sdes
9790267Sdes    /** info about the current class being processed */
9890267Sdes    private KlassInfo kInfo;
9963012Sdes
10088771Sdes    /** dump statistics about lambda code generation */
10163012Sdes    private boolean dumpLambdaToMethodStats;
10290267Sdes
10363012Sdes    /** force serializable representation, for stress testing **/
10463012Sdes    private final boolean forceSerializable;
10563012Sdes
10663012Sdes    /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
10797859Sdes    public static final int FLAG_SERIALIZABLE = 1 << 0;
10837535Sdes
10997858Sdes    /** Flag for alternate metafactories indicating the lambda object has multiple targets */
11097866Sdes    public static final int FLAG_MARKERS = 1 << 1;
11197858Sdes
11297866Sdes    /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
11397866Sdes    public static final int FLAG_BRIDGES = 1 << 2;
11497866Sdes
11597858Sdes    // <editor-fold defaultstate="collapsed" desc="Instantiating">
11697858Sdes    protected static final Context.Key<LambdaToMethod> unlambdaKey = new Context.Key<>();
11797858Sdes
11863281Sdes    public static LambdaToMethod instance(Context context) {
11990267Sdes        LambdaToMethod instance = context.get(unlambdaKey);
12063012Sdes        if (instance == null) {
12137535Sdes            instance = new LambdaToMethod(context);
12237535Sdes        }
12337608Sdes        return instance;
12463012Sdes    }
12537608Sdes    private LambdaToMethod(Context context) {
12637608Sdes        context.put(unlambdaKey, this);
12797859Sdes        diags = JCDiagnostic.Factory.instance(context);
12837608Sdes        log = Log.instance(context);
12990267Sdes        lower = Lower.instance(context);
13090267Sdes        names = Names.instance(context);
13197859Sdes        syms = Symtab.instance(context);
13290267Sdes        rs = Resolve.instance(context);
13390267Sdes        make = TreeMaker.instance(context);
13497859Sdes        types = Types.instance(context);
13590267Sdes        transTypes = TransTypes.instance(context);
13690267Sdes        analyzer = new LambdaAnalyzerPreprocessor();
13797859Sdes        Options options = Options.instance(context);
13890267Sdes        dumpLambdaToMethodStats = options.isSet("dumpLambdaToMethodStats");
13990267Sdes        attr = Attr.instance(context);
14090267Sdes        forceSerializable = options.isSet("forceSerializable");
14190267Sdes    }
14290267Sdes    // </editor-fold>
14397859Sdes
14490267Sdes    private class KlassInfo {
14590267Sdes
14697859Sdes        /**
14790267Sdes         * list of methods to append
14890267Sdes         */
14990267Sdes        private ListBuffer<JCTree> appendedMethodList;
15090267Sdes
15163281Sdes        /**
15290267Sdes         * list of deserialization cases
15397859Sdes         */
15497859Sdes        private final Map<String, ListBuffer<JCStatement>> deserializeCases;
155106207Sdes
15690267Sdes       /**
157106207Sdes         * deserialize method symbol
158106207Sdes         */
159106207Sdes        private final MethodSymbol deserMethodSym;
16090267Sdes
16163012Sdes        /**
16290267Sdes         * deserialize method parameter symbol
16397859Sdes         */
16437608Sdes        private final VarSymbol deserParamSym;
16537608Sdes
16637608Sdes        private final JCClassDecl clazz;
16797866Sdes
16897866Sdes        private KlassInfo(JCClassDecl clazz) {
16997866Sdes            this.clazz = clazz;
17097866Sdes            appendedMethodList = new ListBuffer<>();
17197866Sdes            deserializeCases = new HashMap<>();
17297866Sdes            MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType,
17397866Sdes                    List.<Type>nil(), syms.methodClass);
17497866Sdes            deserMethodSym = makePrivateSyntheticMethod(STATIC, names.deserializeLambda, type, clazz.sym);
17597866Sdes            deserParamSym = new VarSymbol(FINAL, names.fromString("lambda"),
17697866Sdes                    syms.serializedLambdaType, deserMethodSym);
17797866Sdes        }
17897866Sdes
17997866Sdes        private void addMethod(JCTree decl) {
18097866Sdes            appendedMethodList = appendedMethodList.prepend(decl);
181106044Sdes        }
18297866Sdes    }
18397866Sdes
18497866Sdes    // <editor-fold defaultstate="collapsed" desc="translate methods">
18537608Sdes    @Override
18637608Sdes    public <T extends JCTree> T translate(T tree) {
18763012Sdes        TranslationContext<?> newContext = contextMap.get(tree);
18897866Sdes        return translate(tree, newContext != null ? newContext : context);
18937535Sdes    }
19097859Sdes
19190267Sdes    <T extends JCTree> T translate(T tree, TranslationContext<?> newContext) {
19297859Sdes        TranslationContext<?> prevContext = context;
19390267Sdes        try {
19490267Sdes            context = newContext;
19597866Sdes            return super.translate(tree);
19697866Sdes        }
19797866Sdes        finally {
198106185Sdes            context = prevContext;
199106185Sdes        }
20097866Sdes    }
201106185Sdes
20297866Sdes    <T extends JCTree> List<T> translate(List<T> trees, TranslationContext<?> newContext) {
20397866Sdes        ListBuffer<T> buf = new ListBuffer<>();
20497866Sdes        for (T tree : trees) {
20597866Sdes            buf.append(translate(tree, newContext));
20697859Sdes        }
20797859Sdes        return buf.toList();
20890267Sdes    }
20997859Sdes
21090267Sdes    public JCTree translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
21190267Sdes        this.make = make;
21297859Sdes        this.attrEnv = env;
21390267Sdes        this.context = null;
21490267Sdes        this.contextMap = new HashMap<>();
21537535Sdes        return translate(cdef);
21663012Sdes    }
21797866Sdes    // </editor-fold>
21897866Sdes
21997866Sdes    // <editor-fold defaultstate="collapsed" desc="visitor methods">
22090267Sdes    /**
221106185Sdes     * Visit a class.
222106185Sdes     * Maintain the translatedMethodList across nested classes.
22397866Sdes     * Append the translatedMethodList to the class after it is translated.
224106185Sdes     * @param tree
22597866Sdes     */
22690267Sdes    @Override
22797859Sdes    public void visitClassDef(JCClassDecl tree) {
22897856Sdes        if (tree.sym.owner.kind == PCK) {
22997856Sdes            //analyze class
23097866Sdes            tree = analyzer.analyzeAndPreprocessClass(tree);
23197856Sdes        }
23290267Sdes        KlassInfo prevKlassInfo = kInfo;
23390267Sdes        try {
23490267Sdes            kInfo = new KlassInfo(tree);
23597866Sdes            super.visitClassDef(tree);
23690267Sdes            if (!kInfo.deserializeCases.isEmpty()) {
23797866Sdes                int prevPos = make.pos;
23837535Sdes                try {
23937535Sdes                    make.at(tree);
24037608Sdes                    kInfo.addMethod(makeDeserializeMethod(tree.sym));
24137608Sdes                } finally {
24237608Sdes                    make.at(prevPos);
24337535Sdes                }
24463012Sdes            }
24537535Sdes            //add all translated instance methods here
24697859Sdes            List<JCTree> newMethods = kInfo.appendedMethodList.toList();
24790267Sdes            tree.defs = tree.defs.appendList(newMethods);
24863012Sdes            for (JCTree lambda : newMethods) {
24997859Sdes                tree.sym.members().enter(((JCMethodDecl)lambda).sym);
25090267Sdes            }
25197859Sdes            result = tree;
25290267Sdes        } finally {
25363012Sdes            kInfo = prevKlassInfo;
25490267Sdes        }
25590267Sdes    }
25697866Sdes
25797866Sdes    /**
25890267Sdes     * Translate a lambda into a method to be inserted into the class.
25997866Sdes     * Then replace the lambda site with an invokedynamic call of to lambda
26090267Sdes     * meta-factory, which will use the lambda method.
26190267Sdes     * @param tree
26297866Sdes     */
26397866Sdes    @Override
26490267Sdes    public void visitLambda(JCLambda tree) {
26537535Sdes        LambdaTranslationContext localContext = (LambdaTranslationContext)context;
26697859Sdes        MethodSymbol sym = localContext.translatedSym;
26790267Sdes        MethodType lambdaType = (MethodType) sym.type;
26890267Sdes
26937535Sdes        {
27037535Sdes            Symbol owner = localContext.owner;
27137608Sdes            ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>();
27237608Sdes            ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>();
27337608Sdes
27437535Sdes            for (Attribute.TypeCompound tc : owner.getRawTypeAttributes()) {
27563012Sdes                if (tc.position.onLambda == tree) {
27637535Sdes                    lambdaTypeAnnos.append(tc);
27797859Sdes                } else {
27890267Sdes                    ownerTypeAnnos.append(tc);
27997866Sdes                }
28037535Sdes            }
28137535Sdes            if (lambdaTypeAnnos.nonEmpty()) {
28237608Sdes                owner.setTypeAttributes(ownerTypeAnnos.toList());
28337608Sdes                sym.setTypeAttributes(lambdaTypeAnnos.toList());
28437608Sdes            }
28537535Sdes        }
28663012Sdes
28737535Sdes        //create the method declaration hoisting the lambda body
28897859Sdes        JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
28990267Sdes                sym.name,
29063012Sdes                make.QualIdent(lambdaType.getReturnType().tsym),
29197859Sdes                List.<JCTypeParameter>nil(),
29297859Sdes                localContext.syntheticParams,
29397859Sdes                lambdaType.getThrownTypes() == null ?
29497859Sdes                    List.<JCExpression>nil() :
29590267Sdes                    make.Types(lambdaType.getThrownTypes()),
29637535Sdes                null,
29737535Sdes                null);
29837608Sdes        lambdaDecl.sym = sym;
29963012Sdes        lambdaDecl.type = lambdaType;
30037608Sdes
30163012Sdes        //translate lambda body
30297866Sdes        //As the lambda body is translated, all references to lambda locals,
30337535Sdes        //captured variables, enclosing members are adjusted accordingly
30497859Sdes        //to refer to the static method parameters (rather than i.e. acessing to
30590267Sdes        //captured members directly).
30663012Sdes        lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
30797859Sdes
30890267Sdes        //Add the method to the list of methods to be added to this class.
30990267Sdes        kInfo.addMethod(lambdaDecl);
31090267Sdes
31197859Sdes        //now that we have generated a method for the lambda expression,
31297866Sdes        //we can translate the lambda into a method reference pointing to the newly
31397859Sdes        //created method.
31490267Sdes        //
31590267Sdes        //Note that we need to adjust the method handle so that it will match the
31697859Sdes        //signature of the SAM descriptor - this means that the method reference
31790267Sdes        //should be added the following synthetic arguments:
31890267Sdes        //
31990267Sdes        // * the "this" argument if it is an instance method
32063012Sdes        // * enclosing locals captured by the lambda expression
32163012Sdes
32290267Sdes        ListBuffer<JCExpression> syntheticInits = new ListBuffer<>();
32363012Sdes
32463012Sdes        if (localContext.methodReferenceReceiver != null) {
32563012Sdes            syntheticInits.append(localContext.methodReferenceReceiver);
32663012Sdes        } else if (!sym.isStatic()) {
32763012Sdes            syntheticInits.append(makeThis(
32863012Sdes                    sym.owner.enclClass().asType(),
32990267Sdes                    localContext.owner.enclClass()));
33090267Sdes        }
33190267Sdes
33290267Sdes        //add captured locals
33390267Sdes        for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
33490267Sdes            if (fv != localContext.self) {
33590267Sdes                JCTree captured_local = make.Ident(fv).setType(fv.type);
33690267Sdes                syntheticInits.append((JCExpression) captured_local);
33790267Sdes            }
33890267Sdes        }
33985093Sdes
34063012Sdes        //then, determine the arguments to the indy call
34163012Sdes        List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
34263012Sdes
34390267Sdes        //build a sam instance using an indy call to the meta-factory
34490267Sdes        int refKind = referenceKind(sym);
34563012Sdes
34690267Sdes        //convert to an invokedynamic call
34790267Sdes        result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
34890267Sdes    }
34990267Sdes
35090267Sdes    private JCIdent makeThis(Type type, Symbol owner) {
35190267Sdes        VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
35290267Sdes                names._this,
35363012Sdes                type,
35463012Sdes                owner);
35563012Sdes        return make.Ident(_this);
35663012Sdes    }
35763012Sdes
35863012Sdes    /**
35997856Sdes     * Translate a method reference into an invokedynamic call to the
36063012Sdes     * meta-factory.
36190267Sdes     * @param tree
36290267Sdes     */
36390267Sdes    @Override
36490267Sdes    public void visitReference(JCMemberReference tree) {
36563012Sdes        ReferenceTranslationContext localContext = (ReferenceTranslationContext)context;
36690267Sdes
36790267Sdes        //first determine the method symbol to be used to generate the sam instance
36890267Sdes        //this is either the method reference symbol, or the bridged reference symbol
36990267Sdes        Symbol refSym = localContext.isSignaturePolymorphic()
37090267Sdes                ? localContext.sigPolySym
37190267Sdes                : tree.sym;
37290267Sdes
37390267Sdes        //the qualifying expression is treated as a special captured arg
37490267Sdes        JCExpression init;
37590267Sdes        switch(tree.kind) {
37697856Sdes
37790267Sdes            case IMPLICIT_INNER:    /** Inner :: new */
37890267Sdes            case SUPER:             /** super :: instMethod */
37990267Sdes                init = makeThis(
38090267Sdes                    localContext.owner.enclClass().asType(),
38190267Sdes                    localContext.owner.enclClass());
38290267Sdes                break;
38390267Sdes
38490267Sdes            case BOUND:             /** Expr :: instMethod */
38563012Sdes                init = tree.getQualifierExpression();
38663012Sdes                init = attr.makeNullCheck(init);
38763012Sdes                break;
38863012Sdes
38963012Sdes            case UNBOUND:           /** Type :: instMethod */
39063012Sdes            case STATIC:            /** Type :: staticMethod */
39197856Sdes            case TOPLEVEL:          /** Top level :: new */
39263012Sdes            case ARRAY_CTOR:        /** ArrayType :: new */
39390267Sdes                init = null;
39490267Sdes                break;
39597856Sdes
39690267Sdes            default:
39790267Sdes                throw new InternalError("Should not have an invalid kind");
39890267Sdes        }
39990267Sdes
40090267Sdes        List<JCExpression> indy_args = init==null? List.<JCExpression>nil() : translate(List.of(init), localContext.prev);
40190267Sdes
40290267Sdes
40390267Sdes        //build a sam instance using an indy call to the meta-factory
40490267Sdes        result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
40590267Sdes    }
40697856Sdes
40790267Sdes    /**
40897856Sdes     * Translate identifiers within a lambda to the mapped identifier
40990267Sdes     * @param tree
41090267Sdes     */
41190267Sdes    @Override
41290267Sdes    public void visitIdent(JCIdent tree) {
41390267Sdes        if (context == null || !analyzer.lambdaIdentSymbolFilter(tree.sym)) {
41490267Sdes            super.visitIdent(tree);
41590267Sdes        } else {
41690267Sdes            int prevPos = make.pos;
41797856Sdes            try {
41897856Sdes                make.at(tree);
41937535Sdes
42037535Sdes                LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
42137608Sdes                JCTree ltree = lambdaContext.translate(tree);
42290267Sdes                if (ltree != null) {
42390267Sdes                    result = ltree;
42463012Sdes                } else {
42575891Sarchie                    //access to untranslated symbols (i.e. compile-time constants,
42675891Sarchie                    //members defined inside the lambda body, etc.) )
42763012Sdes                    super.visitIdent(tree);
42890267Sdes                }
42990267Sdes            } finally {
43090267Sdes                make.at(prevPos);
43190267Sdes            }
43290267Sdes        }
43390267Sdes    }
43490267Sdes
43563012Sdes    @Override
43663012Sdes    public void visitVarDef(JCVariableDecl tree) {
43763012Sdes        LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context;
43863012Sdes        if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
43963012Sdes            tree.init = translate(tree.init);
44085093Sdes            tree.sym = (VarSymbol) lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym);
44197856Sdes            result = tree;
44263012Sdes        } else if (context != null && lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) {
44390267Sdes            JCExpression init = translate(tree.init);
44490267Sdes            VarSymbol xsym = (VarSymbol)lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym);
44597856Sdes            int prevPos = make.pos;
44690267Sdes            try {
44797856Sdes                result = make.at(tree).VarDef(xsym, init);
44897856Sdes            } finally {
44997856Sdes                make.at(prevPos);
45097856Sdes            }
45197856Sdes            // Replace the entered symbol for this variable
45290267Sdes            WriteableScope sc = tree.sym.owner.members();
45390267Sdes            if (sc != null) {
45490267Sdes                sc.remove(tree.sym);
45590267Sdes                sc.enter(xsym);
45690267Sdes            }
45790267Sdes        } else {
45890267Sdes            super.visitVarDef(tree);
45997856Sdes        }
46090267Sdes    }
46190267Sdes
46263012Sdes    // </editor-fold>
46363012Sdes
46463012Sdes    // <editor-fold defaultstate="collapsed" desc="Translation helper methods">
46563012Sdes
46663012Sdes    private JCBlock makeLambdaBody(JCLambda tree, JCMethodDecl lambdaMethodDecl) {
46763716Sdes        return tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION ?
46875891Sarchie                makeLambdaExpressionBody((JCExpression)tree.body, lambdaMethodDecl) :
46963012Sdes                makeLambdaStatementBody((JCBlock)tree.body, lambdaMethodDecl, tree.canCompleteNormally);
47090267Sdes    }
47190267Sdes
47263012Sdes    private JCBlock makeLambdaExpressionBody(JCExpression expr, JCMethodDecl lambdaMethodDecl) {
47390267Sdes        Type restype = lambdaMethodDecl.type.getReturnType();
47490267Sdes        boolean isLambda_void = expr.type.hasTag(VOID);
47590267Sdes        boolean isTarget_void = restype.hasTag(VOID);
47690267Sdes        boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
47790267Sdes        int prevPos = make.pos;
47890267Sdes        try {
47990267Sdes            if (isTarget_void) {
48090267Sdes                //target is void:
48188769Sdes                // BODY;
48263012Sdes                JCStatement stat = make.at(expr).Exec(expr);
48363012Sdes                return make.Block(0, List.<JCStatement>of(stat));
48490267Sdes            } else if (isLambda_void && isTarget_Void) {
48590267Sdes                //void to Void conversion:
48663012Sdes                // BODY; return null;
48763012Sdes                ListBuffer<JCStatement> stats = new ListBuffer<>();
48863012Sdes                stats.append(make.at(expr).Exec(expr));
48963012Sdes                stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
49063012Sdes                return make.Block(0, stats.toList());
49163716Sdes            } else {
49275891Sarchie                //non-void to non-void conversion:
49363012Sdes                // return (TYPE)BODY;
49490267Sdes                JCExpression retExpr = transTypes.coerce(attrEnv, expr, restype);
49590267Sdes                return make.at(retExpr).Block(0, List.<JCStatement>of(make.Return(retExpr)));
49690267Sdes            }
49790267Sdes        } finally {
49890267Sdes            make.at(prevPos);
49990267Sdes        }
50090267Sdes    }
50190267Sdes
50290267Sdes    private JCBlock makeLambdaStatementBody(JCBlock block, final JCMethodDecl lambdaMethodDecl, boolean completeNormally) {
50390267Sdes        final Type restype = lambdaMethodDecl.type.getReturnType();
50463012Sdes        final boolean isTarget_void = restype.hasTag(VOID);
50563012Sdes        boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
50663012Sdes
50763012Sdes        class LambdaBodyTranslator extends TreeTranslator {
50863012Sdes
50963716Sdes            @Override
51075891Sarchie            public void visitClassDef(JCClassDecl tree) {
51163012Sdes                //do NOT recurse on any inner classes
51290267Sdes                result = tree;
51363716Sdes            }
51490267Sdes
51590267Sdes            @Override
51690267Sdes            public void visitLambda(JCLambda tree) {
51790267Sdes                //do NOT recurse on any nested lambdas
51890267Sdes                result = tree;
51990267Sdes            }
52090267Sdes
52190267Sdes            @Override
52290267Sdes            public void visitReturn(JCReturn tree) {
52390267Sdes                boolean isLambda_void = tree.expr == null;
52490267Sdes                if (isTarget_void && !isLambda_void) {
52590267Sdes                    //Void to void conversion:
52690267Sdes                    // { TYPE $loc = RET-EXPR; return; }
52790267Sdes                    VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym);
52890267Sdes                    JCVariableDecl varDef = make.VarDef(loc, tree.expr);
52990267Sdes                    result = make.Block(0, List.<JCStatement>of(varDef, make.Return(null)));
53090267Sdes                } else if (!isTarget_void || !isLambda_void) {
53190267Sdes                    //non-void to non-void conversion:
53290267Sdes                    // return (TYPE)RET-EXPR;
53390267Sdes                    tree.expr = transTypes.coerce(attrEnv, tree.expr, restype);
53463012Sdes                    result = tree;
53563012Sdes                } else {
53690267Sdes                    result = tree;
53763012Sdes                }
53863012Sdes
53963012Sdes            }
54063012Sdes        }
54163012Sdes
54237608Sdes        JCBlock trans_block = new LambdaBodyTranslator().translate(block);
54337608Sdes        if (completeNormally && isTarget_Void) {
54462965Sdes            //there's no return statement and the lambda (possibly inferred)
54590267Sdes            //return type is java.lang.Void; emit a synthetic return statement
54637608Sdes            trans_block.stats = trans_block.stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
54790267Sdes        }
54890267Sdes        return trans_block;
54990267Sdes    }
55090267Sdes
55190267Sdes    private JCMethodDecl makeDeserializeMethod(Symbol kSym) {
55290267Sdes        ListBuffer<JCCase> cases = new ListBuffer<>();
55390267Sdes        ListBuffer<JCBreak> breaks = new ListBuffer<>();
55462965Sdes        for (Map.Entry<String, ListBuffer<JCStatement>> entry : kInfo.deserializeCases.entrySet()) {
55590267Sdes            JCBreak br = make.Break(null);
55690267Sdes            breaks.add(br);
55790267Sdes            List<JCStatement> stmts = entry.getValue().append(br).toList();
55890267Sdes            cases.add(make.Case(make.Literal(entry.getKey()), stmts));
55990267Sdes        }
56037608Sdes        JCSwitch sw = make.Switch(deserGetter("getImplMethodName", syms.stringType), cases.toList());
56190267Sdes        for (JCBreak br : breaks) {
56290267Sdes            br.target = sw;
56390267Sdes        }
56490267Sdes        JCBlock body = make.Block(0L, List.<JCStatement>of(
56590267Sdes                sw,
56690267Sdes                make.Throw(makeNewClass(
56790267Sdes                    syms.illegalArgumentExceptionType,
56890267Sdes                    List.<JCExpression>of(make.Literal("Invalid lambda deserialization"))))));
56990267Sdes        JCMethodDecl deser = make.MethodDef(make.Modifiers(kInfo.deserMethodSym.flags()),
57037608Sdes                        names.deserializeLambda,
57190267Sdes                        make.QualIdent(kInfo.deserMethodSym.getReturnType().tsym),
57290267Sdes                        List.<JCTypeParameter>nil(),
57390267Sdes                        List.of(make.VarDef(kInfo.deserParamSym, null)),
57490267Sdes                        List.<JCExpression>nil(),
57590267Sdes                        body,
57690267Sdes                        null);
57790267Sdes        deser.sym = kInfo.deserMethodSym;
57890267Sdes        deser.type = kInfo.deserMethodSym.type;
57990267Sdes        //System.err.printf("DESER: '%s'\n", deser);
58090267Sdes        return deser;
58190267Sdes    }
58290267Sdes
58390267Sdes    /** Make an attributed class instance creation expression.
58490267Sdes     *  @param ctype    The class type.
58590267Sdes     *  @param args     The constructor arguments.
58690267Sdes     *  @param cons     The constructor symbol
58790267Sdes     */
58890267Sdes    JCNewClass makeNewClass(Type ctype, List<JCExpression> args, Symbol cons) {
58990267Sdes        JCNewClass tree = make.NewClass(null,
59090267Sdes            null, make.QualIdent(ctype.tsym), args, null);
59190267Sdes        tree.constructor = cons;
59290267Sdes        tree.type = ctype;
59390267Sdes        return tree;
59490267Sdes    }
59537608Sdes
59637608Sdes    /** Make an attributed class instance creation expression.
59737608Sdes     *  @param ctype    The class type.
59837608Sdes     *  @param args     The constructor arguments.
59937608Sdes     */
60062965Sdes    JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
60197856Sdes        return makeNewClass(ctype, args,
60237608Sdes                rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil()));
60390267Sdes     }
60490267Sdes
60537608Sdes    private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
60690267Sdes            DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
60790267Sdes        String functionalInterfaceClass = classSig(targetType);
60890267Sdes        String functionalInterfaceMethodName = samSym.getSimpleName().toString();
60990267Sdes        String functionalInterfaceMethodSignature = typeSig(types.erasure(samSym.type));
61090267Sdes        String implClass = classSig(types.erasure(refSym.owner.type));
61190267Sdes        String implMethodName = refSym.getQualifiedName().toString();
61290267Sdes        String implMethodSignature = typeSig(types.erasure(refSym.type));
61390267Sdes
61497856Sdes        JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
61590267Sdes        ListBuffer<JCExpression> serArgs = new ListBuffer<>();
61690267Sdes        int i = 0;
61762965Sdes        for (Type t : indyType.getParameterTypes()) {
61862965Sdes            List<JCExpression> indexAsArg = new ListBuffer<JCExpression>().append(make.Literal(i)).toList();
61962965Sdes            List<Type> argTypes = new ListBuffer<Type>().append(syms.intType).toList();
62062965Sdes            serArgs.add(make.TypeCast(types.erasure(t), deserGetter("getCapturedArg", syms.objectType, argTypes, indexAsArg)));
62162965Sdes            ++i;
62262965Sdes        }
62397856Sdes        JCStatement stmt = make.If(
62462965Sdes                deserTest(deserTest(deserTest(deserTest(deserTest(
62590267Sdes                    kindTest,
62690267Sdes                    "getFunctionalInterfaceClass", functionalInterfaceClass),
62790267Sdes                    "getFunctionalInterfaceMethodName", functionalInterfaceMethodName),
62890267Sdes                    "getFunctionalInterfaceMethodSignature", functionalInterfaceMethodSignature),
62962965Sdes                    "getImplClass", implClass),
63090267Sdes                    "getImplMethodSignature", implMethodSignature),
63190267Sdes                make.Return(makeIndyCall(
63290267Sdes                    pos,
63390267Sdes                    syms.lambdaMetafactory,
63490267Sdes                    names.altMetafactory,
63590267Sdes                    staticArgs, indyType, serArgs.toList(), samSym.name)),
63690267Sdes                null);
63790267Sdes        ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
63890267Sdes        if (stmts == null) {
63990267Sdes            stmts = new ListBuffer<>();
64097856Sdes            kInfo.deserializeCases.put(implMethodName, stmts);
64190267Sdes        }
64290267Sdes        /****
64390267Sdes        System.err.printf("+++++++++++++++++\n");
64490267Sdes        System.err.printf("*functionalInterfaceClass: '%s'\n", functionalInterfaceClass);
64537608Sdes        System.err.printf("*functionalInterfaceMethodName: '%s'\n", functionalInterfaceMethodName);
64637608Sdes        System.err.printf("*functionalInterfaceMethodSignature: '%s'\n", functionalInterfaceMethodSignature);
64790267Sdes        System.err.printf("*implMethodKind: %d\n", implMethodKind);
64863012Sdes        System.err.printf("*implClass: '%s'\n", implClass);
64963012Sdes        System.err.printf("*implMethodName: '%s'\n", implMethodName);
65063012Sdes        System.err.printf("*implMethodSignature: '%s'\n", implMethodSignature);
65163012Sdes        ****/
65237608Sdes        stmts.append(stmt);
65390267Sdes    }
65463012Sdes
65597856Sdes    private JCExpression eqTest(Type argType, JCExpression arg1, JCExpression arg2) {
65675891Sarchie        JCBinary testExpr = make.Binary(JCTree.Tag.EQ, arg1, arg2);
65763012Sdes        testExpr.operator = rs.resolveBinaryOperator(null, JCTree.Tag.EQ, attrEnv, argType, argType);
65897856Sdes        testExpr.setType(syms.booleanType);
65990267Sdes        return testExpr;
66097856Sdes    }
66190267Sdes
66263012Sdes    private JCExpression deserTest(JCExpression prev, String func, String lit) {
66390267Sdes        MethodType eqmt = new MethodType(List.of(syms.objectType), syms.booleanType, List.<Type>nil(), syms.methodClass);
66460737Sume        Symbol eqsym = rs.resolveQualifiedMethod(null, attrEnv, syms.objectType, names.equals, List.of(syms.objectType), List.<Type>nil());
66590267Sdes        JCMethodInvocation eqtest = make.Apply(
66660737Sume                List.<JCExpression>nil(),
66790267Sdes                make.Select(deserGetter(func, syms.stringType), eqsym).setType(eqmt),
66890267Sdes                List.<JCExpression>of(make.Literal(lit)));
66990267Sdes        eqtest.setType(syms.booleanType);
67090267Sdes        JCBinary compound = make.Binary(JCTree.Tag.AND, prev, eqtest);
67167043Sdes        compound.operator = rs.resolveBinaryOperator(null, JCTree.Tag.AND, attrEnv, syms.booleanType, syms.booleanType);
67290267Sdes        compound.setType(syms.booleanType);
67390267Sdes        return compound;
67467043Sdes    }
67567043Sdes
67697868Sdes    private JCExpression deserGetter(String func, Type type) {
67790267Sdes        return deserGetter(func, type, List.<Type>nil(), List.<JCExpression>nil());
67890267Sdes    }
67990267Sdes
68090267Sdes    private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) {
68197856Sdes        MethodType getmt = new MethodType(argTypes, type, List.<Type>nil(), syms.methodClass);
68290267Sdes        Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.<Type>nil());
68390267Sdes        return make.Apply(
68497856Sdes                    List.<JCExpression>nil(),
68590267Sdes                    make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt),
68697856Sdes                    args).setType(type);
68797868Sdes    }
68897868Sdes
68997868Sdes    /**
69097891Sdes     * Create new synthetic method with given flags, name, type, owner
69197891Sdes     */
69297891Sdes    private MethodSymbol makePrivateSyntheticMethod(long flags, Name name, Type type, Symbol owner) {
69397868Sdes        return new MethodSymbol(flags | SYNTHETIC | PRIVATE, name, type, owner);
69497868Sdes    }
69597856Sdes
69667043Sdes    /**
69767043Sdes     * Create new synthetic variable with given flags, name, type, owner
69867043Sdes     */
69975891Sarchie    private VarSymbol makeSyntheticVar(long flags, String name, Type type, Symbol owner) {
70067043Sdes        return makeSyntheticVar(flags, names.fromString(name), type, owner);
70190267Sdes    }
70290267Sdes
70390267Sdes    /**
70490267Sdes     * Create new synthetic variable with given flags, name, type, owner
70590267Sdes     */
70690267Sdes    private VarSymbol makeSyntheticVar(long flags, Name name, Type type, Symbol owner) {
70790267Sdes        return new VarSymbol(flags | SYNTHETIC, name, type, owner);
70890267Sdes    }
70990267Sdes
71090267Sdes    /**
71190267Sdes     * Set varargsElement field on a given tree (must be either a new class tree
71290267Sdes     * or a method call tree)
71390267Sdes     */
71490267Sdes    private void setVarargsIfNeeded(JCTree tree, Type varargsElement) {
71560376Sdes        if (varargsElement != null) {
71660376Sdes            switch (tree.getTag()) {
71788771Sdes                case APPLY: ((JCMethodInvocation)tree).varargsElement = varargsElement; break;
71888771Sdes                case NEWCLASS: ((JCNewClass)tree).varargsElement = varargsElement; break;
71988771Sdes                default: throw new AssertionError();
72090267Sdes            }
72190267Sdes        }
72290267Sdes    }
72388771Sdes
72490267Sdes    /**
72590267Sdes     * Convert method/constructor arguments by inserting appropriate cast
72690267Sdes     * as required by type-erasure - this is needed when bridging a lambda/method
72790267Sdes     * reference, as the bridged signature might require downcast to be compatible
72890267Sdes     * with the generated signature.
72990267Sdes     */
73090267Sdes    private List<JCExpression> convertArgs(Symbol meth, List<JCExpression> args, Type varargsElement) {
73190267Sdes       Assert.check(meth.kind == MTH);
73290267Sdes       List<Type> formals = types.erasure(meth.type).getParameterTypes();
73390267Sdes       if (varargsElement != null) {
73490267Sdes           Assert.check((meth.flags() & VARARGS) != 0);
73590267Sdes       }
73690267Sdes       return transTypes.translateArgs(args, formals, varargsElement, attrEnv);
73790267Sdes    }
73890267Sdes
73990267Sdes    // </editor-fold>
74090267Sdes
74190267Sdes    /**
74290267Sdes     * Converts a method reference which cannot be used directly into a lambda
74390267Sdes     */
74490267Sdes    private class MemberReferenceToLambda {
74590267Sdes
74690267Sdes        private final JCMemberReference tree;
74790267Sdes        private final ReferenceTranslationContext localContext;
74888771Sdes        private final Symbol owner;
74990267Sdes        private final ListBuffer<JCExpression> args = new ListBuffer<>();
75090267Sdes        private final ListBuffer<JCVariableDecl> params = new ListBuffer<>();
75190267Sdes
75288771Sdes        private JCExpression receiverExpression = null;
75388771Sdes
75488771Sdes        MemberReferenceToLambda(JCMemberReference tree, ReferenceTranslationContext localContext, Symbol owner) {
75590267Sdes            this.tree = tree;
75663012Sdes            this.localContext = localContext;
75763012Sdes            this.owner = owner;
75860954Sdes        }
75960954Sdes
76060954Sdes        JCLambda lambda() {
76163012Sdes            int prevPos = make.pos;
76297866Sdes            try {
76397866Sdes                make.at(tree);
76497866Sdes
76560376Sdes                //body generation - this can be either a method call or a
76667043Sdes                //new instance creation expression, depending on the member reference kind
76775891Sarchie                VarSymbol rcvr = addParametersReturnReceiver();
76890267Sdes                JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
76960376Sdes                        ? expressionInvoke(rcvr)
77097856Sdes                        : expressionNew();
77190267Sdes
77290267Sdes                JCLambda slam = make.Lambda(params.toList(), expr);
77398422Sdes                slam.targets = tree.targets;
77490267Sdes                slam.type = tree.type;
77590267Sdes                slam.pos = tree.pos;
77690267Sdes                return slam;
77790267Sdes            } finally {
77890267Sdes                make.at(prevPos);
779107372Sdes            }
78063012Sdes        }
78190267Sdes
78290267Sdes        /**
78390267Sdes         * Generate the parameter list for the converted member reference.
78460737Sume         *
78590267Sdes         * @return The receiver variable symbol, if any
78690267Sdes         */
78790267Sdes        VarSymbol addParametersReturnReceiver() {
78890267Sdes            Type samDesc = localContext.bridgedRefSig();
78963716Sdes            List<Type> samPTypes = samDesc.getParameterTypes();
79090267Sdes            List<Type> descPTypes = tree.getDescriptorType(types).getParameterTypes();
79190267Sdes
79263012Sdes            // Determine the receiver, if any
79390267Sdes            VarSymbol rcvr;
79490267Sdes            switch (tree.kind) {
79590267Sdes                case BOUND:
79663012Sdes                    // The receiver is explicit in the method reference
79798422Sdes                    rcvr = addParameter("rec$", tree.getQualifierExpression().type, false);
79890267Sdes                    receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
79990267Sdes                    break;
80090267Sdes                case UNBOUND:
80190267Sdes                    // The receiver is the first parameter, extract it and
80290267Sdes                    // adjust the SAM and unerased type lists accordingly
80390267Sdes                    rcvr = addParameter("rec$", samDesc.getParameterTypes().head, false);
80490267Sdes                    samPTypes = samPTypes.tail;
80590267Sdes                    descPTypes = descPTypes.tail;
80690267Sdes                    break;
80790267Sdes                default:
80890267Sdes                    rcvr = null;
80990267Sdes                    break;
81090267Sdes            }
81190267Sdes            List<Type> implPTypes = tree.sym.type.getParameterTypes();
81290267Sdes            int implSize = implPTypes.size();
81390267Sdes            int samSize = samPTypes.size();
81490267Sdes            // Last parameter to copy from referenced method, exclude final var args
81590267Sdes            int last = localContext.needsVarArgsConversion() ? implSize - 1 : implSize;
81690267Sdes
81790267Sdes            // Failsafe -- assure match-up
81890267Sdes            boolean checkForIntersection = tree.varargsElement != null || implSize == descPTypes.size();
81990267Sdes
82090267Sdes            // Use parameter types of the implementation method unless the unerased
82197856Sdes            // SAM parameter type is an intersection type, in that case use the
82290267Sdes            // erased SAM parameter type so that the supertype relationship
82390267Sdes            // the implementation method parameters is not obscured.
82490267Sdes            // Note: in this loop, the lists implPTypes, samPTypes, and descPTypes
82560737Sume            // are used as pointers to the current parameter type information
82690267Sdes            // and are thus not usable afterwards.
82790267Sdes            for (int i = 0; implPTypes.nonEmpty() && i < last; ++i) {
82890267Sdes                // By default use the implementation method parmeter type
82990267Sdes                Type parmType = implPTypes.head;
83060737Sume                // If the unerased parameter type is a type variable whose
831107372Sdes                // bound is an intersection (eg. <T extends A & B>) then
832107372Sdes                // use the SAM parameter type
833107372Sdes                if (checkForIntersection && descPTypes.head.getKind() == TypeKind.TYPEVAR) {
834107372Sdes                    TypeVar tv = (TypeVar) descPTypes.head;
835107372Sdes                    if (tv.bound.getKind() == TypeKind.INTERSECTION) {
836107372Sdes                        parmType = samPTypes.head;
837107372Sdes                    }
838107372Sdes                }
83937535Sdes                addParameter("x$" + i, parmType, true);
84090267Sdes
84190267Sdes                // Advance to the next parameter
842107372Sdes                implPTypes = implPTypes.tail;
843107372Sdes                samPTypes = samPTypes.tail;
84490267Sdes                descPTypes = descPTypes.tail;
845107372Sdes            }
846107372Sdes            // Flatten out the var args
84790267Sdes            for (int i = last; i < samSize; ++i) {
84897856Sdes                addParameter("xva$" + i, tree.varargsElement, true);
84990267Sdes            }
85090267Sdes
85137535Sdes            return rcvr;
85290267Sdes        }
853107372Sdes
85490267Sdes        JCExpression getReceiverExpression() {
85590267Sdes            return receiverExpression;
85690267Sdes        }
85790267Sdes
85897856Sdes        private JCExpression makeReceiver(VarSymbol rcvr) {
85990267Sdes            if (rcvr == null) return null;
86090267Sdes            JCExpression rcvrExpr = make.Ident(rcvr);
86197856Sdes            Type rcvrType = tree.sym.enclClass().type;
86290267Sdes            if (rcvrType == syms.arrayClass.type) {
86390267Sdes                // Map the receiver type to the actually type, not just "array"
86490267Sdes                rcvrType = tree.getQualifierExpression().type;
86590267Sdes            }
86690267Sdes            if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) {
86797856Sdes                rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType);
86890267Sdes            }
86997856Sdes            return rcvrExpr;
87090267Sdes        }
87197856Sdes
87290267Sdes        /**
87390267Sdes         * determine the receiver of the method call - the receiver can
87490267Sdes         * be a type qualifier, the synthetic receiver parameter or 'super'.
87590267Sdes         */
87690267Sdes        private JCExpression expressionInvoke(VarSymbol rcvr) {
87790267Sdes            JCExpression qualifier =
87890267Sdes                    tree.sym.isStatic() ?
879107372Sdes                        make.Type(tree.sym.owner.type) :
880107372Sdes                        (rcvr != null) ?
881107372Sdes                            makeReceiver(rcvr) :
882107372Sdes                            tree.getQualifierExpression();
883107372Sdes
884107372Sdes            //create the qualifier expression
885107372Sdes            JCFieldAccess select = make.Select(qualifier, tree.sym.name);
88690267Sdes            select.sym = tree.sym;
88797856Sdes            select.type = tree.sym.erasure(types);
88890267Sdes
88997856Sdes            //create the method call expression
89090267Sdes            JCExpression apply = make.Apply(List.<JCExpression>nil(), select,
89197856Sdes                    convertArgs(tree.sym, args.toList(), tree.varargsElement)).
89297856Sdes                    setType(tree.sym.erasure(types).getReturnType());
89397856Sdes
89490267Sdes            apply = transTypes.coerce(apply, localContext.generatedRefSig().getReturnType());
89590267Sdes            setVarargsIfNeeded(apply, tree.varargsElement);
89697856Sdes            return apply;
89790267Sdes        }
89890267Sdes
89990267Sdes        /**
90090267Sdes         * Lambda body to use for a 'new'.
90190267Sdes         */
90290267Sdes        private JCExpression expressionNew() {
90390267Sdes            if (tree.kind == ReferenceKind.ARRAY_CTOR) {
90490267Sdes                //create the array creation expression
90590267Sdes                JCNewArray newArr = make.NewArray(
90690267Sdes                        make.Type(types.elemtype(tree.getQualifierExpression().type)),
90790267Sdes                        List.of(make.Ident(params.first())),
90890267Sdes                        null);
90990267Sdes                newArr.type = tree.getQualifierExpression().type;
91090267Sdes                return newArr;
91190267Sdes            } else {
91290267Sdes                //create the instance creation expression
91390267Sdes                //note that method reference syntax does not allow an explicit
91490267Sdes                //enclosing class (so the enclosing class is null)
91597856Sdes                JCNewClass newClass = make.NewClass(null,
91690267Sdes                        List.<JCExpression>nil(),
91790267Sdes                        make.Type(tree.getQualifierExpression().type),
91890267Sdes                        convertArgs(tree.sym, args.toList(), tree.varargsElement),
91990267Sdes                        null);
92090267Sdes                newClass.constructor = tree.sym;
92190267Sdes                newClass.constructorType = tree.sym.erasure(types);
92290267Sdes                newClass.type = tree.getQualifierExpression().type;
92390267Sdes                setVarargsIfNeeded(newClass, tree.varargsElement);
92490267Sdes                return newClass;
92590267Sdes            }
92690267Sdes        }
92797856Sdes
92890267Sdes        private VarSymbol addParameter(String name, Type p, boolean genArg) {
92990267Sdes            VarSymbol vsym = new VarSymbol(PARAMETER | SYNTHETIC, names.fromString(name), p, owner);
93090267Sdes            vsym.pos = tree.pos;
93190267Sdes            params.append(make.VarDef(vsym, null));
93290267Sdes            if (genArg) {
93390267Sdes                args.append(make.Ident(vsym));
93490267Sdes            }
93597856Sdes            return vsym;
93690267Sdes        }
93790267Sdes    }
93890267Sdes
93990267Sdes    private MethodType typeToMethodType(Type mt) {
94090267Sdes        Type type = types.erasure(mt);
94190267Sdes        return new MethodType(type.getParameterTypes(),
94290267Sdes                        type.getReturnType(),
94397856Sdes                        type.getThrownTypes(),
94490267Sdes                        syms.methodClass);
94590267Sdes    }
94690267Sdes
94790267Sdes    /**
94890267Sdes     * Generate an indy method call to the meta factory
94990267Sdes     */
95090267Sdes    private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context,
95190267Sdes            int refKind, Symbol refSym, List<JCExpression> indy_args) {
95290267Sdes        JCFunctionalExpression tree = context.tree;
95390267Sdes        //determine the static bsm args
95490267Sdes        MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
95590267Sdes        List<Object> staticArgs = List.<Object>of(
95690267Sdes                typeToMethodType(samSym.type),
95790267Sdes                new Pool.MethodHandle(refKind, refSym, types),
95890267Sdes                typeToMethodType(tree.getDescriptorType(types)));
95990267Sdes
96097856Sdes        //computed indy arg types
96190267Sdes        ListBuffer<Type> indy_args_types = new ListBuffer<>();
96290267Sdes        for (JCExpression arg : indy_args) {
96390267Sdes            indy_args_types.append(arg.type);
96490267Sdes        }
96597856Sdes
96690267Sdes        //finally, compute the type of the indy call
96790267Sdes        MethodType indyType = new MethodType(indy_args_types.toList(),
96890267Sdes                tree.type,
96990267Sdes                List.<Type>nil(),
97090267Sdes                syms.methodClass);
97190267Sdes
97290267Sdes        Name metafactoryName = context.needsAltMetafactory() ?
97390267Sdes                names.altMetafactory : names.metafactory;
97490267Sdes
97590267Sdes        if (context.needsAltMetafactory()) {
97690267Sdes            ListBuffer<Object> markers = new ListBuffer<>();
97790267Sdes            for (Type t : tree.targets.tail) {
97890267Sdes                if (t.tsym != syms.serializableType.tsym) {
97990267Sdes                    markers.append(t.tsym);
98090267Sdes                }
98190267Sdes            }
98290267Sdes            int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
98390267Sdes            boolean hasMarkers = markers.nonEmpty();
98490267Sdes            boolean hasBridges = context.bridges.nonEmpty();
98590267Sdes            if (hasMarkers) {
98690267Sdes                flags |= FLAG_MARKERS;
98790267Sdes            }
98890267Sdes            if (hasBridges) {
98997856Sdes                flags |= FLAG_BRIDGES;
99090267Sdes            }
99190267Sdes            staticArgs = staticArgs.append(flags);
99290267Sdes            if (hasMarkers) {
99390267Sdes                staticArgs = staticArgs.append(markers.length());
99490267Sdes                staticArgs = staticArgs.appendList(markers.toList());
99590267Sdes            }
99690267Sdes            if (hasBridges) {
99790267Sdes                staticArgs = staticArgs.append(context.bridges.length() - 1);
99890267Sdes                for (Symbol s : context.bridges) {
99990267Sdes                    Type s_erasure = s.erasure(types);
100090267Sdes                    if (!types.isSameType(s_erasure, samSym.erasure(types))) {
100190267Sdes                        staticArgs = staticArgs.append(s.erasure(types));
100297856Sdes                    }
100398422Sdes                }
100490267Sdes            }
100597856Sdes            if (context.isSerializable()) {
100697856Sdes                int prevPos = make.pos;
100790267Sdes                try {
100890267Sdes                    make.at(kInfo.clazz);
100990267Sdes                    addDeserializationCase(refKind, refSym, tree.type, samSym,
1010104404Sru                            tree, staticArgs, indyType);
1011104404Sru                } finally {
1012104404Sru                    make.at(prevPos);
1013104404Sru                }
101490267Sdes            }
101598422Sdes        }
101690267Sdes
101797856Sdes        return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name);
101897856Sdes    }
101990267Sdes
102090267Sdes    /**
102190267Sdes     * Generate an indy method call with given name, type and static bootstrap
102290267Sdes     * arguments types
102390267Sdes     */
102490267Sdes    private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
102590267Sdes            List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
102690267Sdes            Name methName) {
102790267Sdes        int prevPos = make.pos;
102890267Sdes        try {
102997856Sdes            make.at(pos);
103098422Sdes            List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
103163012Sdes                    syms.stringType,
103263012Sdes                    syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
103360376Sdes
103490267Sdes            Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
103590267Sdes                    bsmName, bsm_staticArgs, List.<Type>nil());
103690267Sdes
103790267Sdes            DynamicMethodSymbol dynSym =
103860376Sdes                    new DynamicMethodSymbol(methName,
103990267Sdes                                            syms.noSymbol,
104090267Sdes                                            bsm.isStatic() ?
104190267Sdes                                                ClassFile.REF_invokeStatic :
104263012Sdes                                                ClassFile.REF_invokeVirtual,
104363012Sdes                                            (MethodSymbol)bsm,
104490267Sdes                                            indyType,
104590267Sdes                                            staticArgs.toArray());
104690267Sdes
104790267Sdes            JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
104890267Sdes            qualifier.sym = dynSym;
104963012Sdes            qualifier.type = indyType.getReturnType();
105063012Sdes
105190267Sdes            JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, indyArgs);
105290267Sdes            proxyCall.type = indyType.getReturnType();
105390267Sdes            return proxyCall;
105460376Sdes        } finally {
105590267Sdes            make.at(prevPos);
105690267Sdes        }
105790267Sdes    }
105890267Sdes    //where
105990267Sdes    private List<Type> bsmStaticArgToTypes(List<Object> args) {
106063069Sdes        ListBuffer<Type> argtypes = new ListBuffer<>();
106190267Sdes        for (Object arg : args) {
106290267Sdes            argtypes.append(bsmStaticArgToType(arg));
106390267Sdes        }
106490267Sdes        return argtypes.toList();
106577238Sdes    }
106660376Sdes
106790267Sdes    private Type bsmStaticArgToType(Object arg) {
106890267Sdes        Assert.checkNonNull(arg);
106990267Sdes        if (arg instanceof ClassSymbol) {
107037535Sdes            return syms.classType;
107190267Sdes        } else if (arg instanceof Integer) {
107297866Sdes            return syms.intType;
107390267Sdes        } else if (arg instanceof Long) {
107490267Sdes            return syms.longType;
107590267Sdes        } else if (arg instanceof Float) {
107663716Sdes            return syms.floatType;
107790267Sdes        } else if (arg instanceof Double) {
107890267Sdes            return syms.doubleType;
107990267Sdes        } else if (arg instanceof String) {
108090267Sdes            return syms.stringType;
108163567Sdes        } else if (arg instanceof Pool.MethodHandle) {
108297856Sdes            return syms.methodHandleType;
108390267Sdes        } else if (arg instanceof MethodType) {
108490267Sdes            return syms.methodTypeType;
108590267Sdes        } else {
108690267Sdes            Assert.error("bad static arg " + arg.getClass());
108763012Sdes            return null;
108890267Sdes        }
108988771Sdes    }
109090267Sdes
109190267Sdes    /**
109290267Sdes     * Get the opcode associated with this method reference
109390267Sdes     */
109490267Sdes    private int referenceKind(Symbol refSym) {
109597856Sdes        if (refSym.isConstructor()) {
109697856Sdes            return ClassFile.REF_newInvokeSpecial;
109790267Sdes        } else {
109863012Sdes            if (refSym.isStatic()) {
109960189Sdes                return ClassFile.REF_invokeStatic;
110090267Sdes            } else if ((refSym.flags() & PRIVATE) != 0) {
110163012Sdes                return ClassFile.REF_invokeSpecial;
110263012Sdes            } else if (refSym.enclClass().isInterface()) {
110363012Sdes                return ClassFile.REF_invokeInterface;
110463012Sdes            } else {
110563012Sdes                return ClassFile.REF_invokeVirtual;
110663340Sdes            }
110763340Sdes        }
110863340Sdes    }
110975891Sarchie
111063340Sdes    // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
111190267Sdes    /**
111263340Sdes     * This visitor collects information about translation of a lambda expression.
111363340Sdes     * More specifically, it keeps track of the enclosing contexts and captured locals
111463340Sdes     * accessed by the lambda being translated (as well as other useful info).
111563012Sdes     * It also translates away problems for LambdaToMethod.
111663012Sdes     */
111763012Sdes    class LambdaAnalyzerPreprocessor extends TreeTranslator {
111875891Sarchie
111963012Sdes        /** the frame stack - used to reconstruct translation info about enclosing scopes */
112090267Sdes        private List<Frame> frameStack;
112137535Sdes
112237535Sdes        /**
112363340Sdes         * keep the count of lambda expression (used to generate unambiguous
112463340Sdes         * names)
112563340Sdes         */
112637535Sdes        private int lambdaCount = 0;
112785093Sdes
112837535Sdes        /**
112990267Sdes         * keep the count of lambda expression defined in given context (used to
113090267Sdes         * generate unambiguous names for serializable lambdas)
113137535Sdes         */
113240975Sdes        private class SyntheticMethodNameCounter {
113340975Sdes            private Map<String, Integer> map = new HashMap<>();
113440975Sdes            int getIndex(StringBuilder buf) {
113540975Sdes                String temp = buf.toString();
113640975Sdes                Integer count = map.get(temp);
113775891Sarchie                if (count == null) {
113840975Sdes                    count = 0;
113990267Sdes                }
114090267Sdes                ++count;
114190267Sdes                map.put(temp, count);
114290267Sdes                return count;
114390267Sdes            }
114490267Sdes        }
114540975Sdes        private SyntheticMethodNameCounter syntheticMethodNameCounts =
114641989Sdes                new SyntheticMethodNameCounter();
114741989Sdes
114841989Sdes        private Map<Symbol, JCClassDecl> localClassDefs;
114941989Sdes
115041989Sdes        /**
115185093Sdes         * maps for fake clinit symbols to be used as owners of lambda occurring in
115241989Sdes         * a static var init context
115390267Sdes         */
115490267Sdes        private Map<ClassSymbol, Symbol> clinits = new HashMap<>();
115541989Sdes
1156        private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) {
1157            frameStack = List.nil();
1158            localClassDefs = new HashMap<>();
1159            return translate(tree);
1160        }
1161
1162        @Override
1163        public void visitBlock(JCBlock tree) {
1164            List<Frame> prevStack = frameStack;
1165            try {
1166                if (frameStack.nonEmpty() && frameStack.head.tree.hasTag(CLASSDEF)) {
1167                    frameStack = frameStack.prepend(new Frame(tree));
1168                }
1169                super.visitBlock(tree);
1170            }
1171            finally {
1172                frameStack = prevStack;
1173            }
1174        }
1175
1176        @Override
1177        public void visitClassDef(JCClassDecl tree) {
1178            List<Frame> prevStack = frameStack;
1179            int prevLambdaCount = lambdaCount;
1180            SyntheticMethodNameCounter prevSyntheticMethodNameCounts =
1181                    syntheticMethodNameCounts;
1182            Map<ClassSymbol, Symbol> prevClinits = clinits;
1183            DiagnosticSource prevSource = log.currentSource();
1184            try {
1185                log.useSource(tree.sym.sourcefile);
1186                lambdaCount = 0;
1187                syntheticMethodNameCounts = new SyntheticMethodNameCounter();
1188                prevClinits = new HashMap<>();
1189                if (tree.sym.owner.kind == MTH) {
1190                    localClassDefs.put(tree.sym, tree);
1191                }
1192                if (directlyEnclosingLambda() != null) {
1193                    tree.sym.owner = owner();
1194                    if (tree.sym.hasOuterInstance()) {
1195                        //if a class is defined within a lambda, the lambda must capture
1196                        //its enclosing instance (if any)
1197                        TranslationContext<?> localContext = context();
1198                        while (localContext != null) {
1199                            if (localContext.tree.getTag() == LAMBDA) {
1200                                ((LambdaTranslationContext)localContext)
1201                                        .addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS);
1202                            }
1203                            localContext = localContext.prev;
1204                        }
1205                    }
1206                }
1207                frameStack = frameStack.prepend(new Frame(tree));
1208                super.visitClassDef(tree);
1209            }
1210            finally {
1211                log.useSource(prevSource.getFile());
1212                frameStack = prevStack;
1213                lambdaCount = prevLambdaCount;
1214                syntheticMethodNameCounts = prevSyntheticMethodNameCounts;
1215                clinits = prevClinits;
1216            }
1217        }
1218
1219        @Override
1220        public void visitIdent(JCIdent tree) {
1221            if (context() != null && lambdaIdentSymbolFilter(tree.sym)) {
1222                if (tree.sym.kind == VAR &&
1223                        tree.sym.owner.kind == MTH &&
1224                        tree.type.constValue() == null) {
1225                    TranslationContext<?> localContext = context();
1226                    while (localContext != null) {
1227                        if (localContext.tree.getTag() == LAMBDA) {
1228                            JCTree block = capturedDecl(localContext.depth, tree.sym);
1229                            if (block == null) break;
1230                            ((LambdaTranslationContext)localContext)
1231                                    .addSymbol(tree.sym, CAPTURED_VAR);
1232                        }
1233                        localContext = localContext.prev;
1234                    }
1235                } else if (tree.sym.owner.kind == TYP) {
1236                    TranslationContext<?> localContext = context();
1237                    while (localContext != null) {
1238                        if (localContext.tree.hasTag(LAMBDA)) {
1239                            JCTree block = capturedDecl(localContext.depth, tree.sym);
1240                            if (block == null) break;
1241                            switch (block.getTag()) {
1242                                case CLASSDEF:
1243                                    JCClassDecl cdecl = (JCClassDecl)block;
1244                                    ((LambdaTranslationContext)localContext)
1245                                            .addSymbol(cdecl.sym, CAPTURED_THIS);
1246                                    break;
1247                                default:
1248                                    Assert.error("bad block kind");
1249                            }
1250                        }
1251                        localContext = localContext.prev;
1252                    }
1253                }
1254            }
1255            super.visitIdent(tree);
1256        }
1257
1258        @Override
1259        public void visitLambda(JCLambda tree) {
1260            analyzeLambda(tree, "lambda.stat");
1261        }
1262
1263        private void analyzeLambda(JCLambda tree, JCExpression methodReferenceReceiver) {
1264            // Translation of the receiver expression must occur first
1265            JCExpression rcvr = translate(methodReferenceReceiver);
1266            LambdaTranslationContext context = analyzeLambda(tree, "mref.stat.1");
1267            if (rcvr != null) {
1268                context.methodReferenceReceiver = rcvr;
1269            }
1270        }
1271
1272        private LambdaTranslationContext analyzeLambda(JCLambda tree, String statKey) {
1273            List<Frame> prevStack = frameStack;
1274            try {
1275                LambdaTranslationContext context = new LambdaTranslationContext(tree);
1276                if (dumpLambdaToMethodStats) {
1277                    log.note(tree, statKey, context.needsAltMetafactory(), context.translatedSym);
1278                }
1279                frameStack = frameStack.prepend(new Frame(tree));
1280                for (JCVariableDecl param : tree.params) {
1281                    context.addSymbol(param.sym, PARAM);
1282                    frameStack.head.addLocal(param.sym);
1283                }
1284                contextMap.put(tree, context);
1285                super.visitLambda(tree);
1286                context.complete();
1287                return context;
1288            }
1289            finally {
1290                frameStack = prevStack;
1291            }
1292        }
1293
1294        @Override
1295        public void visitMethodDef(JCMethodDecl tree) {
1296            List<Frame> prevStack = frameStack;
1297            try {
1298                frameStack = frameStack.prepend(new Frame(tree));
1299                super.visitMethodDef(tree);
1300            }
1301            finally {
1302                frameStack = prevStack;
1303            }
1304        }
1305
1306        @Override
1307        public void visitNewClass(JCNewClass tree) {
1308            TypeSymbol def = tree.type.tsym;
1309            boolean inReferencedClass = currentlyInClass(def);
1310            boolean isLocal = def.isLocal();
1311            if ((inReferencedClass && isLocal || lambdaNewClassFilter(context(), tree))) {
1312                TranslationContext<?> localContext = context();
1313                while (localContext != null) {
1314                    if (localContext.tree.getTag() == LAMBDA) {
1315                        ((LambdaTranslationContext)localContext)
1316                                .addSymbol(tree.type.getEnclosingType().tsym, CAPTURED_THIS);
1317                    }
1318                    localContext = localContext.prev;
1319                }
1320            }
1321            if (context() != null && !inReferencedClass && isLocal) {
1322                LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context();
1323                captureLocalClassDefs(def, lambdaContext);
1324            }
1325            super.visitNewClass(tree);
1326        }
1327        //where
1328            void captureLocalClassDefs(Symbol csym, final LambdaTranslationContext lambdaContext) {
1329                JCClassDecl localCDef = localClassDefs.get(csym);
1330                if (localCDef != null && lambdaContext.freeVarProcessedLocalClasses.add(csym)) {
1331                    BasicFreeVarCollector fvc = lower.new BasicFreeVarCollector() {
1332                        @Override
1333                        void addFreeVars(ClassSymbol c) {
1334                            captureLocalClassDefs(c, lambdaContext);
1335                        }
1336                        @Override
1337                        void visitSymbol(Symbol sym) {
1338                            if (sym.kind == VAR &&
1339                                    sym.owner.kind == MTH &&
1340                                    ((VarSymbol)sym).getConstValue() == null) {
1341                                TranslationContext<?> localContext = context();
1342                                while (localContext != null) {
1343                                    if (localContext.tree.getTag() == LAMBDA) {
1344                                        JCTree block = capturedDecl(localContext.depth, sym);
1345                                        if (block == null) break;
1346                                        ((LambdaTranslationContext)localContext).addSymbol(sym, CAPTURED_VAR);
1347                                    }
1348                                    localContext = localContext.prev;
1349                                }
1350                            }
1351                        }
1352                    };
1353                    fvc.scan(localCDef);
1354                }
1355        }
1356        //where
1357        boolean currentlyInClass(Symbol csym) {
1358            for (Frame frame : frameStack) {
1359                if (frame.tree.hasTag(JCTree.Tag.CLASSDEF)) {
1360                    JCClassDecl cdef = (JCClassDecl) frame.tree;
1361                    if (cdef.sym == csym) {
1362                        return true;
1363                    }
1364                }
1365            }
1366            return false;
1367        }
1368
1369        /**
1370         * Method references to local class constructors, may, if the local
1371         * class references local variables, have implicit constructor
1372         * parameters added in Lower; As a result, the invokedynamic bootstrap
1373         * information added in the LambdaToMethod pass will have the wrong
1374         * signature. Hooks between Lower and LambdaToMethod have been added to
1375         * handle normal "new" in this case. This visitor converts potentially
1376         * affected method references into a lambda containing a normal
1377         * expression.
1378         *
1379         * @param tree
1380         */
1381        @Override
1382        public void visitReference(JCMemberReference tree) {
1383            ReferenceTranslationContext rcontext = new ReferenceTranslationContext(tree);
1384            contextMap.put(tree, rcontext);
1385            if (rcontext.needsConversionToLambda()) {
1386                 // Convert to a lambda, and process as such
1387                MemberReferenceToLambda conv = new MemberReferenceToLambda(tree, rcontext, owner());
1388                analyzeLambda(conv.lambda(), conv.getReceiverExpression());
1389            } else {
1390                super.visitReference(tree);
1391                if (dumpLambdaToMethodStats) {
1392                    log.note(tree, "mref.stat", rcontext.needsAltMetafactory(), null);
1393                }
1394            }
1395        }
1396
1397        @Override
1398        public void visitSelect(JCFieldAccess tree) {
1399            if (context() != null && tree.sym.kind == VAR &&
1400                        (tree.sym.name == names._this ||
1401                         tree.sym.name == names._super)) {
1402                // A select of this or super means, if we are in a lambda,
1403                // we much have an instance context
1404                TranslationContext<?> localContext = context();
1405                while (localContext != null) {
1406                    if (localContext.tree.hasTag(LAMBDA)) {
1407                        JCClassDecl clazz = (JCClassDecl)capturedDecl(localContext.depth, tree.sym);
1408                        if (clazz == null) break;
1409                        ((LambdaTranslationContext)localContext).addSymbol(clazz.sym, CAPTURED_THIS);
1410                    }
1411                    localContext = localContext.prev;
1412                }
1413            }
1414            super.visitSelect(tree);
1415        }
1416
1417        @Override
1418        public void visitVarDef(JCVariableDecl tree) {
1419            TranslationContext<?> context = context();
1420            LambdaTranslationContext ltc = (context != null && context instanceof LambdaTranslationContext)?
1421                    (LambdaTranslationContext)context :
1422                    null;
1423            if (ltc != null) {
1424                if (frameStack.head.tree.hasTag(LAMBDA)) {
1425                    ltc.addSymbol(tree.sym, LOCAL_VAR);
1426                }
1427                // Check for type variables (including as type arguments).
1428                // If they occur within class nested in a lambda, mark for erasure
1429                Type type = tree.sym.asType();
1430                if (inClassWithinLambda() && !types.isSameType(types.erasure(type), type)) {
1431                    ltc.addSymbol(tree.sym, TYPE_VAR);
1432                }
1433            }
1434
1435            List<Frame> prevStack = frameStack;
1436            try {
1437                if (tree.sym.owner.kind == MTH) {
1438                    frameStack.head.addLocal(tree.sym);
1439                }
1440                frameStack = frameStack.prepend(new Frame(tree));
1441                super.visitVarDef(tree);
1442            }
1443            finally {
1444                frameStack = prevStack;
1445            }
1446        }
1447
1448        /**
1449         * Return a valid owner given the current declaration stack
1450         * (required to skip synthetic lambda symbols)
1451         */
1452        private Symbol owner() {
1453            return owner(false);
1454        }
1455
1456        @SuppressWarnings("fallthrough")
1457        private Symbol owner(boolean skipLambda) {
1458            List<Frame> frameStack2 = frameStack;
1459            while (frameStack2.nonEmpty()) {
1460                switch (frameStack2.head.tree.getTag()) {
1461                    case VARDEF:
1462                        if (((JCVariableDecl)frameStack2.head.tree).sym.isLocal()) {
1463                            frameStack2 = frameStack2.tail;
1464                            break;
1465                        }
1466                        JCClassDecl cdecl = (JCClassDecl)frameStack2.tail.head.tree;
1467                        return initSym(cdecl.sym,
1468                                ((JCVariableDecl)frameStack2.head.tree).sym.flags() & STATIC);
1469                    case BLOCK:
1470                        JCClassDecl cdecl2 = (JCClassDecl)frameStack2.tail.head.tree;
1471                        return initSym(cdecl2.sym,
1472                                ((JCBlock)frameStack2.head.tree).flags & STATIC);
1473                    case CLASSDEF:
1474                        return ((JCClassDecl)frameStack2.head.tree).sym;
1475                    case METHODDEF:
1476                        return ((JCMethodDecl)frameStack2.head.tree).sym;
1477                    case LAMBDA:
1478                        if (!skipLambda)
1479                            return ((LambdaTranslationContext)contextMap
1480                                    .get(frameStack2.head.tree)).translatedSym;
1481                    default:
1482                        frameStack2 = frameStack2.tail;
1483                }
1484            }
1485            Assert.error();
1486            return null;
1487        }
1488
1489        private Symbol initSym(ClassSymbol csym, long flags) {
1490            boolean isStatic = (flags & STATIC) != 0;
1491            if (isStatic) {
1492                /* static clinits are generated in Gen, so we need to use a fake
1493                 * one. Attr creates a fake clinit method while attributing
1494                 * lambda expressions used as initializers of static fields, so
1495                 * let's use that one.
1496                 */
1497                MethodSymbol clinit = attr.removeClinit(csym);
1498                if (clinit != null) {
1499                    clinits.put(csym, clinit);
1500                    return clinit;
1501                }
1502
1503                /* if no clinit is found at Attr, then let's try at clinits.
1504                 */
1505                clinit = (MethodSymbol)clinits.get(csym);
1506                if (clinit == null) {
1507                    /* no luck, let's create a new one
1508                     */
1509                    clinit = makePrivateSyntheticMethod(STATIC,
1510                            names.clinit,
1511                            new MethodType(List.<Type>nil(), syms.voidType,
1512                                List.<Type>nil(), syms.methodClass),
1513                            csym);
1514                    clinits.put(csym, clinit);
1515                }
1516                return clinit;
1517            } else {
1518                //get the first constructor and treat it as the instance init sym
1519                for (Symbol s : csym.members_field.getSymbolsByName(names.init)) {
1520                    return s;
1521                }
1522            }
1523            Assert.error("init not found");
1524            return null;
1525        }
1526
1527        private JCTree directlyEnclosingLambda() {
1528            if (frameStack.isEmpty()) {
1529                return null;
1530            }
1531            List<Frame> frameStack2 = frameStack;
1532            while (frameStack2.nonEmpty()) {
1533                switch (frameStack2.head.tree.getTag()) {
1534                    case CLASSDEF:
1535                    case METHODDEF:
1536                        return null;
1537                    case LAMBDA:
1538                        return frameStack2.head.tree;
1539                    default:
1540                        frameStack2 = frameStack2.tail;
1541                }
1542            }
1543            Assert.error();
1544            return null;
1545        }
1546
1547        private boolean inClassWithinLambda() {
1548            if (frameStack.isEmpty()) {
1549                return false;
1550            }
1551            List<Frame> frameStack2 = frameStack;
1552            boolean classFound = false;
1553            while (frameStack2.nonEmpty()) {
1554                switch (frameStack2.head.tree.getTag()) {
1555                    case LAMBDA:
1556                        return classFound;
1557                    case CLASSDEF:
1558                        classFound = true;
1559                        frameStack2 = frameStack2.tail;
1560                        break;
1561                    default:
1562                        frameStack2 = frameStack2.tail;
1563                }
1564            }
1565            // No lambda
1566            return false;
1567        }
1568
1569        /**
1570         * Return the declaration corresponding to a symbol in the enclosing
1571         * scope; the depth parameter is used to filter out symbols defined
1572         * in nested scopes (which do not need to undergo capture).
1573         */
1574        private JCTree capturedDecl(int depth, Symbol sym) {
1575            int currentDepth = frameStack.size() - 1;
1576            for (Frame block : frameStack) {
1577                switch (block.tree.getTag()) {
1578                    case CLASSDEF:
1579                        ClassSymbol clazz = ((JCClassDecl)block.tree).sym;
1580                        if (sym.isMemberOf(clazz, types)) {
1581                            return currentDepth > depth ? null : block.tree;
1582                        }
1583                        break;
1584                    case VARDEF:
1585                        if (((JCVariableDecl)block.tree).sym == sym &&
1586                                sym.owner.kind == MTH) { //only locals are captured
1587                            return currentDepth > depth ? null : block.tree;
1588                        }
1589                        break;
1590                    case BLOCK:
1591                    case METHODDEF:
1592                    case LAMBDA:
1593                        if (block.locals != null && block.locals.contains(sym)) {
1594                            return currentDepth > depth ? null : block.tree;
1595                        }
1596                        break;
1597                    default:
1598                        Assert.error("bad decl kind " + block.tree.getTag());
1599                }
1600                currentDepth--;
1601            }
1602            return null;
1603        }
1604
1605        private TranslationContext<?> context() {
1606            for (Frame frame : frameStack) {
1607                TranslationContext<?> context = contextMap.get(frame.tree);
1608                if (context != null) {
1609                    return context;
1610                }
1611            }
1612            return null;
1613        }
1614
1615        /**
1616         *  This is used to filter out those identifiers that needs to be adjusted
1617         *  when translating away lambda expressions
1618         */
1619        private boolean lambdaIdentSymbolFilter(Symbol sym) {
1620            return (sym.kind == VAR || sym.kind == MTH)
1621                    && !sym.isStatic()
1622                    && sym.name != names.init;
1623        }
1624
1625        /**
1626         * This is used to filter out those new class expressions that need to
1627         * be qualified with an enclosing tree
1628         */
1629        private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) {
1630            if (context != null
1631                    && tree.encl == null
1632                    && tree.def == null
1633                    && !tree.type.getEnclosingType().hasTag(NONE)) {
1634                Type encl = tree.type.getEnclosingType();
1635                Type current = context.owner.enclClass().type;
1636                while (!current.hasTag(NONE)) {
1637                    if (current.tsym.isSubClass(encl.tsym, types)) {
1638                        return true;
1639                    }
1640                    current = current.getEnclosingType();
1641                }
1642                return false;
1643            } else {
1644                return false;
1645            }
1646        }
1647
1648        private class Frame {
1649            final JCTree tree;
1650            List<Symbol> locals;
1651
1652            public Frame(JCTree tree) {
1653                this.tree = tree;
1654            }
1655
1656            void addLocal(Symbol sym) {
1657                if (locals == null) {
1658                    locals = List.nil();
1659                }
1660                locals = locals.prepend(sym);
1661            }
1662        }
1663
1664        /**
1665         * This class is used to store important information regarding translation of
1666         * lambda expression/method references (see subclasses).
1667         */
1668        private abstract class TranslationContext<T extends JCFunctionalExpression> {
1669
1670            /** the underlying (untranslated) tree */
1671            final T tree;
1672
1673            /** points to the adjusted enclosing scope in which this lambda/mref expression occurs */
1674            final Symbol owner;
1675
1676            /** the depth of this lambda expression in the frame stack */
1677            final int depth;
1678
1679            /** the enclosing translation context (set for nested lambdas/mref) */
1680            final TranslationContext<?> prev;
1681
1682            /** list of methods to be bridged by the meta-factory */
1683            final List<Symbol> bridges;
1684
1685            TranslationContext(T tree) {
1686                this.tree = tree;
1687                this.owner = owner();
1688                this.depth = frameStack.size() - 1;
1689                this.prev = context();
1690                ClassSymbol csym =
1691                        types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.targets, ABSTRACT | INTERFACE);
1692                this.bridges = types.functionalInterfaceBridges(csym);
1693            }
1694
1695            /** does this functional expression need to be created using alternate metafactory? */
1696            boolean needsAltMetafactory() {
1697                return tree.targets.length() > 1 ||
1698                        isSerializable() ||
1699                        bridges.length() > 1;
1700            }
1701
1702            /** does this functional expression require serialization support? */
1703            boolean isSerializable() {
1704                if (forceSerializable) {
1705                    return true;
1706                }
1707                for (Type target : tree.targets) {
1708                    if (types.asSuper(target, syms.serializableType.tsym) != null) {
1709                        return true;
1710                    }
1711                }
1712                return false;
1713            }
1714
1715            /**
1716             * @return Name of the enclosing method to be folded into synthetic
1717             * method name
1718             */
1719            String enclosingMethodName() {
1720                return syntheticMethodNameComponent(owner.name);
1721            }
1722
1723            /**
1724             * @return Method name in a form that can be folded into a
1725             * component of a synthetic method name
1726             */
1727            String syntheticMethodNameComponent(Name name) {
1728                if (name == null) {
1729                    return "null";
1730                }
1731                String methodName = name.toString();
1732                if (methodName.equals("<clinit>")) {
1733                    methodName = "static";
1734                } else if (methodName.equals("<init>")) {
1735                    methodName = "new";
1736                }
1737                return methodName;
1738            }
1739        }
1740
1741        /**
1742         * This class retains all the useful information about a lambda expression;
1743         * the contents of this class are filled by the LambdaAnalyzer visitor,
1744         * and the used by the main translation routines in order to adjust references
1745         * to captured locals/members, etc.
1746         */
1747        private class LambdaTranslationContext extends TranslationContext<JCLambda> {
1748
1749            /** variable in the enclosing context to which this lambda is assigned */
1750            final Symbol self;
1751
1752            /** variable in the enclosing context to which this lambda is assigned */
1753            final Symbol assignedTo;
1754
1755            Map<LambdaSymbolKind, Map<Symbol, Symbol>> translatedSymbols;
1756
1757            /** the synthetic symbol for the method hoisting the translated lambda */
1758            MethodSymbol translatedSym;
1759
1760            List<JCVariableDecl> syntheticParams;
1761
1762            /**
1763             * to prevent recursion, track local classes processed
1764             */
1765            final Set<Symbol> freeVarProcessedLocalClasses;
1766
1767            /**
1768             * For method references converted to lambdas.  The method
1769             * reference receiver expression. Must be treated like a captured
1770             * variable.
1771             */
1772            JCExpression methodReferenceReceiver;
1773
1774            LambdaTranslationContext(JCLambda tree) {
1775                super(tree);
1776                Frame frame = frameStack.head;
1777                switch (frame.tree.getTag()) {
1778                    case VARDEF:
1779                        assignedTo = self = ((JCVariableDecl) frame.tree).sym;
1780                        break;
1781                    case ASSIGN:
1782                        self = null;
1783                        assignedTo = TreeInfo.symbol(((JCAssign) frame.tree).getVariable());
1784                        break;
1785                    default:
1786                        assignedTo = self = null;
1787                        break;
1788                 }
1789
1790                // This symbol will be filled-in in complete
1791                this.translatedSym = makePrivateSyntheticMethod(0, null, null, owner.enclClass());
1792
1793                translatedSymbols = new EnumMap<>(LambdaSymbolKind.class);
1794
1795                translatedSymbols.put(PARAM, new LinkedHashMap<Symbol, Symbol>());
1796                translatedSymbols.put(LOCAL_VAR, new LinkedHashMap<Symbol, Symbol>());
1797                translatedSymbols.put(CAPTURED_VAR, new LinkedHashMap<Symbol, Symbol>());
1798                translatedSymbols.put(CAPTURED_THIS, new LinkedHashMap<Symbol, Symbol>());
1799                translatedSymbols.put(TYPE_VAR, new LinkedHashMap<Symbol, Symbol>());
1800
1801                freeVarProcessedLocalClasses = new HashSet<>();
1802            }
1803
1804             /**
1805             * For a serializable lambda, generate a disambiguating string
1806             * which maximizes stability across deserialization.
1807             *
1808             * @return String to differentiate synthetic lambda method names
1809             */
1810            private String serializedLambdaDisambiguation() {
1811                StringBuilder buf = new StringBuilder();
1812                // Append the enclosing method signature to differentiate
1813                // overloaded enclosing methods.  For lambdas enclosed in
1814                // lambdas, the generated lambda method will not have type yet,
1815                // but the enclosing method's name will have been generated
1816                // with this same method, so it will be unique and never be
1817                // overloaded.
1818                Assert.check(
1819                        owner.type != null ||
1820                        directlyEnclosingLambda() != null);
1821                if (owner.type != null) {
1822                    buf.append(typeSig(owner.type));
1823                    buf.append(":");
1824                }
1825
1826                // Add target type info
1827                buf.append(types.findDescriptorSymbol(tree.type.tsym).owner.flatName());
1828                buf.append(" ");
1829
1830                // Add variable assigned to
1831                if (assignedTo != null) {
1832                    buf.append(assignedTo.flatName());
1833                    buf.append("=");
1834                }
1835                //add captured locals info: type, name, order
1836                for (Symbol fv : getSymbolMap(CAPTURED_VAR).keySet()) {
1837                    if (fv != self) {
1838                        buf.append(typeSig(fv.type));
1839                        buf.append(" ");
1840                        buf.append(fv.flatName());
1841                        buf.append(",");
1842                    }
1843                }
1844
1845                return buf.toString();
1846            }
1847
1848            /**
1849             * For a non-serializable lambda, generate a simple method.
1850             *
1851             * @return Name to use for the synthetic lambda method name
1852             */
1853            private Name lambdaName() {
1854                return names.lambda.append(names.fromString(enclosingMethodName() + "$" + lambdaCount++));
1855            }
1856
1857            /**
1858             * For a serializable lambda, generate a method name which maximizes
1859             * name stability across deserialization.
1860             *
1861             * @return Name to use for the synthetic lambda method name
1862             */
1863            private Name serializedLambdaName() {
1864                StringBuilder buf = new StringBuilder();
1865                buf.append(names.lambda);
1866                // Append the name of the method enclosing the lambda.
1867                buf.append(enclosingMethodName());
1868                buf.append('$');
1869                // Append a hash of the disambiguating string : enclosing method
1870                // signature, etc.
1871                String disam = serializedLambdaDisambiguation();
1872                buf.append(Integer.toHexString(disam.hashCode()));
1873                buf.append('$');
1874                // The above appended name components may not be unique, append
1875                // a count based on the above name components.
1876                buf.append(syntheticMethodNameCounts.getIndex(buf));
1877                String result = buf.toString();
1878                //System.err.printf("serializedLambdaName: %s -- %s\n", result, disam);
1879                return names.fromString(result);
1880            }
1881
1882            /**
1883             * Translate a symbol of a given kind into something suitable for the
1884             * synthetic lambda body
1885             */
1886            Symbol translate(Name name, final Symbol sym, LambdaSymbolKind skind) {
1887                Symbol ret;
1888                switch (skind) {
1889                    case CAPTURED_THIS:
1890                        ret = sym;  // self represented
1891                        break;
1892                    case TYPE_VAR:
1893                        // Just erase the type var
1894                        ret = new VarSymbol(sym.flags(), name,
1895                                types.erasure(sym.type), sym.owner);
1896
1897                        /* this information should also be kept for LVT generation at Gen
1898                         * a Symbol with pos < startPos won't be tracked.
1899                         */
1900                        ((VarSymbol)ret).pos = ((VarSymbol)sym).pos;
1901                        break;
1902                    case CAPTURED_VAR:
1903                        ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, name, types.erasure(sym.type), translatedSym) {
1904                            @Override
1905                            public Symbol baseSymbol() {
1906                                //keep mapping with original captured symbol
1907                                return sym;
1908                            }
1909                        };
1910                        break;
1911                    case LOCAL_VAR:
1912                        ret = new VarSymbol(sym.flags() & FINAL, name, sym.type, translatedSym);
1913                        ((VarSymbol) ret).pos = ((VarSymbol) sym).pos;
1914                        break;
1915                    case PARAM:
1916                        ret = new VarSymbol((sym.flags() & FINAL) | PARAMETER, name, types.erasure(sym.type), translatedSym);
1917                        ((VarSymbol) ret).pos = ((VarSymbol) sym).pos;
1918                        break;
1919                    default:
1920                        ret = makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym);
1921                        ((VarSymbol) ret).pos = ((VarSymbol) sym).pos;
1922                }
1923                if (ret != sym) {
1924                    ret.setDeclarationAttributes(sym.getRawAttributes());
1925                    ret.setTypeAttributes(sym.getRawTypeAttributes());
1926                }
1927                return ret;
1928            }
1929
1930            void addSymbol(Symbol sym, LambdaSymbolKind skind) {
1931                Map<Symbol, Symbol> transMap = getSymbolMap(skind);
1932                Name preferredName;
1933                switch (skind) {
1934                    case CAPTURED_THIS:
1935                        preferredName = names.fromString("encl$" + transMap.size());
1936                        break;
1937                    case CAPTURED_VAR:
1938                        preferredName = names.fromString("cap$" + transMap.size());
1939                        break;
1940                    case LOCAL_VAR:
1941                        preferredName = sym.name;
1942                        break;
1943                    case PARAM:
1944                        preferredName = sym.name;
1945                        break;
1946                    case TYPE_VAR:
1947                        preferredName = sym.name;
1948                        break;
1949                    default: throw new AssertionError();
1950                }
1951                if (!transMap.containsKey(sym)) {
1952                    transMap.put(sym, translate(preferredName, sym, skind));
1953                }
1954            }
1955
1956            Map<Symbol, Symbol> getSymbolMap(LambdaSymbolKind skind) {
1957                Map<Symbol, Symbol> m = translatedSymbols.get(skind);
1958                Assert.checkNonNull(m);
1959                return m;
1960            }
1961
1962            JCTree translate(JCIdent lambdaIdent) {
1963                for (Map<Symbol, Symbol> m : translatedSymbols.values()) {
1964                    if (m.containsKey(lambdaIdent.sym)) {
1965                        Symbol tSym = m.get(lambdaIdent.sym);
1966                        JCTree t = make.Ident(tSym).setType(lambdaIdent.type);
1967                        tSym.setTypeAttributes(lambdaIdent.sym.getRawTypeAttributes());
1968                        return t;
1969                    }
1970                }
1971                return null;
1972            }
1973
1974            /**
1975             * The translatedSym is not complete/accurate until the analysis is
1976             * finished.  Once the analysis is finished, the translatedSym is
1977             * "completed" -- updated with type information, access modifiers,
1978             * and full parameter list.
1979             */
1980            void complete() {
1981                if (syntheticParams != null) {
1982                    return;
1983                }
1984                boolean inInterface = translatedSym.owner.isInterface();
1985                boolean thisReferenced = !getSymbolMap(CAPTURED_THIS).isEmpty();
1986
1987                // If instance access isn't needed, make it static.
1988                // Interface instance methods must be default methods.
1989                // Lambda methods are private synthetic.
1990                // Inherit ACC_STRICT from the enclosing method, or, for clinit,
1991                // from the class.
1992                translatedSym.flags_field = SYNTHETIC | LAMBDA_METHOD |
1993                        owner.flags_field & STRICTFP |
1994                        owner.owner.flags_field & STRICTFP |
1995                        PRIVATE |
1996                        (thisReferenced? (inInterface? DEFAULT : 0) : STATIC);
1997
1998                //compute synthetic params
1999                ListBuffer<JCVariableDecl> params = new ListBuffer<>();
2000                ListBuffer<VarSymbol> parameterSymbols = new ListBuffer<>();
2001
2002                // The signature of the method is augmented with the following
2003                // synthetic parameters:
2004                //
2005                // 1) reference to enclosing contexts captured by the lambda expression
2006                // 2) enclosing locals captured by the lambda expression
2007                for (Symbol thisSym : getSymbolMap(CAPTURED_VAR).values()) {
2008                    params.append(make.VarDef((VarSymbol) thisSym, null));
2009                    parameterSymbols.append((VarSymbol) thisSym);
2010                }
2011                for (Symbol thisSym : getSymbolMap(PARAM).values()) {
2012                    params.append(make.VarDef((VarSymbol) thisSym, null));
2013                    parameterSymbols.append((VarSymbol) thisSym);
2014                }
2015                syntheticParams = params.toList();
2016
2017                translatedSym.params = parameterSymbols.toList();
2018
2019                // Compute and set the lambda name
2020                translatedSym.name = isSerializable()
2021                        ? serializedLambdaName()
2022                        : lambdaName();
2023
2024                //prepend synthetic args to translated lambda method signature
2025                translatedSym.type = types.createMethodTypeWithParameters(
2026                        generatedLambdaSig(),
2027                        TreeInfo.types(syntheticParams));
2028            }
2029
2030            Type generatedLambdaSig() {
2031                return types.erasure(tree.getDescriptorType(types));
2032            }
2033        }
2034
2035        /**
2036         * This class retains all the useful information about a method reference;
2037         * the contents of this class are filled by the LambdaAnalyzer visitor,
2038         * and the used by the main translation routines in order to adjust method
2039         * references (i.e. in case a bridge is needed)
2040         */
2041        private final class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
2042
2043            final boolean isSuper;
2044            final Symbol sigPolySym;
2045
2046            ReferenceTranslationContext(JCMemberReference tree) {
2047                super(tree);
2048                this.isSuper = tree.hasKind(ReferenceKind.SUPER);
2049                this.sigPolySym = isSignaturePolymorphic()
2050                        ? makePrivateSyntheticMethod(tree.sym.flags(),
2051                                              tree.sym.name,
2052                                              bridgedRefSig(),
2053                                              tree.sym.enclClass())
2054                        : null;
2055            }
2056
2057            /**
2058             * Get the opcode associated with this method reference
2059             */
2060            int referenceKind() {
2061                return LambdaToMethod.this.referenceKind(tree.sym);
2062            }
2063
2064            boolean needsVarArgsConversion() {
2065                return tree.varargsElement != null;
2066            }
2067
2068            /**
2069             * @return Is this an array operation like clone()
2070             */
2071            boolean isArrayOp() {
2072                return tree.sym.owner == syms.arrayClass;
2073            }
2074
2075            boolean receiverAccessible() {
2076                //hack needed to workaround 292 bug (7087658)
2077                //when 292 issue is fixed we should remove this and change the backend
2078                //code to always generate a method handle to an accessible method
2079                return tree.ownerAccessible;
2080            }
2081
2082            /**
2083             * The VM does not support access across nested classes (8010319).
2084             * Were that ever to change, this should be removed.
2085             */
2086            boolean isPrivateInOtherClass() {
2087                return  (tree.sym.flags() & PRIVATE) != 0 &&
2088                        !types.isSameType(
2089                              types.erasure(tree.sym.enclClass().asType()),
2090                              types.erasure(owner.enclClass().asType()));
2091            }
2092
2093            /**
2094             * Signature polymorphic methods need special handling.
2095             * e.g. MethodHandle.invoke() MethodHandle.invokeExact()
2096             */
2097            final boolean isSignaturePolymorphic() {
2098                return  tree.sym.kind == MTH &&
2099                        types.isSignaturePolymorphic((MethodSymbol)tree.sym);
2100            }
2101
2102            /**
2103             * Erasure destroys the implementation parameter subtype
2104             * relationship for intersection types
2105             */
2106            boolean interfaceParameterIsIntersectionType() {
2107                List<Type> tl = tree.getDescriptorType(types).getParameterTypes();
2108                if (tree.kind == ReferenceKind.UNBOUND) {
2109                    tl = tl.tail;
2110                }
2111                for (; tl.nonEmpty(); tl = tl.tail) {
2112                    Type pt = tl.head;
2113                    if (pt.getKind() == TypeKind.TYPEVAR) {
2114                        TypeVar tv = (TypeVar) pt;
2115                        if (tv.bound.getKind() == TypeKind.INTERSECTION) {
2116                            return true;
2117                        }
2118                    }
2119                }
2120                return false;
2121            }
2122
2123            /**
2124             * Does this reference need to be converted to a lambda
2125             * (i.e. var args need to be expanded or "super" is used)
2126             */
2127            final boolean needsConversionToLambda() {
2128                return interfaceParameterIsIntersectionType() ||
2129                        isSuper ||
2130                        needsVarArgsConversion() ||
2131                        isArrayOp() ||
2132                        isPrivateInOtherClass() ||
2133                        !receiverAccessible() ||
2134                        (tree.getMode() == ReferenceMode.NEW &&
2135                          tree.kind != ReferenceKind.ARRAY_CTOR &&
2136                          (tree.sym.owner.isLocal() || tree.sym.owner.isInner()));
2137            }
2138
2139            Type generatedRefSig() {
2140                return types.erasure(tree.sym.type);
2141            }
2142
2143            Type bridgedRefSig() {
2144                return types.erasure(types.findDescriptorSymbol(tree.targets.head.tsym).type);
2145            }
2146        }
2147    }
2148    // </editor-fold>
2149
2150    /*
2151     * These keys provide mappings for various translated lambda symbols
2152     * and the prevailing order must be maintained.
2153     */
2154    enum LambdaSymbolKind {
2155        PARAM,          // original to translated lambda parameters
2156        LOCAL_VAR,      // original to translated lambda locals
2157        CAPTURED_VAR,   // variables in enclosing scope to translated synthetic parameters
2158        CAPTURED_THIS,  // class symbols to translated synthetic parameters (for captured member access)
2159        TYPE_VAR       // original to translated lambda type variables
2160    }
2161
2162    /**
2163     * ****************************************************************
2164     * Signature Generation
2165     * ****************************************************************
2166     */
2167
2168    private String typeSig(Type type) {
2169        L2MSignatureGenerator sg = new L2MSignatureGenerator();
2170        sg.assembleSig(type);
2171        return sg.toString();
2172    }
2173
2174    private String classSig(Type type) {
2175        L2MSignatureGenerator sg = new L2MSignatureGenerator();
2176        sg.assembleClassSig(type);
2177        return sg.toString();
2178    }
2179
2180    /**
2181     * Signature Generation
2182     */
2183    private class L2MSignatureGenerator extends Types.SignatureGenerator {
2184
2185        /**
2186         * An output buffer for type signatures.
2187         */
2188        StringBuilder sb = new StringBuilder();
2189
2190        L2MSignatureGenerator() {
2191            super(types);
2192        }
2193
2194        @Override
2195        protected void append(char ch) {
2196            sb.append(ch);
2197        }
2198
2199        @Override
2200        protected void append(byte[] ba) {
2201            sb.append(new String(ba));
2202        }
2203
2204        @Override
2205        protected void append(Name name) {
2206            sb.append(name.toString());
2207        }
2208
2209        @Override
2210        public String toString() {
2211            return sb.toString();
2212        }
2213    }
2214}
2215