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