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