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