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