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