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