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