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