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