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