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