1 /*
   2  * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import com.sun.tools.javac.tree.*;
  29 import com.sun.tools.javac.tree.JCTree.*;
  30 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
  31 import com.sun.tools.javac.tree.TreeMaker;
  32 import com.sun.tools.javac.tree.TreeTranslator;
  33 import com.sun.tools.javac.code.Attribute;
  34 import com.sun.tools.javac.code.Scope.WriteableScope;
  35 import com.sun.tools.javac.code.Symbol;
  36 import com.sun.tools.javac.code.Symbol.ClassSymbol;
  37 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
  38 import com.sun.tools.javac.code.Symbol.MethodSymbol;
  39 import com.sun.tools.javac.code.Symbol.TypeSymbol;
  40 import com.sun.tools.javac.code.Symbol.VarSymbol;
  41 import com.sun.tools.javac.code.Symtab;
  42 import com.sun.tools.javac.code.Type;
  43 import com.sun.tools.javac.code.Type.MethodType;
  44 import com.sun.tools.javac.code.Type.TypeVar;
  45 import com.sun.tools.javac.code.Types;
  46 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
  47 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
  48 import com.sun.tools.javac.resources.CompilerProperties.Notes;
  49 import com.sun.tools.javac.jvm.*;
  50 import com.sun.tools.javac.util.*;
  51 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  52 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  53 
  54 import java.util.EnumMap;
  55 import java.util.HashMap;
  56 import java.util.HashSet;
  57 import java.util.LinkedHashMap;
  58 import java.util.Map;
  59 import java.util.Objects;
  60 import java.util.Optional;
  61 import java.util.Set;
  62 import java.util.function.Consumer;
  63 import java.util.function.Supplier;
  64 
  65 import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*;
  66 import static com.sun.tools.javac.code.Flags.*;
  67 import static com.sun.tools.javac.code.Kinds.Kind.*;
  68 import static com.sun.tools.javac.code.TypeTag.*;
  69 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  70 import static com.sun.tools.javac.jvm.Pool.DynamicMethod;
  71 
  72 import javax.lang.model.element.ElementKind;
  73 import javax.lang.model.type.TypeKind;
  74 
  75 import com.sun.tools.javac.code.Type.IntersectionClassType;
  76 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
  77 import com.sun.tools.javac.main.Option;
  78 
  79 /**
  80  * This pass desugars lambda expressions into static methods
  81  *
  82  *  <p><b>This is NOT part of any supported API.
  83  *  If you write code that depends on this, you do so at your own risk.
  84  *  This code and its internal interfaces are subject to change or
  85  *  deletion without notice.</b>
  86  */
  87 public class LambdaToMethod extends TreeTranslator {
  88 
  89     private Attr attr;
  90     private JCDiagnostic.Factory diags;
  91     private Log log;
  92     private Lower lower;
  93     private Names names;
  94     private Symtab syms;
  95     private Resolve rs;
  96     private Operators operators;
  97     private TreeMaker make;
  98     private Types types;
  99     private TransTypes transTypes;
 100     private Env<AttrContext> attrEnv;
 101 
 102     /** the analyzer scanner */
 103     private LambdaAnalyzerPreprocessor analyzer;
 104 
 105     /** map from lambda trees to translation contexts */
 106     private Map<JCTree, TranslationContext<?>> contextMap;
 107 
 108     /** current translation context (visitor argument) */
 109     private TranslationContext<?> context;
 110 
 111     /** info about the current class being processed */
 112     private KlassInfo kInfo;
 113 
 114     /** dump statistics about lambda code generation */
 115     private final boolean dumpLambdaToMethodStats;
 116 
 117     /** force serializable representation, for stress testing **/
 118     private final boolean forceSerializable;
 119 
 120     /** true if line or local variable debug info has been requested */
 121     private final boolean debugLinesOrVars;
 122 
 123     /** dump statistics about lambda method deduplication */
 124     private final boolean verboseDeduplication;
 125 
 126     /** deduplicate lambda implementation methods */
 127     private final boolean deduplicateLambdas;
 128 
 129     /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
 130     public static final int FLAG_SERIALIZABLE = 1 << 0;
 131 
 132     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
 133     public static final int FLAG_MARKERS = 1 << 1;
 134 
 135     /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
 136     public static final int FLAG_BRIDGES = 1 << 2;
 137 
 138     // <editor-fold defaultstate="collapsed" desc="Instantiating">
 139     protected static final Context.Key<LambdaToMethod> unlambdaKey = new Context.Key<>();
 140 
 141     public static LambdaToMethod instance(Context context) {
 142         LambdaToMethod instance = context.get(unlambdaKey);
 143         if (instance == null) {
 144             instance = new LambdaToMethod(context);
 145         }
 146         return instance;
 147     }
 148     private LambdaToMethod(Context context) {
 149         context.put(unlambdaKey, this);
 150         diags = JCDiagnostic.Factory.instance(context);
 151         log = Log.instance(context);
 152         lower = Lower.instance(context);
 153         names = Names.instance(context);
 154         syms = Symtab.instance(context);
 155         rs = Resolve.instance(context);
 156         operators = Operators.instance(context);
 157         make = TreeMaker.instance(context);
 158         types = Types.instance(context);
 159         transTypes = TransTypes.instance(context);
 160         analyzer = new LambdaAnalyzerPreprocessor();
 161         Options options = Options.instance(context);
 162         dumpLambdaToMethodStats = options.isSet("debug.dumpLambdaToMethodStats");
 163         attr = Attr.instance(context);
 164         forceSerializable = options.isSet("forceSerializable");
 165         debugLinesOrVars = options.isSet(Option.G)
 166                 || options.isSet(Option.G_CUSTOM, "lines")
 167                 || options.isSet(Option.G_CUSTOM, "vars");
 168         verboseDeduplication = options.isSet("debug.dumpLambdaToMethodDeduplication");
 169         deduplicateLambdas = options.getBoolean("deduplicateLambdas", true);
 170     }
 171     // </editor-fold>
 172 
 173     class DedupedLambda {
 174         private final MethodSymbol symbol;
 175         private final JCTree tree;
 176 
 177         private int hashCode;
 178 
 179         DedupedLambda(MethodSymbol symbol, JCTree tree) {
 180             this.symbol = symbol;
 181             this.tree = tree;
 182         }
 183 
 184 
 185         @Override
 186         public int hashCode() {
 187             int hashCode = this.hashCode;
 188             if (hashCode == 0) {
 189                 this.hashCode = hashCode = TreeHasher.hash(tree, symbol.params());
 190             }
 191             return hashCode;
 192         }
 193 
 194         @Override
 195         public boolean equals(Object o) {
 196             if (!(o instanceof DedupedLambda)) {
 197                 return false;
 198             }
 199             DedupedLambda that = (DedupedLambda) o;
 200             return types.isSameType(symbol.asType(), that.symbol.asType())
 201                     && new TreeDiffer(symbol.params(), that.symbol.params()).scan(tree, that.tree);
 202         }
 203     }
 204 
 205     private class KlassInfo {
 206 
 207         /**
 208          * list of methods to append
 209          */
 210         private ListBuffer<JCTree> appendedMethodList;
 211 
 212         private Map<DedupedLambda, DedupedLambda> dedupedLambdas;
 213 
 214         private Map<DynamicMethod, DynamicMethodSymbol> dynMethSyms = new HashMap<>();
 215 
 216         /**
 217          * list of deserialization cases
 218          */
 219         private final Map<String, ListBuffer<JCStatement>> deserializeCases;
 220 
 221        /**
 222          * deserialize method symbol
 223          */
 224         private final MethodSymbol deserMethodSym;
 225 
 226         /**
 227          * deserialize method parameter symbol
 228          */
 229         private final VarSymbol deserParamSym;
 230 
 231         private final JCClassDecl clazz;
 232 
 233         private KlassInfo(JCClassDecl clazz) {
 234             this.clazz = clazz;
 235             appendedMethodList = new ListBuffer<>();
 236             dedupedLambdas = new HashMap<>();
 237             deserializeCases = new HashMap<>();
 238             MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType,
 239                     List.nil(), syms.methodClass);
 240             deserMethodSym = makePrivateSyntheticMethod(STATIC, names.deserializeLambda, type, clazz.sym);
 241             deserParamSym = new VarSymbol(FINAL, names.fromString("lambda"),
 242                     syms.serializedLambdaType, deserMethodSym);
 243         }
 244 
 245         private void addMethod(JCTree decl) {
 246             appendedMethodList = appendedMethodList.prepend(decl);
 247         }
 248     }
 249 
 250     // <editor-fold defaultstate="collapsed" desc="translate methods">
 251     @Override
 252     public <T extends JCTree> T translate(T tree) {
 253         TranslationContext<?> newContext = contextMap.get(tree);
 254         return translate(tree, newContext != null ? newContext : context);
 255     }
 256 
 257     <T extends JCTree> T translate(T tree, TranslationContext<?> newContext) {
 258         TranslationContext<?> prevContext = context;
 259         try {
 260             context = newContext;
 261             return super.translate(tree);
 262         }
 263         finally {
 264             context = prevContext;
 265         }
 266     }
 267 
 268     <T extends JCTree> List<T> translate(List<T> trees, TranslationContext<?> newContext) {
 269         ListBuffer<T> buf = new ListBuffer<>();
 270         for (T tree : trees) {
 271             buf.append(translate(tree, newContext));
 272         }
 273         return buf.toList();
 274     }
 275 
 276     public JCTree translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
 277         this.make = make;
 278         this.attrEnv = env;
 279         this.context = null;
 280         this.contextMap = new HashMap<>();
 281         return translate(cdef);
 282     }
 283     // </editor-fold>
 284 
 285     // <editor-fold defaultstate="collapsed" desc="visitor methods">
 286     /**
 287      * Visit a class.
 288      * Maintain the translatedMethodList across nested classes.
 289      * Append the translatedMethodList to the class after it is translated.
 290      * @param tree
 291      */
 292     @Override
 293     public void visitClassDef(JCClassDecl tree) {
 294         if (tree.sym.owner.kind == PCK) {
 295             //analyze class
 296             tree = analyzer.analyzeAndPreprocessClass(tree);
 297         }
 298         KlassInfo prevKlassInfo = kInfo;
 299         try {
 300             kInfo = new KlassInfo(tree);
 301             super.visitClassDef(tree);
 302             if (!kInfo.deserializeCases.isEmpty()) {
 303                 int prevPos = make.pos;
 304                 try {
 305                     make.at(tree);
 306                     kInfo.addMethod(makeDeserializeMethod(tree.sym));
 307                 } finally {
 308                     make.at(prevPos);
 309                 }
 310             }
 311             //add all translated instance methods here
 312             List<JCTree> newMethods = kInfo.appendedMethodList.toList();
 313             tree.defs = tree.defs.appendList(newMethods);
 314             for (JCTree lambda : newMethods) {
 315                 tree.sym.members().enter(((JCMethodDecl)lambda).sym);
 316             }
 317             result = tree;
 318         } finally {
 319             kInfo = prevKlassInfo;
 320         }
 321     }
 322 
 323     /**
 324      * Translate a lambda into a method to be inserted into the class.
 325      * Then replace the lambda site with an invokedynamic call of to lambda
 326      * meta-factory, which will use the lambda method.
 327      * @param tree
 328      */
 329     @Override
 330     public void visitLambda(JCLambda tree) {
 331         LambdaTranslationContext localContext = (LambdaTranslationContext)context;
 332         MethodSymbol sym = localContext.translatedSym;
 333         MethodType lambdaType = (MethodType) sym.type;
 334 
 335         {   /* Type annotation management: Based on where the lambda features, type annotations that
 336                are interior to it, may at this point be attached to the enclosing method, or the first
 337                constructor in the class, or in the enclosing class symbol or in the field whose
 338                initializer is the lambda. In any event, gather up the annotations that belong to the
 339                lambda and attach it to the implementation method.
 340             */
 341 
 342             Symbol owner = localContext.owner;
 343             apportionTypeAnnotations(tree,
 344                     owner::getRawTypeAttributes,
 345                     owner::setTypeAttributes,
 346                     sym::setTypeAttributes);
 347 
 348 
 349             boolean init;
 350             if ((init = (owner.name == names.init)) || owner.name == names.clinit) {
 351                 owner = owner.owner;
 352                 apportionTypeAnnotations(tree,
 353                         init ? owner::getInitTypeAttributes : owner::getClassInitTypeAttributes,
 354                         init ? owner::setInitTypeAttributes : owner::setClassInitTypeAttributes,
 355                         sym::appendUniqueTypeAttributes);
 356             }
 357             if (localContext.self != null && localContext.self.getKind() == ElementKind.FIELD) {
 358                 owner = localContext.self;
 359                 apportionTypeAnnotations(tree,
 360                         owner::getRawTypeAttributes,
 361                         owner::setTypeAttributes,
 362                         sym::appendUniqueTypeAttributes);
 363             }
 364         }
 365 
 366         //create the method declaration hoisting the lambda body
 367         JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
 368                 sym.name,
 369                 make.QualIdent(lambdaType.getReturnType().tsym),
 370                 List.nil(),
 371                 localContext.syntheticParams,
 372                 lambdaType.getThrownTypes() == null ?
 373                     List.nil() :
 374                     make.Types(lambdaType.getThrownTypes()),
 375                 null,
 376                 null);
 377         lambdaDecl.sym = sym;
 378         lambdaDecl.type = lambdaType;
 379 
 380         //translate lambda body
 381         //As the lambda body is translated, all references to lambda locals,
 382         //captured variables, enclosing members are adjusted accordingly
 383         //to refer to the static method parameters (rather than i.e. acessing to
 384         //captured members directly).
 385         lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
 386 
 387         boolean dedupe = false;
 388         if (deduplicateLambdas && !debugLinesOrVars && !localContext.isSerializable()) {
 389             DedupedLambda dedupedLambda = new DedupedLambda(lambdaDecl.sym, lambdaDecl.body);
 390             DedupedLambda existing = kInfo.dedupedLambdas.putIfAbsent(dedupedLambda, dedupedLambda);
 391             if (existing != null) {
 392                 sym = existing.symbol;
 393                 dedupe = true;
 394                 if (verboseDeduplication) log.note(tree, Notes.VerboseL2mDeduplicate(sym));
 395             }
 396         }
 397         if (!dedupe) {
 398             //Add the method to the list of methods to be added to this class.
 399             kInfo.addMethod(lambdaDecl);
 400         }
 401 
 402         //now that we have generated a method for the lambda expression,
 403         //we can translate the lambda into a method reference pointing to the newly
 404         //created method.
 405         //
 406         //Note that we need to adjust the method handle so that it will match the
 407         //signature of the SAM descriptor - this means that the method reference
 408         //should be added the following synthetic arguments:
 409         //
 410         // * the "this" argument if it is an instance method
 411         // * enclosing locals captured by the lambda expression
 412 
 413         ListBuffer<JCExpression> syntheticInits = new ListBuffer<>();
 414 
 415         if (localContext.methodReferenceReceiver != null) {
 416             syntheticInits.append(localContext.methodReferenceReceiver);
 417         } else if (!sym.isStatic()) {
 418             syntheticInits.append(makeThis(
 419                     sym.owner.enclClass().asType(),
 420                     localContext.owner.enclClass()));
 421         }
 422 
 423         //add captured locals
 424         for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
 425             if (fv != localContext.self) {
 426                 JCTree captured_local = make.Ident(fv).setType(fv.type);
 427                 syntheticInits.append((JCExpression) captured_local);
 428             }
 429         }
 430         // add captured outer this instances (used only when `this' capture itself is illegal)
 431         for (Symbol fv : localContext.getSymbolMap(CAPTURED_OUTER_THIS).keySet()) {
 432             JCTree captured_local = make.QualThis(fv.type);
 433             syntheticInits.append((JCExpression) captured_local);
 434         }
 435 
 436         //then, determine the arguments to the indy call
 437         List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
 438 
 439         //build a sam instance using an indy call to the meta-factory
 440         int refKind = referenceKind(sym);
 441 
 442         //convert to an invokedynamic call
 443         result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
 444     }
 445 
 446     // where
 447         // Reassign type annotations from the source that should really belong to the lambda
 448         private void apportionTypeAnnotations(JCLambda tree,
 449                                               Supplier<List<Attribute.TypeCompound>> source,
 450                                               Consumer<List<Attribute.TypeCompound>> owner,
 451                                               Consumer<List<Attribute.TypeCompound>> lambda) {
 452 
 453             ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>();
 454             ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>();
 455 
 456             for (Attribute.TypeCompound tc : source.get()) {
 457                 if (tc.position.onLambda == tree) {
 458                     lambdaTypeAnnos.append(tc);
 459                 } else {
 460                     ownerTypeAnnos.append(tc);
 461                 }
 462             }
 463             if (lambdaTypeAnnos.nonEmpty()) {
 464                 owner.accept(ownerTypeAnnos.toList());
 465                 lambda.accept(lambdaTypeAnnos.toList());
 466             }
 467         }
 468 
 469     private JCIdent makeThis(Type type, Symbol owner) {
 470         VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
 471                 names._this,
 472                 type,
 473                 owner);
 474         return make.Ident(_this);
 475     }
 476 
 477     /**
 478      * Translate a method reference into an invokedynamic call to the
 479      * meta-factory.
 480      * @param tree
 481      */
 482     @Override
 483     public void visitReference(JCMemberReference tree) {
 484         ReferenceTranslationContext localContext = (ReferenceTranslationContext)context;
 485 
 486         //first determine the method symbol to be used to generate the sam instance
 487         //this is either the method reference symbol, or the bridged reference symbol
 488         Symbol refSym = tree.sym;
 489 
 490         //the qualifying expression is treated as a special captured arg
 491         JCExpression init;
 492         switch(tree.kind) {
 493 
 494             case IMPLICIT_INNER:    /** Inner :: new */
 495             case SUPER:             /** super :: instMethod */
 496                 init = makeThis(
 497                     localContext.owner.enclClass().asType(),
 498                     localContext.owner.enclClass());
 499                 break;
 500 
 501             case BOUND:             /** Expr :: instMethod */
 502                 init = tree.getQualifierExpression();
 503                 init = attr.makeNullCheck(init);
 504                 break;
 505 
 506             case UNBOUND:           /** Type :: instMethod */
 507             case STATIC:            /** Type :: staticMethod */
 508             case TOPLEVEL:          /** Top level :: new */
 509             case ARRAY_CTOR:        /** ArrayType :: new */
 510                 init = null;
 511                 break;
 512 
 513             default:
 514                 throw new InternalError("Should not have an invalid kind");
 515         }
 516 
 517         List<JCExpression> indy_args = init==null? List.nil() : translate(List.of(init), localContext.prev);
 518 
 519 
 520         //build a sam instance using an indy call to the meta-factory
 521         result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
 522     }
 523 
 524     /**
 525      * Translate identifiers within a lambda to the mapped identifier
 526      * @param tree
 527      */
 528     @Override
 529     public void visitIdent(JCIdent tree) {
 530         if (context == null || !analyzer.lambdaIdentSymbolFilter(tree.sym)) {
 531             super.visitIdent(tree);
 532         } else {
 533             int prevPos = make.pos;
 534             try {
 535                 make.at(tree);
 536 
 537                 LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
 538                 JCTree ltree = lambdaContext.translate(tree);
 539                 if (ltree != null) {
 540                     result = ltree;
 541                 } else {
 542                     //access to untranslated symbols (i.e. compile-time constants,
 543                     //members defined inside the lambda body, etc.) )
 544                     super.visitIdent(tree);
 545                 }
 546             } finally {
 547                 make.at(prevPos);
 548             }
 549         }
 550     }
 551 
 552     /**
 553      * Translate qualified `this' references within a lambda to the mapped identifier
 554      * @param tree
 555      */
 556     @Override
 557     public void visitSelect(JCFieldAccess tree) {
 558         if (context == null || !analyzer.lambdaFieldAccessFilter(tree)) {
 559             super.visitSelect(tree);
 560         } else {
 561             int prevPos = make.pos;
 562             try {
 563                 make.at(tree);
 564 
 565                 LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
 566                 JCTree ltree = lambdaContext.translate(tree);
 567                 if (ltree != null) {
 568                     result = ltree;
 569                 } else {
 570                     super.visitSelect(tree);
 571                 }
 572             } finally {
 573                 make.at(prevPos);
 574             }
 575         }
 576     }
 577 
 578     /**
 579      * Translate instance creation expressions with implicit enclosing instances
 580      * @param tree
 581      */
 582     @Override
 583     public void visitNewClass(JCNewClass tree) {
 584         if (context == null || !analyzer.lambdaNewClassFilter(context, tree)) {
 585             super.visitNewClass(tree);
 586         } else {
 587             int prevPos = make.pos;
 588             try {
 589                 make.at(tree);
 590 
 591                 LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
 592                 tree = lambdaContext.translate(tree);
 593                 super.visitNewClass(tree);
 594             } finally {
 595                 make.at(prevPos);
 596             }
 597         }
 598     }
 599 
 600     @Override
 601     public void visitVarDef(JCVariableDecl tree) {
 602         LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context;
 603         if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
 604             tree.init = translate(tree.init);
 605             tree.sym = (VarSymbol) lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym);
 606             result = tree;
 607         } else if (context != null && lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) {
 608             JCExpression init = translate(tree.init);
 609             VarSymbol xsym = (VarSymbol)lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym);
 610             int prevPos = make.pos;
 611             try {
 612                 result = make.at(tree).VarDef(xsym, init);
 613             } finally {
 614                 make.at(prevPos);
 615             }
 616             // Replace the entered symbol for this variable
 617             WriteableScope sc = tree.sym.owner.members();
 618             if (sc != null) {
 619                 sc.remove(tree.sym);
 620                 sc.enter(xsym);
 621             }
 622         } else {
 623             super.visitVarDef(tree);
 624         }
 625     }
 626 
 627     // </editor-fold>
 628 
 629     // <editor-fold defaultstate="collapsed" desc="Translation helper methods">
 630 
 631     private JCBlock makeLambdaBody(JCLambda tree, JCMethodDecl lambdaMethodDecl) {
 632         return tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION ?
 633                 makeLambdaExpressionBody((JCExpression)tree.body, lambdaMethodDecl) :
 634                 makeLambdaStatementBody((JCBlock)tree.body, lambdaMethodDecl, tree.canCompleteNormally);
 635     }
 636 
 637     private JCBlock makeLambdaExpressionBody(JCExpression expr, JCMethodDecl lambdaMethodDecl) {
 638         Type restype = lambdaMethodDecl.type.getReturnType();
 639         boolean isLambda_void = expr.type.hasTag(VOID);
 640         boolean isTarget_void = restype.hasTag(VOID);
 641         boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
 642         int prevPos = make.pos;
 643         try {
 644             if (isTarget_void) {
 645                 //target is void:
 646                 // BODY;
 647                 JCStatement stat = make.at(expr).Exec(expr);
 648                 return make.Block(0, List.of(stat));
 649             } else if (isLambda_void && isTarget_Void) {
 650                 //void to Void conversion:
 651                 // BODY; return null;
 652                 ListBuffer<JCStatement> stats = new ListBuffer<>();
 653                 stats.append(make.at(expr).Exec(expr));
 654                 stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
 655                 return make.Block(0, stats.toList());
 656             } else {
 657                 //non-void to non-void conversion:
 658                 // return BODY;
 659                 return make.at(expr).Block(0, List.of(make.Return(expr)));
 660             }
 661         } finally {
 662             make.at(prevPos);
 663         }
 664     }
 665 
 666     private JCBlock makeLambdaStatementBody(JCBlock block, final JCMethodDecl lambdaMethodDecl, boolean completeNormally) {
 667         final Type restype = lambdaMethodDecl.type.getReturnType();
 668         final boolean isTarget_void = restype.hasTag(VOID);
 669         boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
 670 
 671         class LambdaBodyTranslator extends TreeTranslator {
 672 
 673             @Override
 674             public void visitClassDef(JCClassDecl tree) {
 675                 //do NOT recurse on any inner classes
 676                 result = tree;
 677             }
 678 
 679             @Override
 680             public void visitLambda(JCLambda tree) {
 681                 //do NOT recurse on any nested lambdas
 682                 result = tree;
 683             }
 684 
 685             @Override
 686             public void visitReturn(JCReturn tree) {
 687                 boolean isLambda_void = tree.expr == null;
 688                 if (isTarget_void && !isLambda_void) {
 689                     //Void to void conversion:
 690                     // { TYPE $loc = RET-EXPR; return; }
 691                     VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym);
 692                     JCVariableDecl varDef = make.VarDef(loc, tree.expr);
 693                     result = make.Block(0, List.of(varDef, make.Return(null)));
 694                 } else {
 695                     result = tree;
 696                 }
 697 
 698             }
 699         }
 700 
 701         JCBlock trans_block = new LambdaBodyTranslator().translate(block);
 702         if (completeNormally && isTarget_Void) {
 703             //there's no return statement and the lambda (possibly inferred)
 704             //return type is java.lang.Void; emit a synthetic return statement
 705             trans_block.stats = trans_block.stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
 706         }
 707         return trans_block;
 708     }
 709 
 710     private JCMethodDecl makeDeserializeMethod(Symbol kSym) {
 711         ListBuffer<JCCase> cases = new ListBuffer<>();
 712         ListBuffer<JCBreak> breaks = new ListBuffer<>();
 713         for (Map.Entry<String, ListBuffer<JCStatement>> entry : kInfo.deserializeCases.entrySet()) {
 714             JCBreak br = make.Break(null);
 715             breaks.add(br);
 716             List<JCStatement> stmts = entry.getValue().append(br).toList();
 717             cases.add(make.Case(make.Literal(entry.getKey()), stmts));
 718         }
 719         JCSwitch sw = make.Switch(deserGetter("getImplMethodName", syms.stringType), cases.toList());
 720         for (JCBreak br : breaks) {
 721             br.target = sw;
 722         }
 723         JCBlock body = make.Block(0L, List.of(
 724                 sw,
 725                 make.Throw(makeNewClass(
 726                     syms.illegalArgumentExceptionType,
 727                     List.of(make.Literal("Invalid lambda deserialization"))))));
 728         JCMethodDecl deser = make.MethodDef(make.Modifiers(kInfo.deserMethodSym.flags()),
 729                         names.deserializeLambda,
 730                         make.QualIdent(kInfo.deserMethodSym.getReturnType().tsym),
 731                         List.nil(),
 732                         List.of(make.VarDef(kInfo.deserParamSym, null)),
 733                         List.nil(),
 734                         body,
 735                         null);
 736         deser.sym = kInfo.deserMethodSym;
 737         deser.type = kInfo.deserMethodSym.type;
 738         //System.err.printf("DESER: '%s'\n", deser);
 739         return deser;
 740     }
 741 
 742     /** Make an attributed class instance creation expression.
 743      *  @param ctype    The class type.
 744      *  @param args     The constructor arguments.
 745      *  @param cons     The constructor symbol
 746      */
 747     JCNewClass makeNewClass(Type ctype, List<JCExpression> args, Symbol cons) {
 748         JCNewClass tree = make.NewClass(null,
 749             null, make.QualIdent(ctype.tsym), args, null);
 750         tree.constructor = cons;
 751         tree.type = ctype;
 752         return tree;
 753     }
 754 
 755     /** Make an attributed class instance creation expression.
 756      *  @param ctype    The class type.
 757      *  @param args     The constructor arguments.
 758      */
 759     JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
 760         return makeNewClass(ctype, args,
 761                 rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.nil()));
 762      }
 763 
 764     private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
 765             DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
 766         String functionalInterfaceClass = classSig(targetType);
 767         String functionalInterfaceMethodName = samSym.getSimpleName().toString();
 768         String functionalInterfaceMethodSignature = typeSig(types.erasure(samSym.type));
 769         String implClass = classSig(types.erasure(refSym.owner.type));
 770         String implMethodName = refSym.getQualifiedName().toString();
 771         String implMethodSignature = typeSig(types.erasure(refSym.type));
 772 
 773         JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
 774         ListBuffer<JCExpression> serArgs = new ListBuffer<>();
 775         int i = 0;
 776         for (Type t : indyType.getParameterTypes()) {
 777             List<JCExpression> indexAsArg = new ListBuffer<JCExpression>().append(make.Literal(i)).toList();
 778             List<Type> argTypes = new ListBuffer<Type>().append(syms.intType).toList();
 779             serArgs.add(make.TypeCast(types.erasure(t), deserGetter("getCapturedArg", syms.objectType, argTypes, indexAsArg)));
 780             ++i;
 781         }
 782         JCStatement stmt = make.If(
 783                 deserTest(deserTest(deserTest(deserTest(deserTest(
 784                     kindTest,
 785                     "getFunctionalInterfaceClass", functionalInterfaceClass),
 786                     "getFunctionalInterfaceMethodName", functionalInterfaceMethodName),
 787                     "getFunctionalInterfaceMethodSignature", functionalInterfaceMethodSignature),
 788                     "getImplClass", implClass),
 789                     "getImplMethodSignature", implMethodSignature),
 790                 make.Return(makeIndyCall(
 791                     pos,
 792                     syms.lambdaMetafactory,
 793                     names.altMetafactory,
 794                     staticArgs, indyType, serArgs.toList(), samSym.name)),
 795                 null);
 796         ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
 797         if (stmts == null) {
 798             stmts = new ListBuffer<>();
 799             kInfo.deserializeCases.put(implMethodName, stmts);
 800         }
 801         /****
 802         System.err.printf("+++++++++++++++++\n");
 803         System.err.printf("*functionalInterfaceClass: '%s'\n", functionalInterfaceClass);
 804         System.err.printf("*functionalInterfaceMethodName: '%s'\n", functionalInterfaceMethodName);
 805         System.err.printf("*functionalInterfaceMethodSignature: '%s'\n", functionalInterfaceMethodSignature);
 806         System.err.printf("*implMethodKind: %d\n", implMethodKind);
 807         System.err.printf("*implClass: '%s'\n", implClass);
 808         System.err.printf("*implMethodName: '%s'\n", implMethodName);
 809         System.err.printf("*implMethodSignature: '%s'\n", implMethodSignature);
 810         ****/
 811         stmts.append(stmt);
 812     }
 813 
 814     private JCExpression eqTest(Type argType, JCExpression arg1, JCExpression arg2) {
 815         JCBinary testExpr = make.Binary(JCTree.Tag.EQ, arg1, arg2);
 816         testExpr.operator = operators.resolveBinary(testExpr, JCTree.Tag.EQ, argType, argType);
 817         testExpr.setType(syms.booleanType);
 818         return testExpr;
 819     }
 820 
 821     private JCExpression deserTest(JCExpression prev, String func, String lit) {
 822         MethodType eqmt = new MethodType(List.of(syms.objectType), syms.booleanType, List.nil(), syms.methodClass);
 823         Symbol eqsym = rs.resolveQualifiedMethod(null, attrEnv, syms.objectType, names.equals, List.of(syms.objectType), List.nil());
 824         JCMethodInvocation eqtest = make.Apply(
 825                 List.nil(),
 826                 make.Select(deserGetter(func, syms.stringType), eqsym).setType(eqmt),
 827                 List.of(make.Literal(lit)));
 828         eqtest.setType(syms.booleanType);
 829         JCBinary compound = make.Binary(JCTree.Tag.AND, prev, eqtest);
 830         compound.operator = operators.resolveBinary(compound, JCTree.Tag.AND, syms.booleanType, syms.booleanType);
 831         compound.setType(syms.booleanType);
 832         return compound;
 833     }
 834 
 835     private JCExpression deserGetter(String func, Type type) {
 836         return deserGetter(func, type, List.nil(), List.nil());
 837     }
 838 
 839     private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) {
 840         MethodType getmt = new MethodType(argTypes, type, List.nil(), syms.methodClass);
 841         Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.nil());
 842         return make.Apply(
 843                     List.nil(),
 844                     make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt),
 845                     args).setType(type);
 846     }
 847 
 848     /**
 849      * Create new synthetic method with given flags, name, type, owner
 850      */
 851     private MethodSymbol makePrivateSyntheticMethod(long flags, Name name, Type type, Symbol owner) {
 852         return new MethodSymbol(flags | SYNTHETIC | PRIVATE, name, type, owner);
 853     }
 854 
 855     /**
 856      * Create new synthetic variable with given flags, name, type, owner
 857      */
 858     private VarSymbol makeSyntheticVar(long flags, Name name, Type type, Symbol owner) {
 859         return new VarSymbol(flags | SYNTHETIC, name, type, owner);
 860     }
 861 
 862     /**
 863      * Set varargsElement field on a given tree (must be either a new class tree
 864      * or a method call tree)
 865      */
 866     private void setVarargsIfNeeded(JCTree tree, Type varargsElement) {
 867         if (varargsElement != null) {
 868             switch (tree.getTag()) {
 869                 case APPLY: ((JCMethodInvocation)tree).varargsElement = varargsElement; break;
 870                 case NEWCLASS: ((JCNewClass)tree).varargsElement = varargsElement; break;
 871                 case TYPECAST: setVarargsIfNeeded(((JCTypeCast) tree).expr, varargsElement); break;
 872                 default: throw new AssertionError();
 873             }
 874         }
 875     }
 876 
 877     /**
 878      * Convert method/constructor arguments by inserting appropriate cast
 879      * as required by type-erasure - this is needed when bridging a lambda/method
 880      * reference, as the bridged signature might require downcast to be compatible
 881      * with the generated signature.
 882      */
 883     private List<JCExpression> convertArgs(Symbol meth, List<JCExpression> args, Type varargsElement) {
 884        Assert.check(meth.kind == MTH);
 885        List<Type> formals = types.erasure(meth.type).getParameterTypes();
 886        if (varargsElement != null) {
 887            Assert.check((meth.flags() & VARARGS) != 0);
 888        }
 889        return transTypes.translateArgs(args, formals, varargsElement, attrEnv);
 890     }
 891 
 892     // </editor-fold>
 893 
 894     /**
 895      * Converts a method reference which cannot be used directly into a lambda
 896      */
 897     private class MemberReferenceToLambda {
 898 
 899         private final JCMemberReference tree;
 900         private final ReferenceTranslationContext localContext;
 901         private final Symbol owner;
 902         private final ListBuffer<JCExpression> args = new ListBuffer<>();
 903         private final ListBuffer<JCVariableDecl> params = new ListBuffer<>();
 904 
 905         private JCExpression receiverExpression = null;
 906 
 907         MemberReferenceToLambda(JCMemberReference tree, ReferenceTranslationContext localContext, Symbol owner) {
 908             this.tree = tree;
 909             this.localContext = localContext;
 910             this.owner = owner;
 911         }
 912 
 913         JCLambda lambda() {
 914             int prevPos = make.pos;
 915             try {
 916                 make.at(tree);
 917 
 918                 //body generation - this can be either a method call or a
 919                 //new instance creation expression, depending on the member reference kind
 920                 VarSymbol rcvr = addParametersReturnReceiver();
 921                 JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
 922                         ? expressionInvoke(rcvr)
 923                         : expressionNew();
 924 
 925                 JCLambda slam = make.Lambda(params.toList(), expr);
 926                 slam.target = tree.target;
 927                 slam.type = tree.type;
 928                 slam.pos = tree.pos;
 929                 return slam;
 930             } finally {
 931                 make.at(prevPos);
 932             }
 933         }
 934 
 935         /**
 936          * Generate the parameter list for the converted member reference.
 937          *
 938          * @return The receiver variable symbol, if any
 939          */
 940         VarSymbol addParametersReturnReceiver() {
 941             Type samDesc = localContext.bridgedRefSig();
 942             List<Type> samPTypes = samDesc.getParameterTypes();
 943             List<Type> descPTypes = tree.getDescriptorType(types).getParameterTypes();
 944 
 945             // Determine the receiver, if any
 946             VarSymbol rcvr;
 947             switch (tree.kind) {
 948                 case BOUND:
 949                     // The receiver is explicit in the method reference
 950                     rcvr = addParameter("rec$", tree.getQualifierExpression().type, false);
 951                     receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
 952                     break;
 953                 case UNBOUND:
 954                     // The receiver is the first parameter, extract it and
 955                     // adjust the SAM and unerased type lists accordingly
 956                     rcvr = addParameter("rec$", samDesc.getParameterTypes().head, false);
 957                     samPTypes = samPTypes.tail;
 958                     descPTypes = descPTypes.tail;
 959                     break;
 960                 default:
 961                     rcvr = null;
 962                     break;
 963             }
 964             List<Type> implPTypes = tree.sym.type.getParameterTypes();
 965             int implSize = implPTypes.size();
 966             int samSize = samPTypes.size();
 967             // Last parameter to copy from referenced method, exclude final var args
 968             int last = localContext.needsVarArgsConversion() ? implSize - 1 : implSize;
 969 
 970             // Failsafe -- assure match-up
 971             boolean checkForIntersection = tree.varargsElement != null || implSize == descPTypes.size();
 972 
 973             // Use parameter types of the implementation method unless the unerased
 974             // SAM parameter type is an intersection type, in that case use the
 975             // erased SAM parameter type so that the supertype relationship
 976             // the implementation method parameters is not obscured.
 977             // Note: in this loop, the lists implPTypes, samPTypes, and descPTypes
 978             // are used as pointers to the current parameter type information
 979             // and are thus not usable afterwards.
 980             for (int i = 0; implPTypes.nonEmpty() && i < last; ++i) {
 981                 // By default use the implementation method parmeter type
 982                 Type parmType = implPTypes.head;
 983                 // If the unerased parameter type is a type variable whose
 984                 // bound is an intersection (eg. <T extends A & B>) then
 985                 // use the SAM parameter type
 986                 if (checkForIntersection && descPTypes.head.getKind() == TypeKind.TYPEVAR) {
 987                     TypeVar tv = (TypeVar) descPTypes.head;
 988                     if (tv.bound.getKind() == TypeKind.INTERSECTION) {
 989                         parmType = samPTypes.head;
 990                     }
 991                 }
 992                 addParameter("x$" + i, parmType, true);
 993 
 994                 // Advance to the next parameter
 995                 implPTypes = implPTypes.tail;
 996                 samPTypes = samPTypes.tail;
 997                 descPTypes = descPTypes.tail;
 998             }
 999             // Flatten out the var args
1000             for (int i = last; i < samSize; ++i) {
1001                 addParameter("xva$" + i, tree.varargsElement, true);
1002             }
1003 
1004             return rcvr;
1005         }
1006 
1007         JCExpression getReceiverExpression() {
1008             return receiverExpression;
1009         }
1010 
1011         private JCExpression makeReceiver(VarSymbol rcvr) {
1012             if (rcvr == null) return null;
1013             JCExpression rcvrExpr = make.Ident(rcvr);
1014             Type rcvrType = tree.ownerAccessible ? tree.sym.enclClass().type : tree.expr.type;
1015             if (rcvrType == syms.arrayClass.type) {
1016                 // Map the receiver type to the actually type, not just "array"
1017                 rcvrType = tree.getQualifierExpression().type;
1018             }
1019             if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) {
1020                 rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType);
1021             }
1022             return rcvrExpr;
1023         }
1024 
1025         /**
1026          * determine the receiver of the method call - the receiver can
1027          * be a type qualifier, the synthetic receiver parameter or 'super'.
1028          */
1029         private JCExpression expressionInvoke(VarSymbol rcvr) {
1030             JCExpression qualifier =
1031                     (rcvr != null) ?
1032                         makeReceiver(rcvr) :
1033                         tree.getQualifierExpression();
1034 
1035             //create the qualifier expression
1036             JCFieldAccess select = make.Select(qualifier, tree.sym.name);
1037             select.sym = tree.sym;
1038             select.type = tree.sym.erasure(types);
1039 
1040             //create the method call expression
1041             JCExpression apply = make.Apply(List.nil(), select,
1042                     convertArgs(tree.sym, args.toList(), tree.varargsElement)).
1043                     setType(tree.sym.erasure(types).getReturnType());
1044 
1045             apply = transTypes.coerce(attrEnv, apply,
1046                     types.erasure(localContext.tree.referentType.getReturnType()));
1047 
1048             setVarargsIfNeeded(apply, tree.varargsElement);
1049             return apply;
1050         }
1051 
1052         /**
1053          * Lambda body to use for a 'new'.
1054          */
1055         private JCExpression expressionNew() {
1056             if (tree.kind == ReferenceKind.ARRAY_CTOR) {
1057                 //create the array creation expression
1058                 JCNewArray newArr = make.NewArray(
1059                         make.Type(types.elemtype(tree.getQualifierExpression().type)),
1060                         List.of(make.Ident(params.first())),
1061                         null);
1062                 newArr.type = tree.getQualifierExpression().type;
1063                 return newArr;
1064             } else {
1065                 //create the instance creation expression
1066                 //note that method reference syntax does not allow an explicit
1067                 //enclosing class (so the enclosing class is null)
1068                 // but this may need to be patched up later with the proxy for the outer this
1069                 JCNewClass newClass = make.NewClass(null,
1070                         List.nil(),
1071                         make.Type(tree.getQualifierExpression().type),
1072                         convertArgs(tree.sym, args.toList(), tree.varargsElement),
1073                         null);
1074                 newClass.constructor = tree.sym;
1075                 newClass.constructorType = tree.sym.erasure(types);
1076                 newClass.type = tree.getQualifierExpression().type;
1077                 setVarargsIfNeeded(newClass, tree.varargsElement);
1078                 return newClass;
1079             }
1080         }
1081 
1082         private VarSymbol addParameter(String name, Type p, boolean genArg) {
1083             VarSymbol vsym = new VarSymbol(PARAMETER | SYNTHETIC, names.fromString(name), p, owner);
1084             vsym.pos = tree.pos;
1085             params.append(make.VarDef(vsym, null));
1086             if (genArg) {
1087                 args.append(make.Ident(vsym));
1088             }
1089             return vsym;
1090         }
1091     }
1092 
1093     private MethodType typeToMethodType(Type mt) {
1094         Type type = types.erasure(mt);
1095         return new MethodType(type.getParameterTypes(),
1096                         type.getReturnType(),
1097                         type.getThrownTypes(),
1098                         syms.methodClass);
1099     }
1100 
1101     /**
1102      * Generate an indy method call to the meta factory
1103      */
1104     private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context,
1105             int refKind, Symbol refSym, List<JCExpression> indy_args) {
1106         JCFunctionalExpression tree = context.tree;
1107         //determine the static bsm args
1108         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.target.tsym);
1109         List<Object> staticArgs = List.of(
1110                 typeToMethodType(samSym.type),
1111                 new Pool.MethodHandle(refKind, refSym, types),
1112                 typeToMethodType(tree.getDescriptorType(types)));
1113 
1114         //computed indy arg types
1115         ListBuffer<Type> indy_args_types = new ListBuffer<>();
1116         for (JCExpression arg : indy_args) {
1117             indy_args_types.append(arg.type);
1118         }
1119 
1120         //finally, compute the type of the indy call
1121         MethodType indyType = new MethodType(indy_args_types.toList(),
1122                 tree.type,
1123                 List.nil(),
1124                 syms.methodClass);
1125 
1126         Name metafactoryName = context.needsAltMetafactory() ?
1127                 names.altMetafactory : names.metafactory;
1128 
1129         if (context.needsAltMetafactory()) {
1130             ListBuffer<Object> markers = new ListBuffer<>();
1131             List<Type> targets = tree.target.isIntersection() ?
1132                     types.directSupertypes(tree.target) :
1133                     List.nil();
1134             for (Type t : targets) {
1135                 t = types.erasure(t);
1136                 if (t.tsym != syms.serializableType.tsym &&
1137                     t.tsym != tree.type.tsym &&
1138                     t.tsym != syms.objectType.tsym) {
1139                     markers.append(t.tsym);
1140                 }
1141             }
1142             int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
1143             boolean hasMarkers = markers.nonEmpty();
1144             boolean hasBridges = context.bridges.nonEmpty();
1145             if (hasMarkers) {
1146                 flags |= FLAG_MARKERS;
1147             }
1148             if (hasBridges) {
1149                 flags |= FLAG_BRIDGES;
1150             }
1151             staticArgs = staticArgs.append(flags);
1152             if (hasMarkers) {
1153                 staticArgs = staticArgs.append(markers.length());
1154                 staticArgs = staticArgs.appendList(markers.toList());
1155             }
1156             if (hasBridges) {
1157                 staticArgs = staticArgs.append(context.bridges.length() - 1);
1158                 for (Symbol s : context.bridges) {
1159                     Type s_erasure = s.erasure(types);
1160                     if (!types.isSameType(s_erasure, samSym.erasure(types))) {
1161                         staticArgs = staticArgs.append(s.erasure(types));
1162                     }
1163                 }
1164             }
1165             if (context.isSerializable()) {
1166                 int prevPos = make.pos;
1167                 try {
1168                     make.at(kInfo.clazz);
1169                     addDeserializationCase(refKind, refSym, tree.type, samSym,
1170                             tree, staticArgs, indyType);
1171                 } finally {
1172                     make.at(prevPos);
1173                 }
1174             }
1175         }
1176 
1177         return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name);
1178     }
1179 
1180     /**
1181      * Generate an indy method call with given name, type and static bootstrap
1182      * arguments types
1183      */
1184     private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
1185             List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
1186             Name methName) {
1187         int prevPos = make.pos;
1188         try {
1189             make.at(pos);
1190             List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
1191                     syms.stringType,
1192                     syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
1193 
1194             Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
1195                     bsmName, bsm_staticArgs, List.nil());
1196 
1197             DynamicMethodSymbol dynSym =
1198                     new DynamicMethodSymbol(methName,
1199                                             syms.noSymbol,
1200                                             bsm.isStatic() ?
1201                                                 ClassFile.REF_invokeStatic :
1202                                                 ClassFile.REF_invokeVirtual,
1203                                             (MethodSymbol)bsm,
1204                                             indyType,
1205                                             staticArgs.toArray());
1206             JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
1207             DynamicMethodSymbol existing = kInfo.dynMethSyms.putIfAbsent(
1208                     new DynamicMethod(dynSym, types), dynSym);
1209             qualifier.sym = existing != null ? existing : dynSym;
1210             qualifier.type = indyType.getReturnType();
1211 
1212             JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, indyArgs);
1213             proxyCall.type = indyType.getReturnType();
1214             return proxyCall;
1215         } finally {
1216             make.at(prevPos);
1217         }
1218     }
1219     //where
1220     private List<Type> bsmStaticArgToTypes(List<Object> args) {
1221         ListBuffer<Type> argtypes = new ListBuffer<>();
1222         for (Object arg : args) {
1223             argtypes.append(bsmStaticArgToType(arg));
1224         }
1225         return argtypes.toList();
1226     }
1227 
1228     private Type bsmStaticArgToType(Object arg) {
1229         Assert.checkNonNull(arg);
1230         if (arg instanceof ClassSymbol) {
1231             return syms.classType;
1232         } else if (arg instanceof Integer) {
1233             return syms.intType;
1234         } else if (arg instanceof Long) {
1235             return syms.longType;
1236         } else if (arg instanceof Float) {
1237             return syms.floatType;
1238         } else if (arg instanceof Double) {
1239             return syms.doubleType;
1240         } else if (arg instanceof String) {
1241             return syms.stringType;
1242         } else if (arg instanceof Pool.MethodHandle) {
1243             return syms.methodHandleType;
1244         } else if (arg instanceof MethodType) {
1245             return syms.methodTypeType;
1246         } else {
1247             Assert.error("bad static arg " + arg.getClass());
1248             return null;
1249         }
1250     }
1251 
1252     /**
1253      * Get the opcode associated with this method reference
1254      */
1255     private int referenceKind(Symbol refSym) {
1256         if (refSym.isConstructor()) {
1257             return ClassFile.REF_newInvokeSpecial;
1258         } else {
1259             if (refSym.isStatic()) {
1260                 return ClassFile.REF_invokeStatic;
1261             } else if ((refSym.flags() & PRIVATE) != 0) {
1262                 return ClassFile.REF_invokeSpecial;
1263             } else if (refSym.enclClass().isInterface()) {
1264                 return ClassFile.REF_invokeInterface;
1265             } else {
1266                 return ClassFile.REF_invokeVirtual;
1267             }
1268         }
1269     }
1270 
1271     // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
1272     /**
1273      * This visitor collects information about translation of a lambda expression.
1274      * More specifically, it keeps track of the enclosing contexts and captured locals
1275      * accessed by the lambda being translated (as well as other useful info).
1276      * It also translates away problems for LambdaToMethod.
1277      */
1278     class LambdaAnalyzerPreprocessor extends TreeTranslator {
1279 
1280         /** the frame stack - used to reconstruct translation info about enclosing scopes */
1281         private List<Frame> frameStack;
1282 
1283         /**
1284          * keep the count of lambda expression (used to generate unambiguous
1285          * names)
1286          */
1287         private int lambdaCount = 0;
1288 
1289         /**
1290          * List of types undergoing construction via explicit constructor chaining.
1291          */
1292         private List<ClassSymbol> typesUnderConstruction;
1293 
1294         /**
1295          * keep the count of lambda expression defined in given context (used to
1296          * generate unambiguous names for serializable lambdas)
1297          */
1298         private class SyntheticMethodNameCounter {
1299             private Map<String, Integer> map = new HashMap<>();
1300             int getIndex(StringBuilder buf) {
1301                 String temp = buf.toString();
1302                 Integer count = map.get(temp);
1303                 if (count == null) {
1304                     count = 0;
1305                 }
1306                 ++count;
1307                 map.put(temp, count);
1308                 return count;
1309             }
1310         }
1311         private SyntheticMethodNameCounter syntheticMethodNameCounts =
1312                 new SyntheticMethodNameCounter();
1313 
1314         private Map<Symbol, JCClassDecl> localClassDefs;
1315 
1316         /**
1317          * maps for fake clinit symbols to be used as owners of lambda occurring in
1318          * a static var init context
1319          */
1320         private Map<ClassSymbol, Symbol> clinits = new HashMap<>();
1321 
1322         private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) {
1323             frameStack = List.nil();
1324             typesUnderConstruction = List.nil();
1325             localClassDefs = new HashMap<>();
1326             return translate(tree);
1327         }
1328 
1329         @Override
1330         public void visitApply(JCMethodInvocation tree) {
1331             List<ClassSymbol> previousNascentTypes = typesUnderConstruction;
1332             try {
1333                 Name methName = TreeInfo.name(tree.meth);
1334                 if (methName == names._this || methName == names._super) {
1335                     typesUnderConstruction = typesUnderConstruction.prepend(currentClass());
1336                 }
1337                 super.visitApply(tree);
1338             } finally {
1339                 typesUnderConstruction = previousNascentTypes;
1340             }
1341         }
1342             // where
1343             private ClassSymbol currentClass() {
1344                 for (Frame frame : frameStack) {
1345                     if (frame.tree.hasTag(JCTree.Tag.CLASSDEF)) {
1346                         JCClassDecl cdef = (JCClassDecl) frame.tree;
1347                         return cdef.sym;
1348                     }
1349                 }
1350                 return null;
1351             }
1352 
1353         @Override
1354         public void visitBlock(JCBlock tree) {
1355             List<Frame> prevStack = frameStack;
1356             try {
1357                 if (frameStack.nonEmpty() && frameStack.head.tree.hasTag(CLASSDEF)) {
1358                     frameStack = frameStack.prepend(new Frame(tree));
1359                 }
1360                 super.visitBlock(tree);
1361             }
1362             finally {
1363                 frameStack = prevStack;
1364             }
1365         }
1366 
1367         @Override
1368         public void visitClassDef(JCClassDecl tree) {
1369             List<Frame> prevStack = frameStack;
1370             int prevLambdaCount = lambdaCount;
1371             SyntheticMethodNameCounter prevSyntheticMethodNameCounts =
1372                     syntheticMethodNameCounts;
1373             Map<ClassSymbol, Symbol> prevClinits = clinits;
1374             DiagnosticSource prevSource = log.currentSource();
1375             try {
1376                 log.useSource(tree.sym.sourcefile);
1377                 lambdaCount = 0;
1378                 syntheticMethodNameCounts = new SyntheticMethodNameCounter();
1379                 prevClinits = new HashMap<>();
1380                 if (tree.sym.owner.kind == MTH) {
1381                     localClassDefs.put(tree.sym, tree);
1382                 }
1383                 if (directlyEnclosingLambda() != null) {
1384                     tree.sym.owner = owner();
1385                     if (tree.sym.hasOuterInstance()) {
1386                         //if a class is defined within a lambda, the lambda must capture
1387                         //its enclosing instance (if any)
1388                         TranslationContext<?> localContext = context();
1389                         final TypeSymbol outerInstanceSymbol = tree.sym.type.getEnclosingType().tsym;
1390                         while (localContext != null && !localContext.owner.isStatic()) {
1391                             if (localContext.tree.hasTag(LAMBDA)) {
1392                                 JCTree block = capturedDecl(localContext.depth, outerInstanceSymbol);
1393                                 if (block == null) break;
1394                                 ((LambdaTranslationContext)localContext)
1395                                         .addSymbol(outerInstanceSymbol, CAPTURED_THIS);
1396                             }
1397                             localContext = localContext.prev;
1398                         }
1399                     }
1400                 }
1401                 frameStack = frameStack.prepend(new Frame(tree));
1402                 super.visitClassDef(tree);
1403             }
1404             finally {
1405                 log.useSource(prevSource.getFile());
1406                 frameStack = prevStack;
1407                 lambdaCount = prevLambdaCount;
1408                 syntheticMethodNameCounts = prevSyntheticMethodNameCounts;
1409                 clinits = prevClinits;
1410             }
1411         }
1412 
1413         @Override
1414         public void visitIdent(JCIdent tree) {
1415             if (context() != null && lambdaIdentSymbolFilter(tree.sym)) {
1416                 if (tree.sym.kind == VAR &&
1417                         tree.sym.owner.kind == MTH &&
1418                         tree.type.constValue() == null) {
1419                     TranslationContext<?> localContext = context();
1420                     while (localContext != null) {
1421                         if (localContext.tree.getTag() == LAMBDA) {
1422                             JCTree block = capturedDecl(localContext.depth, tree.sym);
1423                             if (block == null) break;
1424                             ((LambdaTranslationContext)localContext)
1425                                     .addSymbol(tree.sym, CAPTURED_VAR);
1426                         }
1427                         localContext = localContext.prev;
1428                     }
1429                 } else if (tree.sym.owner.kind == TYP) {
1430                     TranslationContext<?> localContext = context();
1431                     while (localContext != null  && !localContext.owner.isStatic()) {
1432                         if (localContext.tree.hasTag(LAMBDA)) {
1433                             JCTree block = capturedDecl(localContext.depth, tree.sym);
1434                             if (block == null) break;
1435                             switch (block.getTag()) {
1436                                 case CLASSDEF:
1437                                     JCClassDecl cdecl = (JCClassDecl)block;
1438                                     ((LambdaTranslationContext)localContext)
1439                                             .addSymbol(cdecl.sym, CAPTURED_THIS);
1440                                     break;
1441                                 default:
1442                                     Assert.error("bad block kind");
1443                             }
1444                         }
1445                         localContext = localContext.prev;
1446                     }
1447                 }
1448             }
1449             super.visitIdent(tree);
1450         }
1451 
1452         @Override
1453         public void visitLambda(JCLambda tree) {
1454             analyzeLambda(tree, "lambda.stat");
1455         }
1456 
1457         private void analyzeLambda(JCLambda tree, JCExpression methodReferenceReceiver) {
1458             // Translation of the receiver expression must occur first
1459             JCExpression rcvr = translate(methodReferenceReceiver);
1460             LambdaTranslationContext context = analyzeLambda(tree, "mref.stat.1");
1461             if (rcvr != null) {
1462                 context.methodReferenceReceiver = rcvr;
1463             }
1464         }
1465 
1466         private LambdaTranslationContext analyzeLambda(JCLambda tree, String statKey) {
1467             List<Frame> prevStack = frameStack;
1468             try {
1469                 LambdaTranslationContext context = new LambdaTranslationContext(tree);
1470                 frameStack = frameStack.prepend(new Frame(tree));
1471                 for (JCVariableDecl param : tree.params) {
1472                     context.addSymbol(param.sym, PARAM);
1473                     frameStack.head.addLocal(param.sym);
1474                 }
1475                 contextMap.put(tree, context);
1476                 super.visitLambda(tree);
1477                 context.complete();
1478                 if (dumpLambdaToMethodStats) {
1479                     log.note(tree, diags.noteKey(statKey, context.needsAltMetafactory(), context.translatedSym));
1480                 }
1481                 return context;
1482             }
1483             finally {
1484                 frameStack = prevStack;
1485             }
1486         }
1487 
1488         @Override
1489         public void visitMethodDef(JCMethodDecl tree) {
1490             List<Frame> prevStack = frameStack;
1491             try {
1492                 frameStack = frameStack.prepend(new Frame(tree));
1493                 super.visitMethodDef(tree);
1494             }
1495             finally {
1496                 frameStack = prevStack;
1497             }
1498         }
1499 
1500         @Override
1501         public void visitNewClass(JCNewClass tree) {
1502             TypeSymbol def = tree.type.tsym;
1503             boolean inReferencedClass = currentlyInClass(def);
1504             boolean isLocal = def.isLocal();
1505             if ((inReferencedClass && isLocal || lambdaNewClassFilter(context(), tree))) {
1506                 TranslationContext<?> localContext = context();
1507                 final TypeSymbol outerInstanceSymbol = tree.type.getEnclosingType().tsym;
1508                 while (localContext != null  && !localContext.owner.isStatic()) {
1509                     if (localContext.tree.hasTag(LAMBDA)) {
1510                         if (outerInstanceSymbol != null) {
1511                             JCTree block = capturedDecl(localContext.depth, outerInstanceSymbol);
1512                             if (block == null) break;
1513                         }
1514                         ((LambdaTranslationContext)localContext)
1515                                 .addSymbol(outerInstanceSymbol, CAPTURED_THIS);
1516                     }
1517                     localContext = localContext.prev;
1518                 }
1519             }
1520             if (context() != null && !inReferencedClass && isLocal) {
1521                 LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context();
1522                 captureLocalClassDefs(def, lambdaContext);
1523             }
1524             super.visitNewClass(tree);
1525         }
1526         //where
1527             void captureLocalClassDefs(Symbol csym, final LambdaTranslationContext lambdaContext) {
1528                 JCClassDecl localCDef = localClassDefs.get(csym);
1529                 if (localCDef != null && lambdaContext.freeVarProcessedLocalClasses.add(csym)) {
1530                     BasicFreeVarCollector fvc = lower.new BasicFreeVarCollector() {
1531                         @Override
1532                         void addFreeVars(ClassSymbol c) {
1533                             captureLocalClassDefs(c, lambdaContext);
1534                         }
1535                         @Override
1536                         void visitSymbol(Symbol sym) {
1537                             if (sym.kind == VAR &&
1538                                     sym.owner.kind == MTH &&
1539                                     ((VarSymbol)sym).getConstValue() == null) {
1540                                 TranslationContext<?> localContext = context();
1541                                 while (localContext != null) {
1542                                     if (localContext.tree.getTag() == LAMBDA) {
1543                                         JCTree block = capturedDecl(localContext.depth, sym);
1544                                         if (block == null) break;
1545                                         ((LambdaTranslationContext)localContext).addSymbol(sym, CAPTURED_VAR);
1546                                     }
1547                                     localContext = localContext.prev;
1548                                 }
1549                             }
1550                         }
1551                     };
1552                     fvc.scan(localCDef);
1553                 }
1554         }
1555         //where
1556         boolean currentlyInClass(Symbol csym) {
1557             for (Frame frame : frameStack) {
1558                 if (frame.tree.hasTag(JCTree.Tag.CLASSDEF)) {
1559                     JCClassDecl cdef = (JCClassDecl) frame.tree;
1560                     if (cdef.sym == csym) {
1561                         return true;
1562                     }
1563                 }
1564             }
1565             return false;
1566         }
1567 
1568         /**
1569          * Method references to local class constructors, may, if the local
1570          * class references local variables, have implicit constructor
1571          * parameters added in Lower; As a result, the invokedynamic bootstrap
1572          * information added in the LambdaToMethod pass will have the wrong
1573          * signature. Hooks between Lower and LambdaToMethod have been added to
1574          * handle normal "new" in this case. This visitor converts potentially
1575          * affected method references into a lambda containing a normal
1576          * expression.
1577          *
1578          * @param tree
1579          */
1580         @Override
1581         public void visitReference(JCMemberReference tree) {
1582             ReferenceTranslationContext rcontext = new ReferenceTranslationContext(tree);
1583             contextMap.put(tree, rcontext);
1584             if (rcontext.needsConversionToLambda()) {
1585                  // Convert to a lambda, and process as such
1586                 MemberReferenceToLambda conv = new MemberReferenceToLambda(tree, rcontext, owner());
1587                 analyzeLambda(conv.lambda(), conv.getReceiverExpression());
1588             } else {
1589                 super.visitReference(tree);
1590                 if (dumpLambdaToMethodStats) {
1591                     log.note(tree, Notes.MrefStat(rcontext.needsAltMetafactory(), null));
1592                 }
1593             }
1594         }
1595 
1596         @Override
1597         public void visitSelect(JCFieldAccess tree) {
1598             if (context() != null && tree.sym.kind == VAR &&
1599                         (tree.sym.name == names._this ||
1600                          tree.sym.name == names._super)) {
1601                 // A select of this or super means, if we are in a lambda,
1602                 // we much have an instance context
1603                 TranslationContext<?> localContext = context();
1604                 while (localContext != null  && !localContext.owner.isStatic()) {
1605                     if (localContext.tree.hasTag(LAMBDA)) {
1606                         JCClassDecl clazz = (JCClassDecl)capturedDecl(localContext.depth, tree.sym);
1607                         if (clazz == null) break;
1608                         ((LambdaTranslationContext)localContext).addSymbol(clazz.sym, CAPTURED_THIS);
1609                     }
1610                     localContext = localContext.prev;
1611                 }
1612             }
1613             super.visitSelect(tree);
1614         }
1615 
1616         @Override
1617         public void visitVarDef(JCVariableDecl tree) {
1618             TranslationContext<?> context = context();
1619             LambdaTranslationContext ltc = (context != null && context instanceof LambdaTranslationContext)?
1620                     (LambdaTranslationContext)context :
1621                     null;
1622             if (ltc != null) {
1623                 if (frameStack.head.tree.hasTag(LAMBDA)) {
1624                     ltc.addSymbol(tree.sym, LOCAL_VAR);
1625                 }
1626                 // Check for type variables (including as type arguments).
1627                 // If they occur within class nested in a lambda, mark for erasure
1628                 Type type = tree.sym.asType();
1629                 if (inClassWithinLambda() && !types.isSameType(types.erasure(type), type)) {
1630                     ltc.addSymbol(tree.sym, TYPE_VAR);
1631                 }
1632             }
1633 
1634             List<Frame> prevStack = frameStack;
1635             try {
1636                 if (tree.sym.owner.kind == MTH) {
1637                     frameStack.head.addLocal(tree.sym);
1638                 }
1639                 frameStack = frameStack.prepend(new Frame(tree));
1640                 super.visitVarDef(tree);
1641             }
1642             finally {
1643                 frameStack = prevStack;
1644             }
1645         }
1646 
1647         /**
1648          * Return a valid owner given the current declaration stack
1649          * (required to skip synthetic lambda symbols)
1650          */
1651         private Symbol owner() {
1652             return owner(false);
1653         }
1654 
1655         @SuppressWarnings("fallthrough")
1656         private Symbol owner(boolean skipLambda) {
1657             List<Frame> frameStack2 = frameStack;
1658             while (frameStack2.nonEmpty()) {
1659                 switch (frameStack2.head.tree.getTag()) {
1660                     case VARDEF:
1661                         if (((JCVariableDecl)frameStack2.head.tree).sym.isLocal()) {
1662                             frameStack2 = frameStack2.tail;
1663                             break;
1664                         }
1665                         JCClassDecl cdecl = (JCClassDecl)frameStack2.tail.head.tree;
1666                         return initSym(cdecl.sym,
1667                                 ((JCVariableDecl)frameStack2.head.tree).sym.flags() & STATIC);
1668                     case BLOCK:
1669                         JCClassDecl cdecl2 = (JCClassDecl)frameStack2.tail.head.tree;
1670                         return initSym(cdecl2.sym,
1671                                 ((JCBlock)frameStack2.head.tree).flags & STATIC);
1672                     case CLASSDEF:
1673                         return ((JCClassDecl)frameStack2.head.tree).sym;
1674                     case METHODDEF:
1675                         return ((JCMethodDecl)frameStack2.head.tree).sym;
1676                     case LAMBDA:
1677                         if (!skipLambda)
1678                             return ((LambdaTranslationContext)contextMap
1679                                     .get(frameStack2.head.tree)).translatedSym;
1680                     default:
1681                         frameStack2 = frameStack2.tail;
1682                 }
1683             }
1684             Assert.error();
1685             return null;
1686         }
1687 
1688         private Symbol initSym(ClassSymbol csym, long flags) {
1689             boolean isStatic = (flags & STATIC) != 0;
1690             if (isStatic) {
1691                 /* static clinits are generated in Gen, so we need to use a fake
1692                  * one. Attr creates a fake clinit method while attributing
1693                  * lambda expressions used as initializers of static fields, so
1694                  * let's use that one.
1695                  */
1696                 MethodSymbol clinit = attr.removeClinit(csym);
1697                 if (clinit != null) {
1698                     clinits.put(csym, clinit);
1699                     return clinit;
1700                 }
1701 
1702                 /* if no clinit is found at Attr, then let's try at clinits.
1703                  */
1704                 clinit = (MethodSymbol)clinits.get(csym);
1705                 if (clinit == null) {
1706                     /* no luck, let's create a new one
1707                      */
1708                     clinit = makePrivateSyntheticMethod(STATIC,
1709                             names.clinit,
1710                             new MethodType(List.nil(), syms.voidType,
1711                                 List.nil(), syms.methodClass),
1712                             csym);
1713                     clinits.put(csym, clinit);
1714                 }
1715                 return clinit;
1716             } else {
1717                 //get the first constructor and treat it as the instance init sym
1718                 for (Symbol s : csym.members_field.getSymbolsByName(names.init)) {
1719                     return s;
1720                 }
1721             }
1722             Assert.error("init not found");
1723             return null;
1724         }
1725 
1726         private JCTree directlyEnclosingLambda() {
1727             if (frameStack.isEmpty()) {
1728                 return null;
1729             }
1730             List<Frame> frameStack2 = frameStack;
1731             while (frameStack2.nonEmpty()) {
1732                 switch (frameStack2.head.tree.getTag()) {
1733                     case CLASSDEF:
1734                     case METHODDEF:
1735                         return null;
1736                     case LAMBDA:
1737                         return frameStack2.head.tree;
1738                     default:
1739                         frameStack2 = frameStack2.tail;
1740                 }
1741             }
1742             Assert.error();
1743             return null;
1744         }
1745 
1746         private boolean inClassWithinLambda() {
1747             if (frameStack.isEmpty()) {
1748                 return false;
1749             }
1750             List<Frame> frameStack2 = frameStack;
1751             boolean classFound = false;
1752             while (frameStack2.nonEmpty()) {
1753                 switch (frameStack2.head.tree.getTag()) {
1754                     case LAMBDA:
1755                         return classFound;
1756                     case CLASSDEF:
1757                         classFound = true;
1758                         frameStack2 = frameStack2.tail;
1759                         break;
1760                     default:
1761                         frameStack2 = frameStack2.tail;
1762                 }
1763             }
1764             // No lambda
1765             return false;
1766         }
1767 
1768         /**
1769          * Return the declaration corresponding to a symbol in the enclosing
1770          * scope; the depth parameter is used to filter out symbols defined
1771          * in nested scopes (which do not need to undergo capture).
1772          */
1773         private JCTree capturedDecl(int depth, Symbol sym) {
1774             int currentDepth = frameStack.size() - 1;
1775             for (Frame block : frameStack) {
1776                 switch (block.tree.getTag()) {
1777                     case CLASSDEF:
1778                         ClassSymbol clazz = ((JCClassDecl)block.tree).sym;
1779                         if (clazz.isSubClass(sym, types) || sym.isMemberOf(clazz, types)) {
1780                             return currentDepth > depth ? null : block.tree;
1781                         }
1782                         break;
1783                     case VARDEF:
1784                         if (((JCVariableDecl)block.tree).sym == sym &&
1785                                 sym.owner.kind == MTH) { //only locals are captured
1786                             return currentDepth > depth ? null : block.tree;
1787                         }
1788                         break;
1789                     case BLOCK:
1790                     case METHODDEF:
1791                     case LAMBDA:
1792                         if (block.locals != null && block.locals.contains(sym)) {
1793                             return currentDepth > depth ? null : block.tree;
1794                         }
1795                         break;
1796                     default:
1797                         Assert.error("bad decl kind " + block.tree.getTag());
1798                 }
1799                 currentDepth--;
1800             }
1801             return null;
1802         }
1803 
1804         private TranslationContext<?> context() {
1805             for (Frame frame : frameStack) {
1806                 TranslationContext<?> context = contextMap.get(frame.tree);
1807                 if (context != null) {
1808                     return context;
1809                 }
1810             }
1811             return null;
1812         }
1813 
1814         /**
1815          *  This is used to filter out those identifiers that needs to be adjusted
1816          *  when translating away lambda expressions
1817          */
1818         private boolean lambdaIdentSymbolFilter(Symbol sym) {
1819             return (sym.kind == VAR || sym.kind == MTH)
1820                     && !sym.isStatic()
1821                     && sym.name != names.init;
1822         }
1823 
1824         /**
1825          *  This is used to filter out those select nodes that need to be adjusted
1826          *  when translating away lambda expressions - at the moment, this is the
1827          *  set of nodes that select `this' (qualified this)
1828          */
1829         private boolean lambdaFieldAccessFilter(JCFieldAccess fAccess) {
1830             LambdaTranslationContext lambdaContext =
1831                     context instanceof LambdaTranslationContext ?
1832                             (LambdaTranslationContext) context : null;
1833             return lambdaContext != null
1834                     && !fAccess.sym.isStatic()
1835                     && fAccess.name == names._this
1836                     && (fAccess.sym.owner.kind == TYP)
1837                     && !lambdaContext.translatedSymbols.get(CAPTURED_OUTER_THIS).isEmpty();
1838         }
1839 
1840         /**
1841          * This is used to filter out those new class expressions that need to
1842          * be qualified with an enclosing tree
1843          */
1844         private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) {
1845             if (context != null
1846                     && tree.encl == null
1847                     && tree.def == null
1848                     && !tree.type.getEnclosingType().hasTag(NONE)) {
1849                 Type encl = tree.type.getEnclosingType();
1850                 Type current = context.owner.enclClass().type;
1851                 while (!current.hasTag(NONE)) {
1852                     if (current.tsym.isSubClass(encl.tsym, types)) {
1853                         return true;
1854                     }
1855                     current = current.getEnclosingType();
1856                 }
1857                 return false;
1858             } else {
1859                 return false;
1860             }
1861         }
1862 
1863         private class Frame {
1864             final JCTree tree;
1865             List<Symbol> locals;
1866 
1867             public Frame(JCTree tree) {
1868                 this.tree = tree;
1869             }
1870 
1871             void addLocal(Symbol sym) {
1872                 if (locals == null) {
1873                     locals = List.nil();
1874                 }
1875                 locals = locals.prepend(sym);
1876             }
1877         }
1878 
1879         /**
1880          * This class is used to store important information regarding translation of
1881          * lambda expression/method references (see subclasses).
1882          */
1883         abstract class TranslationContext<T extends JCFunctionalExpression> {
1884 
1885             /** the underlying (untranslated) tree */
1886             final T tree;
1887 
1888             /** points to the adjusted enclosing scope in which this lambda/mref expression occurs */
1889             final Symbol owner;
1890 
1891             /** the depth of this lambda expression in the frame stack */
1892             final int depth;
1893 
1894             /** the enclosing translation context (set for nested lambdas/mref) */
1895             final TranslationContext<?> prev;
1896 
1897             /** list of methods to be bridged by the meta-factory */
1898             final List<Symbol> bridges;
1899 
1900             TranslationContext(T tree) {
1901                 this.tree = tree;
1902                 this.owner = owner(true);
1903                 this.depth = frameStack.size() - 1;
1904                 this.prev = context();
1905                 ClassSymbol csym =
1906                         types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
1907                 this.bridges = types.functionalInterfaceBridges(csym);
1908             }
1909 
1910             /** does this functional expression need to be created using alternate metafactory? */
1911             boolean needsAltMetafactory() {
1912                 return tree.target.isIntersection() ||
1913                         isSerializable() ||
1914                         bridges.length() > 1;
1915             }
1916 
1917             /** does this functional expression require serialization support? */
1918             boolean isSerializable() {
1919                 if (forceSerializable) {
1920                     return true;
1921                 }
1922                 return types.asSuper(tree.target, syms.serializableType.tsym) != null;
1923             }
1924 
1925             /**
1926              * @return Name of the enclosing method to be folded into synthetic
1927              * method name
1928              */
1929             String enclosingMethodName() {
1930                 return syntheticMethodNameComponent(owner.name);
1931             }
1932 
1933             /**
1934              * @return Method name in a form that can be folded into a
1935              * component of a synthetic method name
1936              */
1937             String syntheticMethodNameComponent(Name name) {
1938                 if (name == null) {
1939                     return "null";
1940                 }
1941                 String methodName = name.toString();
1942                 if (methodName.equals("<clinit>")) {
1943                     methodName = "static";
1944                 } else if (methodName.equals("<init>")) {
1945                     methodName = "new";
1946                 }
1947                 return methodName;
1948             }
1949         }
1950 
1951         /**
1952          * This class retains all the useful information about a lambda expression;
1953          * the contents of this class are filled by the LambdaAnalyzer visitor,
1954          * and the used by the main translation routines in order to adjust references
1955          * to captured locals/members, etc.
1956          */
1957         class LambdaTranslationContext extends TranslationContext<JCLambda> {
1958 
1959             /** variable in the enclosing context to which this lambda is assigned */
1960             final Symbol self;
1961 
1962             /** variable in the enclosing context to which this lambda is assigned */
1963             final Symbol assignedTo;
1964 
1965             Map<LambdaSymbolKind, Map<Symbol, Symbol>> translatedSymbols;
1966 
1967             /** the synthetic symbol for the method hoisting the translated lambda */
1968             MethodSymbol translatedSym;
1969 
1970             List<JCVariableDecl> syntheticParams;
1971 
1972             /**
1973              * to prevent recursion, track local classes processed
1974              */
1975             final Set<Symbol> freeVarProcessedLocalClasses;
1976 
1977             /**
1978              * For method references converted to lambdas.  The method
1979              * reference receiver expression. Must be treated like a captured
1980              * variable.
1981              */
1982             JCExpression methodReferenceReceiver;
1983 
1984             LambdaTranslationContext(JCLambda tree) {
1985                 super(tree);
1986                 Frame frame = frameStack.head;
1987                 switch (frame.tree.getTag()) {
1988                     case VARDEF:
1989                         assignedTo = self = ((JCVariableDecl) frame.tree).sym;
1990                         break;
1991                     case ASSIGN:
1992                         self = null;
1993                         assignedTo = TreeInfo.symbol(((JCAssign) frame.tree).getVariable());
1994                         break;
1995                     default:
1996                         assignedTo = self = null;
1997                         break;
1998                  }
1999 
2000                 // This symbol will be filled-in in complete
2001                 this.translatedSym = makePrivateSyntheticMethod(0, null, null, owner.enclClass());
2002 
2003                 translatedSymbols = new EnumMap<>(LambdaSymbolKind.class);
2004 
2005                 translatedSymbols.put(PARAM, new LinkedHashMap<Symbol, Symbol>());
2006                 translatedSymbols.put(LOCAL_VAR, new LinkedHashMap<Symbol, Symbol>());
2007                 translatedSymbols.put(CAPTURED_VAR, new LinkedHashMap<Symbol, Symbol>());
2008                 translatedSymbols.put(CAPTURED_THIS, new LinkedHashMap<Symbol, Symbol>());
2009                 translatedSymbols.put(CAPTURED_OUTER_THIS, new LinkedHashMap<Symbol, Symbol>());
2010                 translatedSymbols.put(TYPE_VAR, new LinkedHashMap<Symbol, Symbol>());
2011 
2012                 freeVarProcessedLocalClasses = new HashSet<>();
2013             }
2014 
2015              /**
2016              * For a serializable lambda, generate a disambiguating string
2017              * which maximizes stability across deserialization.
2018              *
2019              * @return String to differentiate synthetic lambda method names
2020              */
2021             private String serializedLambdaDisambiguation() {
2022                 StringBuilder buf = new StringBuilder();
2023                 // Append the enclosing method signature to differentiate
2024                 // overloaded enclosing methods.  For lambdas enclosed in
2025                 // lambdas, the generated lambda method will not have type yet,
2026                 // but the enclosing method's name will have been generated
2027                 // with this same method, so it will be unique and never be
2028                 // overloaded.
2029                 Assert.check(
2030                         owner.type != null ||
2031                         directlyEnclosingLambda() != null);
2032                 if (owner.type != null) {
2033                     buf.append(typeSig(owner.type));
2034                     buf.append(":");
2035                 }
2036 
2037                 // Add target type info
2038                 buf.append(types.findDescriptorSymbol(tree.type.tsym).owner.flatName());
2039                 buf.append(" ");
2040 
2041                 // Add variable assigned to
2042                 if (assignedTo != null) {
2043                     buf.append(assignedTo.flatName());
2044                     buf.append("=");
2045                 }
2046                 //add captured locals info: type, name, order
2047                 for (Symbol fv : getSymbolMap(CAPTURED_VAR).keySet()) {
2048                     if (fv != self) {
2049                         buf.append(typeSig(fv.type));
2050                         buf.append(" ");
2051                         buf.append(fv.flatName());
2052                         buf.append(",");
2053                     }
2054                 }
2055 
2056                 return buf.toString();
2057             }
2058 
2059             /**
2060              * For a non-serializable lambda, generate a simple method.
2061              *
2062              * @return Name to use for the synthetic lambda method name
2063              */
2064             private Name lambdaName() {
2065                 return names.lambda.append(names.fromString(enclosingMethodName() + "$" + lambdaCount++));
2066             }
2067 
2068             /**
2069              * For a serializable lambda, generate a method name which maximizes
2070              * name stability across deserialization.
2071              *
2072              * @return Name to use for the synthetic lambda method name
2073              */
2074             private Name serializedLambdaName() {
2075                 StringBuilder buf = new StringBuilder();
2076                 buf.append(names.lambda);
2077                 // Append the name of the method enclosing the lambda.
2078                 buf.append(enclosingMethodName());
2079                 buf.append('$');
2080                 // Append a hash of the disambiguating string : enclosing method
2081                 // signature, etc.
2082                 String disam = serializedLambdaDisambiguation();
2083                 buf.append(Integer.toHexString(disam.hashCode()));
2084                 buf.append('$');
2085                 // The above appended name components may not be unique, append
2086                 // a count based on the above name components.
2087                 buf.append(syntheticMethodNameCounts.getIndex(buf));
2088                 String result = buf.toString();
2089                 //System.err.printf("serializedLambdaName: %s -- %s\n", result, disam);
2090                 return names.fromString(result);
2091             }
2092 
2093             /**
2094              * Translate a symbol of a given kind into something suitable for the
2095              * synthetic lambda body
2096              */
2097             Symbol translate(final Symbol sym, LambdaSymbolKind skind) {
2098                 Symbol ret;
2099                 switch (skind) {
2100                     case CAPTURED_THIS:
2101                         ret = sym;  // self represented
2102                         break;
2103                     case TYPE_VAR:
2104                         // Just erase the type var
2105                         ret = new VarSymbol(sym.flags(), sym.name,
2106                                 types.erasure(sym.type), sym.owner);
2107 
2108                         /* this information should also be kept for LVT generation at Gen
2109                          * a Symbol with pos < startPos won't be tracked.
2110                          */
2111                         ((VarSymbol)ret).pos = ((VarSymbol)sym).pos;
2112                         break;
2113                     case CAPTURED_VAR:
2114                         ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, sym.name, types.erasure(sym.type), translatedSym) {
2115                             @Override
2116                             public Symbol baseSymbol() {
2117                                 //keep mapping with original captured symbol
2118                                 return sym;
2119                             }
2120                         };
2121                         break;
2122                     case CAPTURED_OUTER_THIS:
2123                         Name name = names.fromString(new String(sym.flatName().toString().replace('.', '$') + names.dollarThis));
2124                         ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, name, types.erasure(sym.type), translatedSym) {
2125                             @Override
2126                             public Symbol baseSymbol() {
2127                                 //keep mapping with original captured symbol
2128                                 return sym;
2129                             }
2130                         };
2131                         break;
2132                     case LOCAL_VAR:
2133                         ret = new VarSymbol(sym.flags() & FINAL, sym.name, sym.type, translatedSym);
2134                         ((VarSymbol) ret).pos = ((VarSymbol) sym).pos;
2135                         break;
2136                     case PARAM:
2137                         ret = new VarSymbol((sym.flags() & FINAL) | PARAMETER, sym.name, types.erasure(sym.type), translatedSym);
2138                         ((VarSymbol) ret).pos = ((VarSymbol) sym).pos;
2139                         break;
2140                     default:
2141                         Assert.error(skind.name());
2142                         throw new AssertionError();
2143                 }
2144                 if (ret != sym && skind.propagateAnnotations()) {
2145                     ret.setDeclarationAttributes(sym.getRawAttributes());
2146                     ret.setTypeAttributes(sym.getRawTypeAttributes());
2147                 }
2148                 return ret;
2149             }
2150 
2151             void addSymbol(Symbol sym, LambdaSymbolKind skind) {
2152                 if (skind == CAPTURED_THIS && sym != null && sym.kind == TYP && !typesUnderConstruction.isEmpty()) {
2153                     ClassSymbol currentClass = currentClass();
2154                     if (currentClass != null && typesUnderConstruction.contains(currentClass)) {
2155                         // reference must be to enclosing outer instance, mutate capture kind.
2156                         Assert.check(sym != currentClass); // should have been caught right in Attr
2157                         skind = CAPTURED_OUTER_THIS;
2158                     }
2159                 }
2160                 Map<Symbol, Symbol> transMap = getSymbolMap(skind);
2161                 if (!transMap.containsKey(sym)) {
2162                     transMap.put(sym, translate(sym, skind));
2163                 }
2164             }
2165 
2166             Map<Symbol, Symbol> getSymbolMap(LambdaSymbolKind skind) {
2167                 Map<Symbol, Symbol> m = translatedSymbols.get(skind);
2168                 Assert.checkNonNull(m);
2169                 return m;
2170             }
2171 
2172             JCTree translate(JCIdent lambdaIdent) {
2173                 for (LambdaSymbolKind kind : LambdaSymbolKind.values()) {
2174                     Map<Symbol, Symbol> m = getSymbolMap(kind);
2175                     switch(kind) {
2176                         default:
2177                             if (m.containsKey(lambdaIdent.sym)) {
2178                                 Symbol tSym = m.get(lambdaIdent.sym);
2179                                 JCTree t = make.Ident(tSym).setType(lambdaIdent.type);
2180                                 return t;
2181                             }
2182                             break;
2183                         case CAPTURED_OUTER_THIS:
2184                             Optional<Symbol> proxy = m.keySet().stream()
2185                                     .filter(out -> lambdaIdent.sym.isMemberOf(out.type.tsym, types))
2186                                     .reduce((a, b) -> a.isEnclosedBy((ClassSymbol)b) ? a : b);
2187                             if (proxy.isPresent()) {
2188                                 // Transform outer instance variable references anchoring them to the captured synthetic.
2189                                 Symbol tSym = m.get(proxy.get());
2190                                 JCExpression t = make.Ident(tSym).setType(lambdaIdent.sym.owner.type);
2191                                 t = make.Select(t, lambdaIdent.name);
2192                                 t.setType(lambdaIdent.type);
2193                                 TreeInfo.setSymbol(t, lambdaIdent.sym);
2194                                 return t;
2195                             }
2196                             break;
2197                     }
2198                 }
2199                 return null;
2200             }
2201 
2202             /* Translate away qualified this expressions, anchoring them to synthetic parameters that
2203                capture the qualified this handle. `fieldAccess' is guaranteed to one such.
2204             */
2205             public JCTree translate(JCFieldAccess fieldAccess) {
2206                 Assert.check(fieldAccess.name == names._this);
2207                 Map<Symbol, Symbol> m = translatedSymbols.get(LambdaSymbolKind.CAPTURED_OUTER_THIS);
2208                 if (m.containsKey(fieldAccess.sym.owner)) {
2209                     Symbol tSym = m.get(fieldAccess.sym.owner);
2210                     JCExpression t = make.Ident(tSym).setType(fieldAccess.sym.owner.type);
2211                     return t;
2212                 }
2213                 return null;
2214             }
2215 
2216             /* Translate away naked new instance creation expressions with implicit enclosing instances,
2217                anchoring them to synthetic parameters that stand proxy for the qualified outer this handle.
2218             */
2219             public JCNewClass translate(JCNewClass newClass) {
2220                 Assert.check(newClass.clazz.type.tsym.hasOuterInstance() && newClass.encl == null);
2221                 Map<Symbol, Symbol> m = translatedSymbols.get(LambdaSymbolKind.CAPTURED_OUTER_THIS);
2222                 final Type enclosingType = newClass.clazz.type.getEnclosingType();
2223                 if (m.containsKey(enclosingType.tsym)) {
2224                       Symbol tSym = m.get(enclosingType.tsym);
2225                       JCExpression encl = make.Ident(tSym).setType(enclosingType);
2226                       newClass.encl = encl;
2227                 }
2228                 return newClass;
2229             }
2230 
2231             /**
2232              * The translatedSym is not complete/accurate until the analysis is
2233              * finished.  Once the analysis is finished, the translatedSym is
2234              * "completed" -- updated with type information, access modifiers,
2235              * and full parameter list.
2236              */
2237             void complete() {
2238                 if (syntheticParams != null) {
2239                     return;
2240                 }
2241                 boolean inInterface = translatedSym.owner.isInterface();
2242                 boolean thisReferenced = !getSymbolMap(CAPTURED_THIS).isEmpty();
2243 
2244                 // If instance access isn't needed, make it static.
2245                 // Interface instance methods must be default methods.
2246                 // Lambda methods are private synthetic.
2247                 // Inherit ACC_STRICT from the enclosing method, or, for clinit,
2248                 // from the class.
2249                 translatedSym.flags_field = SYNTHETIC | LAMBDA_METHOD |
2250                         owner.flags_field & STRICTFP |
2251                         owner.owner.flags_field & STRICTFP |
2252                         PRIVATE |
2253                         (thisReferenced? (inInterface? DEFAULT : 0) : STATIC);
2254 
2255                 //compute synthetic params
2256                 ListBuffer<JCVariableDecl> params = new ListBuffer<>();
2257                 ListBuffer<VarSymbol> parameterSymbols = new ListBuffer<>();
2258 
2259                 // The signature of the method is augmented with the following
2260                 // synthetic parameters:
2261                 //
2262                 // 1) reference to enclosing contexts captured by the lambda expression
2263                 // 2) enclosing locals captured by the lambda expression
2264                 for (Symbol thisSym : getSymbolMap(CAPTURED_VAR).values()) {
2265                     params.append(make.VarDef((VarSymbol) thisSym, null));
2266                     parameterSymbols.append((VarSymbol) thisSym);
2267                 }
2268                 for (Symbol thisSym : getSymbolMap(CAPTURED_OUTER_THIS).values()) {
2269                     params.append(make.VarDef((VarSymbol) thisSym, null));
2270                     parameterSymbols.append((VarSymbol) thisSym);
2271                 }
2272                 for (Symbol thisSym : getSymbolMap(PARAM).values()) {
2273                     params.append(make.VarDef((VarSymbol) thisSym, null));
2274                     parameterSymbols.append((VarSymbol) thisSym);
2275                 }
2276                 syntheticParams = params.toList();
2277 
2278                 translatedSym.params = parameterSymbols.toList();
2279 
2280                 // Compute and set the lambda name
2281                 translatedSym.name = isSerializable()
2282                         ? serializedLambdaName()
2283                         : lambdaName();
2284 
2285                 //prepend synthetic args to translated lambda method signature
2286                 translatedSym.type = types.createMethodTypeWithParameters(
2287                         generatedLambdaSig(),
2288                         TreeInfo.types(syntheticParams));
2289             }
2290 
2291             Type generatedLambdaSig() {
2292                 return types.erasure(tree.getDescriptorType(types));
2293             }
2294         }
2295 
2296         /**
2297          * This class retains all the useful information about a method reference;
2298          * the contents of this class are filled by the LambdaAnalyzer visitor,
2299          * and the used by the main translation routines in order to adjust method
2300          * references (i.e. in case a bridge is needed)
2301          */
2302         final class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
2303 
2304             final boolean isSuper;
2305 
2306             ReferenceTranslationContext(JCMemberReference tree) {
2307                 super(tree);
2308                 this.isSuper = tree.hasKind(ReferenceKind.SUPER);
2309             }
2310 
2311             /**
2312              * Get the opcode associated with this method reference
2313              */
2314             int referenceKind() {
2315                 return LambdaToMethod.this.referenceKind(tree.sym);
2316             }
2317 
2318             boolean needsVarArgsConversion() {
2319                 return tree.varargsElement != null;
2320             }
2321 
2322             /**
2323              * @return Is this an array operation like clone()
2324              */
2325             boolean isArrayOp() {
2326                 return tree.sym.owner == syms.arrayClass;
2327             }
2328 
2329             boolean receiverAccessible() {
2330                 //hack needed to workaround 292 bug (7087658)
2331                 //when 292 issue is fixed we should remove this and change the backend
2332                 //code to always generate a method handle to an accessible method
2333                 return tree.ownerAccessible;
2334             }
2335 
2336             /**
2337              * The VM does not support access across nested classes (8010319).
2338              * Were that ever to change, this should be removed.
2339              */
2340             boolean isPrivateInOtherClass() {
2341                 return  (tree.sym.flags() & PRIVATE) != 0 &&
2342                         !types.isSameType(
2343                               types.erasure(tree.sym.enclClass().asType()),
2344                               types.erasure(owner.enclClass().asType()));
2345             }
2346 
2347             boolean isProtectedInSuperClassOfEnclosingClassInOtherPackage() {
2348                 return ((tree.sym.flags() & PROTECTED) != 0 &&
2349                         tree.sym.packge() != owner.packge() &&
2350                         !owner.enclClass().isSubClass(tree.sym.owner, types));
2351             }
2352 
2353             /**
2354              * Erasure destroys the implementation parameter subtype
2355              * relationship for intersection types.
2356              * Have similar problems for union types too.
2357              */
2358             boolean interfaceParameterIsIntersectionOrUnionType() {
2359                 List<Type> tl = tree.getDescriptorType(types).getParameterTypes();
2360                 for (; tl.nonEmpty(); tl = tl.tail) {
2361                     Type pt = tl.head;
2362                     switch (pt.getKind()) {
2363                         case INTERSECTION:
2364                         case UNION:
2365                             return true;
2366                         case TYPEVAR:
2367                             TypeVar tv = (TypeVar) pt;
2368                             if (tv.bound.getKind() == TypeKind.INTERSECTION) {
2369                                 return true;
2370                             }
2371                     }
2372                 }
2373                 return false;
2374             }
2375 
2376             /**
2377              * Does this reference need to be converted to a lambda
2378              * (i.e. var args need to be expanded or "super" is used)
2379              */
2380             final boolean needsConversionToLambda() {
2381                 return interfaceParameterIsIntersectionOrUnionType() ||
2382                         isSuper ||
2383                         needsVarArgsConversion() ||
2384                         isArrayOp() ||
2385                         isPrivateInOtherClass() ||
2386                         isProtectedInSuperClassOfEnclosingClassInOtherPackage() ||
2387                         !receiverAccessible() ||
2388                         (tree.getMode() == ReferenceMode.NEW &&
2389                           tree.kind != ReferenceKind.ARRAY_CTOR &&
2390                           (tree.sym.owner.isLocal() || tree.sym.owner.isInner()));
2391             }
2392 
2393             Type generatedRefSig() {
2394                 return types.erasure(tree.sym.type);
2395             }
2396 
2397             Type bridgedRefSig() {
2398                 return types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
2399             }
2400         }
2401     }
2402     // </editor-fold>
2403 
2404     /*
2405      * These keys provide mappings for various translated lambda symbols
2406      * and the prevailing order must be maintained.
2407      */
2408     enum LambdaSymbolKind {
2409         PARAM,          // original to translated lambda parameters
2410         LOCAL_VAR,      // original to translated lambda locals
2411         CAPTURED_VAR,   // variables in enclosing scope to translated synthetic parameters
2412         CAPTURED_THIS,  // class symbols to translated synthetic parameters (for captured member access)
2413         CAPTURED_OUTER_THIS, // used when `this' capture is illegal, but outer this capture is legit (JDK-8129740)
2414         TYPE_VAR;      // original to translated lambda type variables
2415 
2416         boolean propagateAnnotations() {
2417             switch (this) {
2418                 case CAPTURED_VAR:
2419                 case CAPTURED_THIS:
2420                 case CAPTURED_OUTER_THIS:
2421                     return false;
2422                 default:
2423                     return true;
2424            }
2425         }
2426     }
2427 
2428     /**
2429      * ****************************************************************
2430      * Signature Generation
2431      * ****************************************************************
2432      */
2433 
2434     private String typeSig(Type type) {
2435         L2MSignatureGenerator sg = new L2MSignatureGenerator();
2436         sg.assembleSig(type);
2437         return sg.toString();
2438     }
2439 
2440     private String classSig(Type type) {
2441         L2MSignatureGenerator sg = new L2MSignatureGenerator();
2442         sg.assembleClassSig(type);
2443         return sg.toString();
2444     }
2445 
2446     /**
2447      * Signature Generation
2448      */
2449     private class L2MSignatureGenerator extends Types.SignatureGenerator {
2450 
2451         /**
2452          * An output buffer for type signatures.
2453          */
2454         StringBuilder sb = new StringBuilder();
2455 
2456         L2MSignatureGenerator() {
2457             super(types);
2458         }
2459 
2460         @Override
2461         protected void append(char ch) {
2462             sb.append(ch);
2463         }
2464 
2465         @Override
2466         protected void append(byte[] ba) {
2467             sb.append(new String(ba));
2468         }
2469 
2470         @Override
2471         protected void append(Name name) {
2472             sb.append(name.toString());
2473         }
2474 
2475         @Override
2476         public String toString() {
2477             return sb.toString();
2478         }
2479     }
2480 }