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