Wed, 17 Jul 2013 14:19:25 +0100
8019340: varargs-related warnings are meaningless on signature-polymorphic methods such as MethodHandle.invokeExact
Summary: Disable certain varargs warnings when compiling polymorphic signature calls
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2010, 2013, 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 package com.sun.tools.javac.comp;
27 import com.sun.tools.javac.tree.*;
28 import com.sun.tools.javac.tree.JCTree.*;
29 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
30 import com.sun.tools.javac.tree.TreeMaker;
31 import com.sun.tools.javac.tree.TreeTranslator;
32 import com.sun.tools.javac.code.Attribute;
33 import com.sun.tools.javac.code.Kinds;
34 import com.sun.tools.javac.code.Scope;
35 import com.sun.tools.javac.code.Symbol;
36 import com.sun.tools.javac.code.Symbol.ClassSymbol;
37 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
38 import com.sun.tools.javac.code.Symbol.MethodSymbol;
39 import com.sun.tools.javac.code.Symbol.VarSymbol;
40 import com.sun.tools.javac.code.Symtab;
41 import com.sun.tools.javac.code.Type;
42 import com.sun.tools.javac.code.Type.MethodType;
43 import com.sun.tools.javac.code.Types;
44 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
45 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
46 import com.sun.tools.javac.jvm.*;
47 import com.sun.tools.javac.util.*;
48 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
49 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
51 import java.util.HashMap;
52 import java.util.LinkedHashMap;
53 import java.util.Map;
55 import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*;
56 import static com.sun.tools.javac.code.Flags.*;
57 import static com.sun.tools.javac.code.Kinds.*;
58 import static com.sun.tools.javac.code.TypeTag.*;
59 import static com.sun.tools.javac.tree.JCTree.Tag.*;
61 /**
62 * This pass desugars lambda expressions into static methods
63 *
64 * <p><b>This is NOT part of any supported API.
65 * If you write code that depends on this, you do so at your own risk.
66 * This code and its internal interfaces are subject to change or
67 * deletion without notice.</b>
68 */
69 public class LambdaToMethod extends TreeTranslator {
71 private JCDiagnostic.Factory diags;
72 private Log log;
73 private Lower lower;
74 private Names names;
75 private Symtab syms;
76 private Resolve rs;
77 private TreeMaker make;
78 private Types types;
79 private TransTypes transTypes;
80 private Env<AttrContext> attrEnv;
82 /** the analyzer scanner */
83 private LambdaAnalyzerPreprocessor analyzer;
85 /** map from lambda trees to translation contexts */
86 private Map<JCTree, TranslationContext<?>> contextMap;
88 /** current translation context (visitor argument) */
89 private TranslationContext<?> context;
91 /** info about the current class being processed */
92 private KlassInfo kInfo;
94 /** dump statistics about lambda code generation */
95 private boolean dumpLambdaToMethodStats;
97 /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
98 public static final int FLAG_SERIALIZABLE = 1 << 0;
100 /** Flag for alternate metafactories indicating the lambda object has multiple targets */
101 public static final int FLAG_MARKERS = 1 << 1;
103 private class KlassInfo {
105 /**
106 * list of methods to append
107 */
108 private ListBuffer<JCTree> appendedMethodList;
110 /**
111 * list of deserialization cases
112 */
113 private final Map<String, ListBuffer<JCStatement>> deserializeCases;
115 /**
116 * deserialize method symbol
117 */
118 private final MethodSymbol deserMethodSym;
120 /**
121 * deserialize method parameter symbol
122 */
123 private final VarSymbol deserParamSym;
125 private KlassInfo(Symbol kSym) {
126 appendedMethodList = ListBuffer.lb();
127 deserializeCases = new HashMap<String, ListBuffer<JCStatement>>();
128 long flags = PRIVATE | STATIC | SYNTHETIC;
129 MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType,
130 List.<Type>nil(), syms.methodClass);
131 deserMethodSym = makeSyntheticMethod(flags, names.deserializeLambda, type, kSym);
132 deserParamSym = new VarSymbol(FINAL, names.fromString("lambda"),
133 syms.serializedLambdaType, deserMethodSym);
134 }
136 private void addMethod(JCTree decl) {
137 appendedMethodList = appendedMethodList.prepend(decl);
138 }
139 }
141 // <editor-fold defaultstate="collapsed" desc="Instantiating">
142 private static final Context.Key<LambdaToMethod> unlambdaKey =
143 new Context.Key<LambdaToMethod>();
145 public static LambdaToMethod instance(Context context) {
146 LambdaToMethod instance = context.get(unlambdaKey);
147 if (instance == null) {
148 instance = new LambdaToMethod(context);
149 }
150 return instance;
151 }
153 private LambdaToMethod(Context context) {
154 diags = JCDiagnostic.Factory.instance(context);
155 log = Log.instance(context);
156 lower = Lower.instance(context);
157 names = Names.instance(context);
158 syms = Symtab.instance(context);
159 rs = Resolve.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("dumpLambdaToMethodStats");
166 }
167 // </editor-fold>
169 // <editor-fold defaultstate="collapsed" desc="translate methods">
170 @Override
171 public <T extends JCTree> T translate(T tree) {
172 TranslationContext<?> newContext = contextMap.get(tree);
173 return translate(tree, newContext != null ? newContext : context);
174 }
176 <T extends JCTree> T translate(T tree, TranslationContext<?> newContext) {
177 TranslationContext<?> prevContext = context;
178 try {
179 context = newContext;
180 return super.translate(tree);
181 }
182 finally {
183 context = prevContext;
184 }
185 }
187 <T extends JCTree> List<T> translate(List<T> trees, TranslationContext<?> newContext) {
188 ListBuffer<T> buf = ListBuffer.lb();
189 for (T tree : trees) {
190 buf.append(translate(tree, newContext));
191 }
192 return buf.toList();
193 }
195 public JCTree translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
196 this.make = make;
197 this.attrEnv = env;
198 this.context = null;
199 this.contextMap = new HashMap<JCTree, TranslationContext<?>>();
200 return translate(cdef);
201 }
202 // </editor-fold>
204 // <editor-fold defaultstate="collapsed" desc="visitor methods">
205 /**
206 * Visit a class.
207 * Maintain the translatedMethodList across nested classes.
208 * Append the translatedMethodList to the class after it is translated.
209 * @param tree
210 */
211 @Override
212 public void visitClassDef(JCClassDecl tree) {
213 if (tree.sym.owner.kind == PCK) {
214 //analyze class
215 tree = analyzer.analyzeAndPreprocessClass(tree);
216 }
217 KlassInfo prevKlassInfo = kInfo;
218 try {
219 kInfo = new KlassInfo(tree.sym);
220 super.visitClassDef(tree);
221 if (!kInfo.deserializeCases.isEmpty()) {
222 kInfo.addMethod(makeDeserializeMethod(tree.sym));
223 }
224 //add all translated instance methods here
225 List<JCTree> newMethods = kInfo.appendedMethodList.toList();
226 tree.defs = tree.defs.appendList(newMethods);
227 for (JCTree lambda : newMethods) {
228 tree.sym.members().enter(((JCMethodDecl)lambda).sym);
229 }
230 result = tree;
231 } finally {
232 kInfo = prevKlassInfo;
233 }
234 }
236 /**
237 * Translate a lambda into a method to be inserted into the class.
238 * Then replace the lambda site with an invokedynamic call of to lambda
239 * meta-factory, which will use the lambda method.
240 * @param tree
241 */
242 @Override
243 public void visitLambda(JCLambda tree) {
244 LambdaTranslationContext localContext = (LambdaTranslationContext)context;
245 MethodSymbol sym = (MethodSymbol)localContext.translatedSym;
246 MethodType lambdaType = (MethodType) sym.type;
248 {
249 MethodSymbol owner = (MethodSymbol) localContext.owner;
250 ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
251 ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
253 for (Attribute.TypeCompound tc : owner.getRawTypeAttributes()) {
254 if (tc.position.onLambda == tree) {
255 lambdaTypeAnnos.append(tc);
256 } else {
257 ownerTypeAnnos.append(tc);
258 }
259 }
260 if (lambdaTypeAnnos.nonEmpty()) {
261 owner.setTypeAttributes(ownerTypeAnnos.toList());
262 sym.setTypeAttributes(lambdaTypeAnnos.toList());
263 }
264 }
266 //create the method declaration hoisting the lambda body
267 JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
268 sym.name,
269 make.QualIdent(lambdaType.getReturnType().tsym),
270 List.<JCTypeParameter>nil(),
271 localContext.syntheticParams,
272 lambdaType.getThrownTypes() == null ?
273 List.<JCExpression>nil() :
274 make.Types(lambdaType.getThrownTypes()),
275 null,
276 null);
277 lambdaDecl.sym = sym;
278 lambdaDecl.type = lambdaType;
280 //translate lambda body
281 //As the lambda body is translated, all references to lambda locals,
282 //captured variables, enclosing members are adjusted accordingly
283 //to refer to the static method parameters (rather than i.e. acessing to
284 //captured members directly).
285 lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
287 //Add the method to the list of methods to be added to this class.
288 kInfo.addMethod(lambdaDecl);
290 //now that we have generated a method for the lambda expression,
291 //we can translate the lambda into a method reference pointing to the newly
292 //created method.
293 //
294 //Note that we need to adjust the method handle so that it will match the
295 //signature of the SAM descriptor - this means that the method reference
296 //should be added the following synthetic arguments:
297 //
298 // * the "this" argument if it is an instance method
299 // * enclosing locals captured by the lambda expression
301 ListBuffer<JCExpression> syntheticInits = ListBuffer.lb();
303 if (!sym.isStatic()) {
304 syntheticInits.append(makeThis(
305 sym.owner.enclClass().asType(),
306 localContext.owner.enclClass()));
307 }
309 //add captured locals
310 for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
311 if (fv != localContext.self) {
312 JCTree captured_local = make.Ident(fv).setType(fv.type);
313 syntheticInits.append((JCExpression) captured_local);
314 }
315 }
317 //then, determine the arguments to the indy call
318 List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
320 //build a sam instance using an indy call to the meta-factory
321 int refKind = referenceKind(sym);
323 //convert to an invokedynamic call
324 result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args);
325 }
327 private JCIdent makeThis(Type type, Symbol owner) {
328 VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
329 names._this,
330 type,
331 owner);
332 return make.Ident(_this);
333 }
335 /**
336 * Translate a method reference into an invokedynamic call to the
337 * meta-factory.
338 * @param tree
339 */
340 @Override
341 public void visitReference(JCMemberReference tree) {
342 ReferenceTranslationContext localContext = (ReferenceTranslationContext)context;
344 //first determine the method symbol to be used to generate the sam instance
345 //this is either the method reference symbol, or the bridged reference symbol
346 Symbol refSym = localContext.needsBridge() ?
347 localContext.bridgeSym :
348 tree.sym;
350 //build the bridge method, if needed
351 if (localContext.needsBridge()) {
352 bridgeMemberReference(tree, localContext);
353 }
355 //the qualifying expression is treated as a special captured arg
356 JCExpression init;
357 switch(tree.kind) {
359 case IMPLICIT_INNER: /** Inner :: new */
360 case SUPER: /** super :: instMethod */
361 init = makeThis(
362 localContext.owner.enclClass().asType(),
363 localContext.owner.enclClass());
364 break;
366 case BOUND: /** Expr :: instMethod */
367 init = tree.getQualifierExpression();
368 break;
370 case UNBOUND: /** Type :: instMethod */
371 case STATIC: /** Type :: staticMethod */
372 case TOPLEVEL: /** Top level :: new */
373 case ARRAY_CTOR: /** ArrayType :: new */
374 init = null;
375 break;
377 default:
378 throw new InternalError("Should not have an invalid kind");
379 }
381 List<JCExpression> indy_args = init==null? List.<JCExpression>nil() : translate(List.of(init), localContext.prev);
384 //build a sam instance using an indy call to the meta-factory
385 result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args);
386 }
388 /**
389 * Translate identifiers within a lambda to the mapped identifier
390 * @param tree
391 */
392 @Override
393 public void visitIdent(JCIdent tree) {
394 if (context == null || !analyzer.lambdaIdentSymbolFilter(tree.sym)) {
395 super.visitIdent(tree);
396 } else {
397 LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
398 if (lambdaContext.getSymbolMap(PARAM).containsKey(tree.sym)) {
399 Symbol translatedSym = lambdaContext.getSymbolMap(PARAM).get(tree.sym);
400 result = make.Ident(translatedSym).setType(tree.type);
401 translatedSym.setTypeAttributes(tree.sym.getRawTypeAttributes());
402 } else if (lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
403 Symbol translatedSym = lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym);
404 result = make.Ident(translatedSym).setType(tree.type);
405 translatedSym.setTypeAttributes(tree.sym.getRawTypeAttributes());
406 } else if (lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) {
407 Symbol translatedSym = lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym);
408 result = make.Ident(translatedSym).setType(translatedSym.type);
409 translatedSym.setTypeAttributes(tree.sym.getRawTypeAttributes());
410 } else if (lambdaContext.getSymbolMap(CAPTURED_VAR).containsKey(tree.sym)) {
411 Symbol translatedSym = lambdaContext.getSymbolMap(CAPTURED_VAR).get(tree.sym);
412 result = make.Ident(translatedSym).setType(tree.type);
413 } else {
414 //access to untranslated symbols (i.e. compile-time constants,
415 //members defined inside the lambda body, etc.) )
416 super.visitIdent(tree);
417 }
418 }
419 }
421 @Override
422 public void visitVarDef(JCVariableDecl tree) {
423 LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context;
424 if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
425 JCExpression init = translate(tree.init);
426 result = make.VarDef((VarSymbol)lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym), init);
427 } else if (context != null && lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) {
428 JCExpression init = translate(tree.init);
429 VarSymbol xsym = (VarSymbol)lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym);
430 result = make.VarDef(xsym, init);
431 // Replace the entered symbol for this variable
432 Scope sc = tree.sym.owner.members();
433 if (sc != null) {
434 sc.remove(tree.sym);
435 sc.enter(xsym);
436 }
437 } else {
438 super.visitVarDef(tree);
439 }
440 }
442 // </editor-fold>
444 // <editor-fold defaultstate="collapsed" desc="Translation helper methods">
446 private JCBlock makeLambdaBody(JCLambda tree, JCMethodDecl lambdaMethodDecl) {
447 return tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION ?
448 makeLambdaExpressionBody((JCExpression)tree.body, lambdaMethodDecl) :
449 makeLambdaStatementBody((JCBlock)tree.body, lambdaMethodDecl, tree.canCompleteNormally);
450 }
452 private JCBlock makeLambdaExpressionBody(JCExpression expr, JCMethodDecl lambdaMethodDecl) {
453 Type restype = lambdaMethodDecl.type.getReturnType();
454 boolean isLambda_void = expr.type.hasTag(VOID);
455 boolean isTarget_void = restype.hasTag(VOID);
456 boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
457 if (isTarget_void) {
458 //target is void:
459 // BODY;
460 JCStatement stat = make.Exec(expr);
461 return make.Block(0, List.<JCStatement>of(stat));
462 } else if (isLambda_void && isTarget_Void) {
463 //void to Void conversion:
464 // BODY; return null;
465 ListBuffer<JCStatement> stats = ListBuffer.lb();
466 stats.append(make.Exec(expr));
467 stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
468 return make.Block(0, stats.toList());
469 } else {
470 //non-void to non-void conversion:
471 // return (TYPE)BODY;
472 JCExpression retExpr = transTypes.coerce(attrEnv, expr, restype);
473 return make.Block(0, List.<JCStatement>of(make.Return(retExpr)));
474 }
475 }
477 private JCBlock makeLambdaStatementBody(JCBlock block, final JCMethodDecl lambdaMethodDecl, boolean completeNormally) {
478 final Type restype = lambdaMethodDecl.type.getReturnType();
479 final boolean isTarget_void = restype.hasTag(VOID);
480 boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type);
482 class LambdaBodyTranslator extends TreeTranslator {
484 @Override
485 public void visitClassDef(JCClassDecl tree) {
486 //do NOT recurse on any inner classes
487 result = tree;
488 }
490 @Override
491 public void visitLambda(JCLambda tree) {
492 //do NOT recurse on any nested lambdas
493 result = tree;
494 }
496 @Override
497 public void visitReturn(JCReturn tree) {
498 boolean isLambda_void = tree.expr == null;
499 if (isTarget_void && !isLambda_void) {
500 //Void to void conversion:
501 // { TYPE $loc = RET-EXPR; return; }
502 VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym);
503 JCVariableDecl varDef = make.VarDef(loc, tree.expr);
504 result = make.Block(0, List.<JCStatement>of(varDef, make.Return(null)));
505 } else if (!isTarget_void || !isLambda_void) {
506 //non-void to non-void conversion:
507 // return (TYPE)RET-EXPR;
508 tree.expr = transTypes.coerce(attrEnv, tree.expr, restype);
509 result = tree;
510 } else {
511 result = tree;
512 }
514 }
515 }
517 JCBlock trans_block = new LambdaBodyTranslator().translate(block);
518 if (completeNormally && isTarget_Void) {
519 //there's no return statement and the lambda (possibly inferred)
520 //return type is java.lang.Void; emit a synthetic return statement
521 trans_block.stats = trans_block.stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType)));
522 }
523 return trans_block;
524 }
526 private JCMethodDecl makeDeserializeMethod(Symbol kSym) {
527 ListBuffer<JCCase> cases = ListBuffer.lb();
528 ListBuffer<JCBreak> breaks = ListBuffer.lb();
529 for (Map.Entry<String, ListBuffer<JCStatement>> entry : kInfo.deserializeCases.entrySet()) {
530 JCBreak br = make.Break(null);
531 breaks.add(br);
532 List<JCStatement> stmts = entry.getValue().append(br).toList();
533 cases.add(make.Case(make.Literal(entry.getKey()), stmts));
534 }
535 JCSwitch sw = make.Switch(deserGetter("getImplMethodName", syms.stringType), cases.toList());
536 for (JCBreak br : breaks) {
537 br.target = sw;
538 }
539 JCBlock body = make.Block(0L, List.<JCStatement>of(
540 sw,
541 make.Throw(makeNewClass(
542 syms.illegalArgumentExceptionType,
543 List.<JCExpression>of(make.Literal("Invalid lambda deserialization"))))));
544 JCMethodDecl deser = make.MethodDef(make.Modifiers(kInfo.deserMethodSym.flags()),
545 names.deserializeLambda,
546 make.QualIdent(kInfo.deserMethodSym.getReturnType().tsym),
547 List.<JCTypeParameter>nil(),
548 List.of(make.VarDef(kInfo.deserParamSym, null)),
549 List.<JCExpression>nil(),
550 body,
551 null);
552 deser.sym = kInfo.deserMethodSym;
553 deser.type = kInfo.deserMethodSym.type;
554 //System.err.printf("DESER: '%s'\n", deser);
555 return deser;
556 }
558 /** Make an attributed class instance creation expression.
559 * @param ctype The class type.
560 * @param args The constructor arguments.
561 * @param cons The constructor symbol
562 */
563 JCNewClass makeNewClass(Type ctype, List<JCExpression> args, Symbol cons) {
564 JCNewClass tree = make.NewClass(null,
565 null, make.QualIdent(ctype.tsym), args, null);
566 tree.constructor = cons;
567 tree.type = ctype;
568 return tree;
569 }
571 /** Make an attributed class instance creation expression.
572 * @param ctype The class type.
573 * @param args The constructor arguments.
574 */
575 JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
576 return makeNewClass(ctype, args,
577 rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil()));
578 }
580 private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
581 DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
582 String functionalInterfaceClass = classSig(targetType);
583 String functionalInterfaceMethodName = samSym.getSimpleName().toString();
584 String functionalInterfaceMethodSignature = methodSig(types.erasure(samSym.type));
585 String implClass = classSig(types.erasure(refSym.owner.type));
586 String implMethodName = refSym.getQualifiedName().toString();
587 String implMethodSignature = methodSig(types.erasure(refSym.type));
589 JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
590 ListBuffer<JCExpression> serArgs = ListBuffer.lb();
591 int i = 0;
592 for (Type t : indyType.getParameterTypes()) {
593 List<JCExpression> indexAsArg = ListBuffer.<JCExpression>lb().append(make.Literal(i)).toList();
594 List<Type> argTypes = ListBuffer.<Type>lb().append(syms.intType).toList();
595 serArgs.add(make.TypeCast(types.erasure(t), deserGetter("getCapturedArg", syms.objectType, argTypes, indexAsArg)));
596 ++i;
597 }
598 JCStatement stmt = make.If(
599 deserTest(deserTest(deserTest(deserTest(deserTest(
600 kindTest,
601 "getFunctionalInterfaceClass", functionalInterfaceClass),
602 "getFunctionalInterfaceMethodName", functionalInterfaceMethodName),
603 "getFunctionalInterfaceMethodSignature", functionalInterfaceMethodSignature),
604 "getImplClass", implClass),
605 "getImplMethodSignature", implMethodSignature),
606 make.Return(makeIndyCall(
607 pos,
608 syms.lambdaMetafactory,
609 names.altMetaFactory,
610 staticArgs, indyType, serArgs.toList())),
611 null);
612 ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
613 if (stmts == null) {
614 stmts = ListBuffer.lb();
615 kInfo.deserializeCases.put(implMethodName, stmts);
616 }
617 /****
618 System.err.printf("+++++++++++++++++\n");
619 System.err.printf("*functionalInterfaceClass: '%s'\n", functionalInterfaceClass);
620 System.err.printf("*functionalInterfaceMethodName: '%s'\n", functionalInterfaceMethodName);
621 System.err.printf("*functionalInterfaceMethodSignature: '%s'\n", functionalInterfaceMethodSignature);
622 System.err.printf("*implMethodKind: %d\n", implMethodKind);
623 System.err.printf("*implClass: '%s'\n", implClass);
624 System.err.printf("*implMethodName: '%s'\n", implMethodName);
625 System.err.printf("*implMethodSignature: '%s'\n", implMethodSignature);
626 ****/
627 stmts.append(stmt);
628 }
630 private JCExpression eqTest(Type argType, JCExpression arg1, JCExpression arg2) {
631 JCBinary testExpr = make.Binary(JCTree.Tag.EQ, arg1, arg2);
632 testExpr.operator = rs.resolveBinaryOperator(null, JCTree.Tag.EQ, attrEnv, argType, argType);
633 testExpr.setType(syms.booleanType);
634 return testExpr;
635 }
637 private JCExpression deserTest(JCExpression prev, String func, String lit) {
638 MethodType eqmt = new MethodType(List.of(syms.objectType), syms.booleanType, List.<Type>nil(), syms.methodClass);
639 Symbol eqsym = rs.resolveQualifiedMethod(null, attrEnv, syms.objectType, names.equals, List.of(syms.objectType), List.<Type>nil());
640 JCMethodInvocation eqtest = make.Apply(
641 List.<JCExpression>nil(),
642 make.Select(deserGetter(func, syms.stringType), eqsym).setType(eqmt),
643 List.<JCExpression>of(make.Literal(lit)));
644 eqtest.setType(syms.booleanType);
645 JCBinary compound = make.Binary(JCTree.Tag.AND, prev, eqtest);
646 compound.operator = rs.resolveBinaryOperator(null, JCTree.Tag.AND, attrEnv, syms.booleanType, syms.booleanType);
647 compound.setType(syms.booleanType);
648 return compound;
649 }
651 private JCExpression deserGetter(String func, Type type) {
652 return deserGetter(func, type, List.<Type>nil(), List.<JCExpression>nil());
653 }
655 private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) {
656 MethodType getmt = new MethodType(argTypes, type, List.<Type>nil(), syms.methodClass);
657 Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.<Type>nil());
658 return make.Apply(
659 List.<JCExpression>nil(),
660 make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt),
661 args).setType(type);
662 }
664 /**
665 * Create new synthetic method with given flags, name, type, owner
666 */
667 private MethodSymbol makeSyntheticMethod(long flags, Name name, Type type, Symbol owner) {
668 return new MethodSymbol(flags | SYNTHETIC, name, type, owner);
669 }
671 /**
672 * Create new synthetic variable with given flags, name, type, owner
673 */
674 private VarSymbol makeSyntheticVar(long flags, String name, Type type, Symbol owner) {
675 return makeSyntheticVar(flags, names.fromString(name), type, owner);
676 }
678 /**
679 * Create new synthetic variable with given flags, name, type, owner
680 */
681 private VarSymbol makeSyntheticVar(long flags, Name name, Type type, Symbol owner) {
682 return new VarSymbol(flags | SYNTHETIC, name, type, owner);
683 }
685 /**
686 * Set varargsElement field on a given tree (must be either a new class tree
687 * or a method call tree)
688 */
689 private void setVarargsIfNeeded(JCTree tree, Type varargsElement) {
690 if (varargsElement != null) {
691 switch (tree.getTag()) {
692 case APPLY: ((JCMethodInvocation)tree).varargsElement = varargsElement; break;
693 case NEWCLASS: ((JCNewClass)tree).varargsElement = varargsElement; break;
694 default: throw new AssertionError();
695 }
696 }
697 }
699 /**
700 * Convert method/constructor arguments by inserting appropriate cast
701 * as required by type-erasure - this is needed when bridging a lambda/method
702 * reference, as the bridged signature might require downcast to be compatible
703 * with the generated signature.
704 */
705 private List<JCExpression> convertArgs(Symbol meth, List<JCExpression> args, Type varargsElement) {
706 Assert.check(meth.kind == Kinds.MTH);
707 List<Type> formals = types.erasure(meth.type).getParameterTypes();
708 if (varargsElement != null) {
709 Assert.check((meth.flags() & VARARGS) != 0);
710 }
711 return transTypes.translateArgs(args, formals, varargsElement, attrEnv);
712 }
714 // </editor-fold>
716 /**
717 * Generate an adapter method "bridge" for a method reference which cannot
718 * be used directly.
719 */
720 private class MemberReferenceBridger {
722 private final JCMemberReference tree;
723 private final ReferenceTranslationContext localContext;
724 private final ListBuffer<JCExpression> args = ListBuffer.lb();
725 private final ListBuffer<JCVariableDecl> params = ListBuffer.lb();
727 MemberReferenceBridger(JCMemberReference tree, ReferenceTranslationContext localContext) {
728 this.tree = tree;
729 this.localContext = localContext;
730 }
732 /**
733 * Generate the bridge
734 */
735 JCMethodDecl bridge() {
736 int prevPos = make.pos;
737 try {
738 make.at(tree);
739 Type samDesc = localContext.bridgedRefSig();
740 List<Type> samPTypes = samDesc.getParameterTypes();
742 //an extra argument is prepended to the signature of the bridge in case
743 //the member reference is an instance method reference (in which case
744 //the receiver expression is passed to the bridge itself).
745 Type recType = null;
746 switch (tree.kind) {
747 case IMPLICIT_INNER:
748 recType = tree.sym.owner.type.getEnclosingType();
749 break;
750 case BOUND:
751 recType = tree.getQualifierExpression().type;
752 break;
753 case UNBOUND:
754 recType = samPTypes.head;
755 samPTypes = samPTypes.tail;
756 break;
757 }
759 //generate the parameter list for the bridged member reference - the
760 //bridge signature will match the signature of the target sam descriptor
762 VarSymbol rcvr = (recType == null)
763 ? null
764 : addParameter("rec$", recType, false);
766 List<Type> refPTypes = tree.sym.type.getParameterTypes();
767 int refSize = refPTypes.size();
768 int samSize = samPTypes.size();
769 // Last parameter to copy from referenced method
770 int last = localContext.needsVarArgsConversion() ? refSize - 1 : refSize;
772 List<Type> l = refPTypes;
773 // Use parameter types of the referenced method, excluding final var args
774 for (int i = 0; l.nonEmpty() && i < last; ++i) {
775 addParameter("x$" + i, l.head, true);
776 l = l.tail;
777 }
778 // Flatten out the var args
779 for (int i = last; i < samSize; ++i) {
780 addParameter("xva$" + i, tree.varargsElement, true);
781 }
783 //generate the bridge method declaration
784 JCMethodDecl bridgeDecl = make.MethodDef(make.Modifiers(localContext.bridgeSym.flags()),
785 localContext.bridgeSym.name,
786 make.QualIdent(samDesc.getReturnType().tsym),
787 List.<JCTypeParameter>nil(),
788 params.toList(),
789 tree.sym.type.getThrownTypes() == null
790 ? List.<JCExpression>nil()
791 : make.Types(tree.sym.type.getThrownTypes()),
792 null,
793 null);
794 bridgeDecl.sym = (MethodSymbol) localContext.bridgeSym;
795 bridgeDecl.type = localContext.bridgeSym.type =
796 types.createMethodTypeWithParameters(samDesc, TreeInfo.types(params.toList()));
798 //bridge method body generation - this can be either a method call or a
799 //new instance creation expression, depending on the member reference kind
800 JCExpression bridgeExpr = (tree.getMode() == ReferenceMode.INVOKE)
801 ? bridgeExpressionInvoke(makeReceiver(rcvr))
802 : bridgeExpressionNew();
804 //the body is either a return expression containing a method call,
805 //or the method call itself, depending on whether the return type of
806 //the bridge is non-void/void.
807 bridgeDecl.body = makeLambdaExpressionBody(bridgeExpr, bridgeDecl);
809 return bridgeDecl;
810 } finally {
811 make.at(prevPos);
812 }
813 }
814 //where
815 private JCExpression makeReceiver(VarSymbol rcvr) {
816 if (rcvr == null) return null;
817 JCExpression rcvrExpr = make.Ident(rcvr);
818 Type rcvrType = tree.sym.enclClass().type;
819 if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) {
820 rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType);
821 }
822 return rcvrExpr;
823 }
825 /**
826 * determine the receiver of the bridged method call - the receiver can
827 * be either the synthetic receiver parameter or a type qualifier; the
828 * original qualifier expression is never used here, as it might refer
829 * to symbols not available in the static context of the bridge
830 */
831 private JCExpression bridgeExpressionInvoke(JCExpression rcvr) {
832 JCExpression qualifier =
833 tree.sym.isStatic() ?
834 make.Type(tree.sym.owner.type) :
835 (rcvr != null) ?
836 rcvr :
837 tree.getQualifierExpression();
839 //create the qualifier expression
840 JCFieldAccess select = make.Select(qualifier, tree.sym.name);
841 select.sym = tree.sym;
842 select.type = tree.sym.erasure(types);
844 //create the method call expression
845 JCExpression apply = make.Apply(List.<JCExpression>nil(), select,
846 convertArgs(tree.sym, args.toList(), tree.varargsElement)).
847 setType(tree.sym.erasure(types).getReturnType());
849 apply = transTypes.coerce(apply, localContext.generatedRefSig().getReturnType());
850 setVarargsIfNeeded(apply, tree.varargsElement);
851 return apply;
852 }
854 /**
855 * the enclosing expression is either 'null' (no enclosing type) or set
856 * to the first bridge synthetic parameter
857 */
858 private JCExpression bridgeExpressionNew() {
859 if (tree.kind == ReferenceKind.ARRAY_CTOR) {
860 //create the array creation expression
861 JCNewArray newArr = make.NewArray(
862 make.Type(types.elemtype(tree.getQualifierExpression().type)),
863 List.of(make.Ident(params.first())),
864 null);
865 newArr.type = tree.getQualifierExpression().type;
866 return newArr;
867 } else {
868 JCExpression encl = null;
869 switch (tree.kind) {
870 case UNBOUND:
871 case IMPLICIT_INNER:
872 encl = make.Ident(params.first());
873 }
875 //create the instance creation expression
876 JCNewClass newClass = make.NewClass(encl,
877 List.<JCExpression>nil(),
878 make.Type(tree.getQualifierExpression().type),
879 convertArgs(tree.sym, args.toList(), tree.varargsElement),
880 null);
881 newClass.constructor = tree.sym;
882 newClass.constructorType = tree.sym.erasure(types);
883 newClass.type = tree.getQualifierExpression().type;
884 setVarargsIfNeeded(newClass, tree.varargsElement);
885 return newClass;
886 }
887 }
889 private VarSymbol addParameter(String name, Type p, boolean genArg) {
890 VarSymbol vsym = new VarSymbol(0, names.fromString(name), p, localContext.bridgeSym);
891 params.append(make.VarDef(vsym, null));
892 if (genArg) {
893 args.append(make.Ident(vsym));
894 }
895 return vsym;
896 }
897 }
899 /**
900 * Bridges a member reference - this is needed when:
901 * * Var args in the referenced method need to be flattened away
902 * * super is used
903 */
904 private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) {
905 kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge());
906 }
908 /**
909 * Generate an indy method call to the meta factory
910 */
911 private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory,
912 boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) {
913 //determine the static bsm args
914 Type mtype = types.erasure(tree.descriptorType);
915 MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
916 List<Object> staticArgs = List.<Object>of(
917 new Pool.MethodHandle(ClassFile.REF_invokeInterface,
918 types.findDescriptorSymbol(tree.type.tsym), types),
919 new Pool.MethodHandle(refKind, refSym, types),
920 new MethodType(mtype.getParameterTypes(),
921 mtype.getReturnType(),
922 mtype.getThrownTypes(),
923 syms.methodClass));
925 //computed indy arg types
926 ListBuffer<Type> indy_args_types = ListBuffer.lb();
927 for (JCExpression arg : indy_args) {
928 indy_args_types.append(arg.type);
929 }
931 //finally, compute the type of the indy call
932 MethodType indyType = new MethodType(indy_args_types.toList(),
933 tree.type,
934 List.<Type>nil(),
935 syms.methodClass);
937 Name metafactoryName = needsAltMetafactory ?
938 names.altMetaFactory : names.metaFactory;
940 if (needsAltMetafactory) {
941 ListBuffer<Object> markers = ListBuffer.lb();
942 for (Symbol t : tree.targets.tail) {
943 if (t != syms.serializableType.tsym) {
944 markers.append(t);
945 }
946 }
947 int flags = isSerializable? FLAG_SERIALIZABLE : 0;
948 boolean hasMarkers = markers.nonEmpty();
949 flags |= hasMarkers ? FLAG_MARKERS : 0;
950 staticArgs = staticArgs.append(flags);
951 if (hasMarkers) {
952 staticArgs = staticArgs.append(markers.length());
953 staticArgs = staticArgs.appendList(markers.toList());
954 }
955 if (isSerializable) {
956 addDeserializationCase(refKind, refSym, tree.type, samSym,
957 tree, staticArgs, indyType);
958 }
959 }
961 return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args);
962 }
964 /**
965 * Generate an indy method call with given name, type and static bootstrap
966 * arguments types
967 */
968 private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
969 List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs) {
970 int prevPos = make.pos;
971 try {
972 make.at(pos);
973 List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
974 syms.stringType,
975 syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
977 Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
978 bsmName, bsm_staticArgs, List.<Type>nil());
980 DynamicMethodSymbol dynSym =
981 new DynamicMethodSymbol(names.lambda,
982 syms.noSymbol,
983 bsm.isStatic() ?
984 ClassFile.REF_invokeStatic :
985 ClassFile.REF_invokeVirtual,
986 (MethodSymbol)bsm,
987 indyType,
988 staticArgs.toArray());
990 JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
991 qualifier.sym = dynSym;
992 qualifier.type = indyType.getReturnType();
994 JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, indyArgs);
995 proxyCall.type = indyType.getReturnType();
996 return proxyCall;
997 } finally {
998 make.at(prevPos);
999 }
1000 }
1001 //where
1002 private List<Type> bsmStaticArgToTypes(List<Object> args) {
1003 ListBuffer<Type> argtypes = ListBuffer.lb();
1004 for (Object arg : args) {
1005 argtypes.append(bsmStaticArgToType(arg));
1006 }
1007 return argtypes.toList();
1008 }
1010 private Type bsmStaticArgToType(Object arg) {
1011 Assert.checkNonNull(arg);
1012 if (arg instanceof ClassSymbol) {
1013 return syms.classType;
1014 } else if (arg instanceof Integer) {
1015 return syms.intType;
1016 } else if (arg instanceof Long) {
1017 return syms.longType;
1018 } else if (arg instanceof Float) {
1019 return syms.floatType;
1020 } else if (arg instanceof Double) {
1021 return syms.doubleType;
1022 } else if (arg instanceof String) {
1023 return syms.stringType;
1024 } else if (arg instanceof Pool.MethodHandle) {
1025 return syms.methodHandleType;
1026 } else if (arg instanceof MethodType) {
1027 return syms.methodTypeType;
1028 } else {
1029 Assert.error("bad static arg " + arg.getClass());
1030 return null;
1031 }
1032 }
1034 /**
1035 * Get the opcode associated with this method reference
1036 */
1037 private int referenceKind(Symbol refSym) {
1038 if (refSym.isConstructor()) {
1039 return ClassFile.REF_newInvokeSpecial;
1040 } else {
1041 if (refSym.isStatic()) {
1042 return ClassFile.REF_invokeStatic;
1043 } else if (refSym.enclClass().isInterface()) {
1044 return ClassFile.REF_invokeInterface;
1045 } else {
1046 return (refSym.flags() & PRIVATE) != 0 ?
1047 ClassFile.REF_invokeSpecial :
1048 ClassFile.REF_invokeVirtual;
1049 }
1050 }
1051 }
1053 // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
1054 /**
1055 * This visitor collects information about translation of a lambda expression.
1056 * More specifically, it keeps track of the enclosing contexts and captured locals
1057 * accessed by the lambda being translated (as well as other useful info).
1058 * It also translates away problems for LambdaToMethod.
1059 */
1060 class LambdaAnalyzerPreprocessor extends TreeTranslator {
1062 /** the frame stack - used to reconstruct translation info about enclosing scopes */
1063 private List<Frame> frameStack;
1065 /**
1066 * keep the count of lambda expression (used to generate unambiguous
1067 * names)
1068 */
1069 private int lambdaCount = 0;
1071 /**
1072 * keep the count of lambda expression defined in given context (used to
1073 * generate unambiguous names for serializable lambdas)
1074 */
1075 private Map<String, Integer> serializableLambdaCounts =
1076 new HashMap<String, Integer>();
1078 private Map<Symbol, JCClassDecl> localClassDefs;
1080 /**
1081 * maps for fake clinit symbols to be used as owners of lambda occurring in
1082 * a static var init context
1083 */
1084 private Map<ClassSymbol, Symbol> clinits =
1085 new HashMap<ClassSymbol, Symbol>();
1087 private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) {
1088 frameStack = List.nil();
1089 localClassDefs = new HashMap<Symbol, JCClassDecl>();
1090 return translate(tree);
1091 }
1093 @Override
1094 public void visitBlock(JCBlock tree) {
1095 List<Frame> prevStack = frameStack;
1096 try {
1097 if (frameStack.nonEmpty() && frameStack.head.tree.hasTag(CLASSDEF)) {
1098 frameStack = frameStack.prepend(new Frame(tree));
1099 }
1100 super.visitBlock(tree);
1101 }
1102 finally {
1103 frameStack = prevStack;
1104 }
1105 }
1107 @Override
1108 public void visitClassDef(JCClassDecl tree) {
1109 List<Frame> prevStack = frameStack;
1110 Map<String, Integer> prevSerializableLambdaCount =
1111 serializableLambdaCounts;
1112 Map<ClassSymbol, Symbol> prevClinits = clinits;
1113 DiagnosticSource prevSource = log.currentSource();
1114 try {
1115 log.useSource(tree.sym.sourcefile);
1116 serializableLambdaCounts = new HashMap<String, Integer>();
1117 prevClinits = new HashMap<ClassSymbol, Symbol>();
1118 if (tree.sym.owner.kind == MTH) {
1119 localClassDefs.put(tree.sym, tree);
1120 }
1121 if (directlyEnclosingLambda() != null) {
1122 tree.sym.owner = owner();
1123 if (tree.sym.hasOuterInstance()) {
1124 //if a class is defined within a lambda, the lambda must capture
1125 //its enclosing instance (if any)
1126 TranslationContext<?> localContext = context();
1127 while (localContext != null) {
1128 if (localContext.tree.getTag() == LAMBDA) {
1129 ((LambdaTranslationContext)localContext)
1130 .addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS);
1131 }
1132 localContext = localContext.prev;
1133 }
1134 }
1135 }
1136 frameStack = frameStack.prepend(new Frame(tree));
1137 super.visitClassDef(tree);
1138 }
1139 finally {
1140 log.useSource(prevSource.getFile());
1141 frameStack = prevStack;
1142 serializableLambdaCounts = prevSerializableLambdaCount;
1143 clinits = prevClinits;
1144 }
1145 }
1147 @Override
1148 public void visitIdent(JCIdent tree) {
1149 if (context() != null && lambdaIdentSymbolFilter(tree.sym)) {
1150 if (tree.sym.kind == VAR &&
1151 tree.sym.owner.kind == MTH &&
1152 tree.type.constValue() == null) {
1153 TranslationContext<?> localContext = context();
1154 while (localContext != null) {
1155 if (localContext.tree.getTag() == LAMBDA) {
1156 JCTree block = capturedDecl(localContext.depth, tree.sym);
1157 if (block == null) break;
1158 ((LambdaTranslationContext)localContext)
1159 .addSymbol(tree.sym, CAPTURED_VAR);
1160 }
1161 localContext = localContext.prev;
1162 }
1163 } else if (tree.sym.owner.kind == TYP) {
1164 TranslationContext<?> localContext = context();
1165 while (localContext != null) {
1166 if (localContext.tree.hasTag(LAMBDA)) {
1167 JCTree block = capturedDecl(localContext.depth, tree.sym);
1168 if (block == null) break;
1169 switch (block.getTag()) {
1170 case CLASSDEF:
1171 JCClassDecl cdecl = (JCClassDecl)block;
1172 ((LambdaTranslationContext)localContext)
1173 .addSymbol(cdecl.sym, CAPTURED_THIS);
1174 break;
1175 default:
1176 Assert.error("bad block kind");
1177 }
1178 }
1179 localContext = localContext.prev;
1180 }
1181 }
1182 }
1183 super.visitIdent(tree);
1184 }
1186 @Override
1187 public void visitLambda(JCLambda tree) {
1188 List<Frame> prevStack = frameStack;
1189 try {
1190 LambdaTranslationContext context = (LambdaTranslationContext)makeLambdaContext(tree);
1191 frameStack = frameStack.prepend(new Frame(tree));
1192 for (JCVariableDecl param : tree.params) {
1193 context.addSymbol(param.sym, PARAM);
1194 frameStack.head.addLocal(param.sym);
1195 }
1196 contextMap.put(tree, context);
1197 super.visitLambda(tree);
1198 context.complete();
1199 }
1200 finally {
1201 frameStack = prevStack;
1202 }
1203 }
1205 @Override
1206 public void visitMethodDef(JCMethodDecl tree) {
1207 List<Frame> prevStack = frameStack;
1208 try {
1209 frameStack = frameStack.prepend(new Frame(tree));
1210 super.visitMethodDef(tree);
1211 }
1212 finally {
1213 frameStack = prevStack;
1214 }
1215 }
1217 @Override
1218 public void visitNewClass(JCNewClass tree) {
1219 if (lambdaNewClassFilter(context(), tree)) {
1220 TranslationContext<?> localContext = context();
1221 while (localContext != null) {
1222 if (localContext.tree.getTag() == LAMBDA) {
1223 ((LambdaTranslationContext)localContext)
1224 .addSymbol(tree.type.getEnclosingType().tsym, CAPTURED_THIS);
1225 }
1226 localContext = localContext.prev;
1227 }
1228 }
1229 if (context() != null && tree.type.tsym.owner.kind == MTH) {
1230 LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context();
1231 captureLocalClassDefs(tree.type.tsym, lambdaContext);
1232 }
1233 super.visitNewClass(tree);
1234 }
1235 //where
1236 void captureLocalClassDefs(Symbol csym, final LambdaTranslationContext lambdaContext) {
1237 JCClassDecl localCDef = localClassDefs.get(csym);
1238 if (localCDef != null && localCDef.pos < lambdaContext.tree.pos) {
1239 BasicFreeVarCollector fvc = lower.new BasicFreeVarCollector() {
1240 @Override
1241 void addFreeVars(ClassSymbol c) {
1242 captureLocalClassDefs(c, lambdaContext);
1243 }
1244 @Override
1245 void visitSymbol(Symbol sym) {
1246 if (sym.kind == VAR &&
1247 sym.owner.kind == MTH &&
1248 ((VarSymbol)sym).getConstValue() == null) {
1249 TranslationContext<?> localContext = context();
1250 while (localContext != null) {
1251 if (localContext.tree.getTag() == LAMBDA) {
1252 JCTree block = capturedDecl(localContext.depth, sym);
1253 if (block == null) break;
1254 ((LambdaTranslationContext)localContext).addSymbol(sym, CAPTURED_VAR);
1255 }
1256 localContext = localContext.prev;
1257 }
1258 }
1259 }
1260 };
1261 fvc.scan(localCDef);
1262 }
1263 }
1265 /**
1266 * Method references to local class constructors, may, if the local
1267 * class references local variables, have implicit constructor
1268 * parameters added in Lower; As a result, the invokedynamic bootstrap
1269 * information added in the LambdaToMethod pass will have the wrong
1270 * signature. Hooks between Lower and LambdaToMethod have been added to
1271 * handle normal "new" in this case. This visitor converts potentially
1272 * effected method references into a lambda containing a normal "new" of
1273 * the class.
1274 *
1275 * @param tree
1276 */
1277 @Override
1278 public void visitReference(JCMemberReference tree) {
1279 if (tree.getMode() == ReferenceMode.NEW
1280 && tree.kind != ReferenceKind.ARRAY_CTOR
1281 && tree.sym.owner.isLocal()) {
1282 MethodSymbol consSym = (MethodSymbol) tree.sym;
1283 List<Type> ptypes = ((MethodType) consSym.type).getParameterTypes();
1284 Type classType = consSym.owner.type;
1286 // Build lambda parameters
1287 // partially cloned from TreeMaker.Params until 8014021 is fixed
1288 Symbol owner = owner();
1289 ListBuffer<JCVariableDecl> paramBuff = new ListBuffer<JCVariableDecl>();
1290 int i = 0;
1291 for (List<Type> l = ptypes; l.nonEmpty(); l = l.tail) {
1292 paramBuff.append(make.Param(make.paramName(i++), l.head, owner));
1293 }
1294 List<JCVariableDecl> params = paramBuff.toList();
1296 // Make new-class call
1297 JCNewClass nc = makeNewClass(classType, make.Idents(params));
1298 nc.pos = tree.pos;
1300 // Make lambda holding the new-class call
1301 JCLambda slam = make.Lambda(params, nc);
1302 slam.descriptorType = tree.descriptorType;
1303 slam.targets = tree.targets;
1304 slam.type = tree.type;
1305 slam.pos = tree.pos;
1307 // Now it is a lambda, process as such
1308 visitLambda(slam);
1309 } else {
1310 super.visitReference(tree);
1311 contextMap.put(tree, makeReferenceContext(tree));
1312 }
1313 }
1315 @Override
1316 public void visitSelect(JCFieldAccess tree) {
1317 if (context() != null && tree.sym.kind == VAR &&
1318 (tree.sym.name == names._this ||
1319 tree.sym.name == names._super)) {
1320 // A select of this or super means, if we are in a lambda,
1321 // we much have an instance context
1322 TranslationContext<?> localContext = context();
1323 while (localContext != null) {
1324 if (localContext.tree.hasTag(LAMBDA)) {
1325 JCClassDecl clazz = (JCClassDecl)capturedDecl(localContext.depth, tree.sym);
1326 if (clazz == null) break;
1327 ((LambdaTranslationContext)localContext).addSymbol(clazz.sym, CAPTURED_THIS);
1328 }
1329 localContext = localContext.prev;
1330 }
1331 }
1332 super.visitSelect(tree);
1333 }
1335 @Override
1336 public void visitVarDef(JCVariableDecl tree) {
1337 TranslationContext<?> context = context();
1338 LambdaTranslationContext ltc = (context != null && context instanceof LambdaTranslationContext)?
1339 (LambdaTranslationContext)context :
1340 null;
1341 if (ltc != null) {
1342 if (frameStack.head.tree.hasTag(LAMBDA)) {
1343 ltc.addSymbol(tree.sym, LOCAL_VAR);
1344 }
1345 // Check for type variables (including as type arguments).
1346 // If they occur within class nested in a lambda, mark for erasure
1347 Type type = tree.sym.asType();
1348 if (inClassWithinLambda() && !types.isSameType(types.erasure(type), type)) {
1349 ltc.addSymbol(tree.sym, TYPE_VAR);
1350 }
1351 }
1353 List<Frame> prevStack = frameStack;
1354 try {
1355 if (tree.sym.owner.kind == MTH) {
1356 frameStack.head.addLocal(tree.sym);
1357 }
1358 frameStack = frameStack.prepend(new Frame(tree));
1359 super.visitVarDef(tree);
1360 }
1361 finally {
1362 frameStack = prevStack;
1363 }
1364 }
1366 private Name lambdaName() {
1367 return names.lambda.append(names.fromString("" + lambdaCount++));
1368 }
1370 /**
1371 * For a serializable lambda, generate a name which maximizes name
1372 * stability across deserialization.
1373 * @param owner
1374 * @return Name to use for the synthetic lambda method name
1375 */
1376 private Name serializedLambdaName(Symbol owner) {
1377 StringBuilder buf = new StringBuilder();
1378 buf.append(names.lambda);
1379 // Append the name of the method enclosing the lambda.
1380 String methodName = owner.name.toString();
1381 if (methodName.equals("<clinit>"))
1382 methodName = "static";
1383 else if (methodName.equals("<init>"))
1384 methodName = "new";
1385 buf.append(methodName);
1386 buf.append('$');
1387 // Append a hash of the enclosing method signature to differentiate
1388 // overloaded enclosing methods. For lambdas enclosed in lambdas,
1389 // the generated lambda method will not have type yet, but the
1390 // enclosing method's name will have been generated with this same
1391 // method, so it will be unique and never be overloaded.
1392 Assert.check(owner.type != null || directlyEnclosingLambda() != null);
1393 if (owner.type != null) {
1394 int methTypeHash = methodSig(owner.type).hashCode();
1395 buf.append(Integer.toHexString(methTypeHash));
1396 }
1397 buf.append('$');
1398 // The above appended name components may not be unique, append a
1399 // count based on the above name components.
1400 String temp = buf.toString();
1401 Integer count = serializableLambdaCounts.get(temp);
1402 if (count == null) {
1403 count = 0;
1404 }
1405 buf.append(count++);
1406 serializableLambdaCounts.put(temp, count);
1407 return names.fromString(buf.toString());
1408 }
1410 /**
1411 * Return a valid owner given the current declaration stack
1412 * (required to skip synthetic lambda symbols)
1413 */
1414 private Symbol owner() {
1415 return owner(false);
1416 }
1418 @SuppressWarnings("fallthrough")
1419 private Symbol owner(boolean skipLambda) {
1420 List<Frame> frameStack2 = frameStack;
1421 while (frameStack2.nonEmpty()) {
1422 switch (frameStack2.head.tree.getTag()) {
1423 case VARDEF:
1424 if (((JCVariableDecl)frameStack2.head.tree).sym.isLocal()) {
1425 frameStack2 = frameStack2.tail;
1426 break;
1427 }
1428 JCClassDecl cdecl = (JCClassDecl)frameStack2.tail.head.tree;
1429 return initSym(cdecl.sym,
1430 ((JCVariableDecl)frameStack2.head.tree).sym.flags() & STATIC);
1431 case BLOCK:
1432 JCClassDecl cdecl2 = (JCClassDecl)frameStack2.tail.head.tree;
1433 return initSym(cdecl2.sym,
1434 ((JCBlock)frameStack2.head.tree).flags & STATIC);
1435 case CLASSDEF:
1436 return ((JCClassDecl)frameStack2.head.tree).sym;
1437 case METHODDEF:
1438 return ((JCMethodDecl)frameStack2.head.tree).sym;
1439 case LAMBDA:
1440 if (!skipLambda)
1441 return ((LambdaTranslationContext)contextMap
1442 .get(frameStack2.head.tree)).translatedSym;
1443 default:
1444 frameStack2 = frameStack2.tail;
1445 }
1446 }
1447 Assert.error();
1448 return null;
1449 }
1451 private Symbol initSym(ClassSymbol csym, long flags) {
1452 boolean isStatic = (flags & STATIC) != 0;
1453 if (isStatic) {
1454 //static clinits are generated in Gen - so we need to fake them
1455 Symbol clinit = clinits.get(csym);
1456 if (clinit == null) {
1457 clinit = makeSyntheticMethod(STATIC,
1458 names.clinit,
1459 new MethodType(List.<Type>nil(), syms.voidType, List.<Type>nil(), syms.methodClass),
1460 csym);
1461 clinits.put(csym, clinit);
1462 }
1463 return clinit;
1464 } else {
1465 //get the first constructor and treat it as the instance init sym
1466 for (Symbol s : csym.members_field.getElementsByName(names.init)) {
1467 return s;
1468 }
1469 }
1470 Assert.error("init not found");
1471 return null;
1472 }
1474 private JCTree directlyEnclosingLambda() {
1475 if (frameStack.isEmpty()) {
1476 return null;
1477 }
1478 List<Frame> frameStack2 = frameStack;
1479 while (frameStack2.nonEmpty()) {
1480 switch (frameStack2.head.tree.getTag()) {
1481 case CLASSDEF:
1482 case METHODDEF:
1483 return null;
1484 case LAMBDA:
1485 return frameStack2.head.tree;
1486 default:
1487 frameStack2 = frameStack2.tail;
1488 }
1489 }
1490 Assert.error();
1491 return null;
1492 }
1494 private boolean inClassWithinLambda() {
1495 if (frameStack.isEmpty()) {
1496 return false;
1497 }
1498 List<Frame> frameStack2 = frameStack;
1499 boolean classFound = false;
1500 while (frameStack2.nonEmpty()) {
1501 switch (frameStack2.head.tree.getTag()) {
1502 case LAMBDA:
1503 return classFound;
1504 case CLASSDEF:
1505 classFound = true;
1506 frameStack2 = frameStack2.tail;
1507 break;
1508 default:
1509 frameStack2 = frameStack2.tail;
1510 }
1511 }
1512 // No lambda
1513 return false;
1514 }
1516 /**
1517 * Return the declaration corresponding to a symbol in the enclosing
1518 * scope; the depth parameter is used to filter out symbols defined
1519 * in nested scopes (which do not need to undergo capture).
1520 */
1521 private JCTree capturedDecl(int depth, Symbol sym) {
1522 int currentDepth = frameStack.size() - 1;
1523 for (Frame block : frameStack) {
1524 switch (block.tree.getTag()) {
1525 case CLASSDEF:
1526 ClassSymbol clazz = ((JCClassDecl)block.tree).sym;
1527 if (sym.isMemberOf(clazz, types)) {
1528 return currentDepth > depth ? null : block.tree;
1529 }
1530 break;
1531 case VARDEF:
1532 if (((JCVariableDecl)block.tree).sym == sym &&
1533 sym.owner.kind == MTH) { //only locals are captured
1534 return currentDepth > depth ? null : block.tree;
1535 }
1536 break;
1537 case BLOCK:
1538 case METHODDEF:
1539 case LAMBDA:
1540 if (block.locals != null && block.locals.contains(sym)) {
1541 return currentDepth > depth ? null : block.tree;
1542 }
1543 break;
1544 default:
1545 Assert.error("bad decl kind " + block.tree.getTag());
1546 }
1547 currentDepth--;
1548 }
1549 return null;
1550 }
1552 private TranslationContext<?> context() {
1553 for (Frame frame : frameStack) {
1554 TranslationContext<?> context = contextMap.get(frame.tree);
1555 if (context != null) {
1556 return context;
1557 }
1558 }
1559 return null;
1560 }
1562 /**
1563 * This is used to filter out those identifiers that needs to be adjusted
1564 * when translating away lambda expressions
1565 */
1566 private boolean lambdaIdentSymbolFilter(Symbol sym) {
1567 return (sym.kind == VAR || sym.kind == MTH)
1568 && !sym.isStatic()
1569 && sym.name != names.init;
1570 }
1572 /**
1573 * This is used to filter out those new class expressions that need to
1574 * be qualified with an enclosing tree
1575 */
1576 private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) {
1577 if (context != null
1578 && tree.encl == null
1579 && tree.def == null
1580 && !tree.type.getEnclosingType().hasTag(NONE)) {
1581 Type encl = tree.type.getEnclosingType();
1582 Type current = context.owner.enclClass().type;
1583 while (!current.hasTag(NONE)) {
1584 if (current.tsym.isSubClass(encl.tsym, types)) {
1585 return true;
1586 }
1587 current = current.getEnclosingType();
1588 }
1589 return false;
1590 } else {
1591 return false;
1592 }
1593 }
1595 private TranslationContext<JCLambda> makeLambdaContext(JCLambda tree) {
1596 return new LambdaTranslationContext(tree);
1597 }
1599 private TranslationContext<JCMemberReference> makeReferenceContext(JCMemberReference tree) {
1600 return new ReferenceTranslationContext(tree);
1601 }
1603 private class Frame {
1604 final JCTree tree;
1605 List<Symbol> locals;
1607 public Frame(JCTree tree) {
1608 this.tree = tree;
1609 }
1611 void addLocal(Symbol sym) {
1612 if (locals == null) {
1613 locals = List.nil();
1614 }
1615 locals = locals.prepend(sym);
1616 }
1617 }
1619 /**
1620 * This class is used to store important information regarding translation of
1621 * lambda expression/method references (see subclasses).
1622 */
1623 private abstract class TranslationContext<T extends JCFunctionalExpression> {
1625 /** the underlying (untranslated) tree */
1626 T tree;
1628 /** points to the adjusted enclosing scope in which this lambda/mref expression occurs */
1629 Symbol owner;
1631 /** the depth of this lambda expression in the frame stack */
1632 int depth;
1634 /** the enclosing translation context (set for nested lambdas/mref) */
1635 TranslationContext<?> prev;
1637 TranslationContext(T tree) {
1638 this.tree = tree;
1639 this.owner = owner();
1640 this.depth = frameStack.size() - 1;
1641 this.prev = context();
1642 }
1644 /** does this functional expression need to be created using alternate metafactory? */
1645 boolean needsAltMetafactory() {
1646 return (tree.targets.length() > 1 ||
1647 isSerializable());
1648 }
1650 /** does this functional expression require serialization support? */
1651 boolean isSerializable() {
1652 for (Symbol target : tree.targets) {
1653 if (types.asSuper(target.type, syms.serializableType.tsym) != null) {
1654 return true;
1655 }
1656 }
1657 return false;
1658 }
1659 }
1661 /**
1662 * This class retains all the useful information about a lambda expression;
1663 * the contents of this class are filled by the LambdaAnalyzer visitor,
1664 * and the used by the main translation routines in order to adjust references
1665 * to captured locals/members, etc.
1666 */
1667 private class LambdaTranslationContext extends TranslationContext<JCLambda> {
1669 /** variable in the enclosing context to which this lambda is assigned */
1670 Symbol self;
1672 /** map from original to translated lambda parameters */
1673 Map<Symbol, Symbol> lambdaParams = new LinkedHashMap<Symbol, Symbol>();
1675 /** map from original to translated lambda locals */
1676 Map<Symbol, Symbol> lambdaLocals = new LinkedHashMap<Symbol, Symbol>();
1678 /** map from variables in enclosing scope to translated synthetic parameters */
1679 Map<Symbol, Symbol> capturedLocals = new LinkedHashMap<Symbol, Symbol>();
1681 /** map from class symbols to translated synthetic parameters (for captured member access) */
1682 Map<Symbol, Symbol> capturedThis = new LinkedHashMap<Symbol, Symbol>();
1684 /** map from original to translated lambda locals */
1685 Map<Symbol, Symbol> typeVars = new LinkedHashMap<Symbol, Symbol>();
1687 /** the synthetic symbol for the method hoisting the translated lambda */
1688 Symbol translatedSym;
1690 List<JCVariableDecl> syntheticParams;
1692 LambdaTranslationContext(JCLambda tree) {
1693 super(tree);
1694 Frame frame = frameStack.head;
1695 if (frame.tree.hasTag(VARDEF)) {
1696 self = ((JCVariableDecl)frame.tree).sym;
1697 }
1698 Name name = isSerializable() ? serializedLambdaName(owner) : lambdaName();
1699 this.translatedSym = makeSyntheticMethod(0, name, null, owner.enclClass());
1700 if (dumpLambdaToMethodStats) {
1701 log.note(tree, "lambda.stat", needsAltMetafactory(), translatedSym);
1702 }
1703 }
1705 /**
1706 * Translate a symbol of a given kind into something suitable for the
1707 * synthetic lambda body
1708 */
1709 Symbol translate(Name name, final Symbol sym, LambdaSymbolKind skind) {
1710 Symbol ret;
1711 switch (skind) {
1712 case CAPTURED_THIS:
1713 ret = sym; // self represented
1714 break;
1715 case TYPE_VAR:
1716 // Just erase the type var
1717 ret = new VarSymbol(sym.flags(), name,
1718 types.erasure(sym.type), sym.owner);
1719 break;
1720 case CAPTURED_VAR:
1721 ret = new VarSymbol(SYNTHETIC | FINAL, name, types.erasure(sym.type), translatedSym) {
1722 @Override
1723 public Symbol baseSymbol() {
1724 //keep mapping with original captured symbol
1725 return sym;
1726 }
1727 };
1728 break;
1729 default:
1730 ret = makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym);
1731 }
1732 if (ret != sym) {
1733 ret.setDeclarationAttributes(sym.getRawAttributes());
1734 ret.setTypeAttributes(sym.getRawTypeAttributes());
1735 }
1736 return ret;
1737 }
1739 void addSymbol(Symbol sym, LambdaSymbolKind skind) {
1740 Map<Symbol, Symbol> transMap = null;
1741 Name preferredName;
1742 switch (skind) {
1743 case CAPTURED_THIS:
1744 transMap = capturedThis;
1745 preferredName = names.fromString("encl$" + capturedThis.size());
1746 break;
1747 case CAPTURED_VAR:
1748 transMap = capturedLocals;
1749 preferredName = names.fromString("cap$" + capturedLocals.size());
1750 break;
1751 case LOCAL_VAR:
1752 transMap = lambdaLocals;
1753 preferredName = sym.name;
1754 break;
1755 case PARAM:
1756 transMap = lambdaParams;
1757 preferredName = sym.name;
1758 break;
1759 case TYPE_VAR:
1760 transMap = typeVars;
1761 preferredName = sym.name;
1762 break;
1763 default: throw new AssertionError();
1764 }
1765 if (!transMap.containsKey(sym)) {
1766 transMap.put(sym, translate(preferredName, sym, skind));
1767 }
1768 }
1770 Map<Symbol, Symbol> getSymbolMap(LambdaSymbolKind... skinds) {
1771 LinkedHashMap<Symbol, Symbol> translationMap = new LinkedHashMap<Symbol, Symbol>();
1772 for (LambdaSymbolKind skind : skinds) {
1773 switch (skind) {
1774 case CAPTURED_THIS:
1775 translationMap.putAll(capturedThis);
1776 break;
1777 case CAPTURED_VAR:
1778 translationMap.putAll(capturedLocals);
1779 break;
1780 case LOCAL_VAR:
1781 translationMap.putAll(lambdaLocals);
1782 break;
1783 case PARAM:
1784 translationMap.putAll(lambdaParams);
1785 break;
1786 case TYPE_VAR:
1787 translationMap.putAll(typeVars);
1788 break;
1789 default: throw new AssertionError();
1790 }
1791 }
1792 return translationMap;
1793 }
1795 /**
1796 * The translatedSym is not complete/accurate until the analysis is
1797 * finished. Once the analysis is finished, the translatedSym is
1798 * "completed" -- updated with type information, access modifiers,
1799 * and full parameter list.
1800 */
1801 void complete() {
1802 if (syntheticParams != null) {
1803 return;
1804 }
1805 boolean inInterface = translatedSym.owner.isInterface();
1806 boolean thisReferenced = !getSymbolMap(CAPTURED_THIS).isEmpty();
1808 // If instance access isn't needed, make it static.
1809 // Interface instance methods must be default methods.
1810 // Awaiting VM channges, default methods are public
1811 translatedSym.flags_field = SYNTHETIC |
1812 ((inInterface && thisReferenced)? PUBLIC : PRIVATE) |
1813 (thisReferenced? (inInterface? DEFAULT : 0) : STATIC);
1815 //compute synthetic params
1816 ListBuffer<JCVariableDecl> params = ListBuffer.lb();
1818 // The signature of the method is augmented with the following
1819 // synthetic parameters:
1820 //
1821 // 1) reference to enclosing contexts captured by the lambda expression
1822 // 2) enclosing locals captured by the lambda expression
1823 for (Symbol thisSym : getSymbolMap(CAPTURED_VAR, PARAM).values()) {
1824 params.append(make.VarDef((VarSymbol) thisSym, null));
1825 }
1827 syntheticParams = params.toList();
1829 //prepend synthetic args to translated lambda method signature
1830 translatedSym.type = types.createMethodTypeWithParameters(
1831 generatedLambdaSig(),
1832 TreeInfo.types(syntheticParams));
1833 }
1835 Type generatedLambdaSig() {
1836 return types.erasure(tree.descriptorType);
1837 }
1838 }
1840 /**
1841 * This class retains all the useful information about a method reference;
1842 * the contents of this class are filled by the LambdaAnalyzer visitor,
1843 * and the used by the main translation routines in order to adjust method
1844 * references (i.e. in case a bridge is needed)
1845 */
1846 private class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
1848 final boolean isSuper;
1849 final Symbol bridgeSym;
1851 ReferenceTranslationContext(JCMemberReference tree) {
1852 super(tree);
1853 this.isSuper = tree.hasKind(ReferenceKind.SUPER);
1854 this.bridgeSym = needsBridge()
1855 ? makeSyntheticMethod(isSuper ? 0 : STATIC,
1856 lambdaName().append(names.fromString("$bridge")), null,
1857 owner.enclClass())
1858 : null;
1859 if (dumpLambdaToMethodStats) {
1860 String key = bridgeSym == null ?
1861 "mref.stat" : "mref.stat.1";
1862 log.note(tree, key, needsAltMetafactory(), bridgeSym);
1863 }
1864 }
1866 /**
1867 * Get the opcode associated with this method reference
1868 */
1869 int referenceKind() {
1870 return LambdaToMethod.this.referenceKind(needsBridge() ? bridgeSym : tree.sym);
1871 }
1873 boolean needsVarArgsConversion() {
1874 return tree.varargsElement != null;
1875 }
1877 /**
1878 * @return Is this an array operation like clone()
1879 */
1880 boolean isArrayOp() {
1881 return tree.sym.owner == syms.arrayClass;
1882 }
1884 boolean isPrivateConstructor() {
1885 //hack needed to workaround 292 bug (8005122)
1886 //when 292 issue is fixed we should simply remove this
1887 return tree.sym.name == names.init &&
1888 (tree.sym.flags() & PRIVATE) != 0;
1889 }
1891 boolean receiverAccessible() {
1892 //hack needed to workaround 292 bug (7087658)
1893 //when 292 issue is fixed we should remove this and change the backend
1894 //code to always generate a method handle to an accessible method
1895 return tree.ownerAccessible;
1896 }
1898 /**
1899 * Does this reference needs a bridge (i.e. var args need to be
1900 * expanded or "super" is used)
1901 */
1902 final boolean needsBridge() {
1903 return isSuper || needsVarArgsConversion() || isArrayOp() ||
1904 isPrivateConstructor() || !receiverAccessible();
1905 }
1907 Type generatedRefSig() {
1908 return types.erasure(tree.sym.type);
1909 }
1911 Type bridgedRefSig() {
1912 return types.erasure(types.findDescriptorSymbol(tree.targets.head).type);
1913 }
1914 }
1915 }
1916 // </editor-fold>
1918 enum LambdaSymbolKind {
1919 CAPTURED_VAR,
1920 CAPTURED_THIS,
1921 LOCAL_VAR,
1922 PARAM,
1923 TYPE_VAR;
1924 }
1926 /**
1927 * ****************************************************************
1928 * Signature Generation
1929 * ****************************************************************
1930 */
1932 private String methodSig(Type type) {
1933 L2MSignatureGenerator sg = new L2MSignatureGenerator();
1934 sg.assembleSig(type);
1935 return sg.toString();
1936 }
1938 private String classSig(Type type) {
1939 L2MSignatureGenerator sg = new L2MSignatureGenerator();
1940 sg.assembleClassSig(type);
1941 return sg.toString();
1942 }
1944 /**
1945 * Signature Generation
1946 */
1947 private class L2MSignatureGenerator extends Types.SignatureGenerator {
1949 /**
1950 * An output buffer for type signatures.
1951 */
1952 StringBuilder sb = new StringBuilder();
1954 L2MSignatureGenerator() {
1955 super(types);
1956 }
1958 @Override
1959 protected void append(char ch) {
1960 sb.append(ch);
1961 }
1963 @Override
1964 protected void append(byte[] ba) {
1965 sb.append(new String(ba));
1966 }
1968 @Override
1969 protected void append(Name name) {
1970 sb.append(name.toString());
1971 }
1973 @Override
1974 public String toString() {
1975 return sb.toString();
1976 }
1977 }
1978 }