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