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