1586:9fb4f223a90d | 1587:f1f605f85850 |
---|---|
29 import com.sun.tools.javac.tree.JCTree.*; | 29 import com.sun.tools.javac.tree.JCTree.*; |
30 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; | 30 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; |
31 import com.sun.tools.javac.tree.TreeMaker; | 31 import com.sun.tools.javac.tree.TreeMaker; |
32 import com.sun.tools.javac.tree.TreeScanner; | 32 import com.sun.tools.javac.tree.TreeScanner; |
33 import com.sun.tools.javac.tree.TreeTranslator; | 33 import com.sun.tools.javac.tree.TreeTranslator; |
34 import com.sun.tools.javac.code.Flags; | |
35 import com.sun.tools.javac.code.Kinds; | 34 import com.sun.tools.javac.code.Kinds; |
35 import com.sun.tools.javac.code.Scope; | |
36 import com.sun.tools.javac.code.Symbol; | 36 import com.sun.tools.javac.code.Symbol; |
37 import com.sun.tools.javac.code.Symbol.ClassSymbol; | 37 import com.sun.tools.javac.code.Symbol.ClassSymbol; |
38 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol; | 38 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol; |
39 import com.sun.tools.javac.code.Symbol.MethodSymbol; | 39 import com.sun.tools.javac.code.Symbol.MethodSymbol; |
40 import com.sun.tools.javac.code.Symbol.VarSymbol; | 40 import com.sun.tools.javac.code.Symbol.VarSymbol; |
55 import java.util.Map; | 55 import java.util.Map; |
56 | 56 |
57 import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*; | 57 import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*; |
58 import static com.sun.tools.javac.code.Flags.*; | 58 import static com.sun.tools.javac.code.Flags.*; |
59 import static com.sun.tools.javac.code.Kinds.*; | 59 import static com.sun.tools.javac.code.Kinds.*; |
60 import static com.sun.tools.javac.code.TypeTag.BOT; | 60 import static com.sun.tools.javac.code.TypeTag.*; |
61 import static com.sun.tools.javac.code.TypeTag.NONE; | |
62 import static com.sun.tools.javac.code.TypeTag.VOID; | |
63 import static com.sun.tools.javac.tree.JCTree.Tag.*; | 61 import static com.sun.tools.javac.tree.JCTree.Tag.*; |
64 | 62 |
65 /** | 63 /** |
66 * This pass desugars lambda expressions into static methods | 64 * This pass desugars lambda expressions into static methods |
67 * | 65 * |
87 private Map<JCTree, TranslationContext<?>> contextMap; | 85 private Map<JCTree, TranslationContext<?>> contextMap; |
88 | 86 |
89 /** current translation context (visitor argument) */ | 87 /** current translation context (visitor argument) */ |
90 private TranslationContext<?> context; | 88 private TranslationContext<?> context; |
91 | 89 |
92 /** list of translated methods | 90 /** info about the current class being processed */ |
93 **/ | 91 private KlassInfo kInfo; |
94 private ListBuffer<JCTree> translatedMethodList; | 92 |
93 /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */ | |
94 public static final int FLAG_SERIALIZABLE = 1 << 0; | |
95 | |
96 /** Flag for alternate metafactories indicating the lambda object has multiple targets */ | |
97 public static final int FLAG_MARKERS = 1 << 1; | |
98 | |
99 private class KlassInfo { | |
100 | |
101 /** | |
102 * list of methods to append | |
103 */ | |
104 private ListBuffer<JCTree> appendedMethodList; | |
105 | |
106 /** | |
107 * list of deserialization cases | |
108 */ | |
109 private final Map<String, ListBuffer<JCStatement>> deserializeCases; | |
110 | |
111 /** | |
112 * deserialize method symbol | |
113 */ | |
114 private final MethodSymbol deserMethodSym; | |
115 | |
116 /** | |
117 * deserialize method parameter symbol | |
118 */ | |
119 private final VarSymbol deserParamSym; | |
120 | |
121 private KlassInfo(Symbol kSym) { | |
122 appendedMethodList = ListBuffer.lb(); | |
123 deserializeCases = new HashMap<String, ListBuffer<JCStatement>>(); | |
124 long flags = PRIVATE | STATIC | SYNTHETIC; | |
125 MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType, | |
126 List.<Type>nil(), syms.methodClass); | |
127 deserMethodSym = makeSyntheticMethod(flags, names.deserializeLambda, type, kSym); | |
128 deserParamSym = new VarSymbol(FINAL, names.fromString("lambda"), syms.serializedLambdaType, deserMethodSym); | |
129 } | |
130 | |
131 private void addMethod(JCTree decl) { | |
132 appendedMethodList = appendedMethodList.prepend(decl); | |
133 } | |
134 } | |
95 | 135 |
96 // <editor-fold defaultstate="collapsed" desc="Instantiating"> | 136 // <editor-fold defaultstate="collapsed" desc="Instantiating"> |
97 private static final Context.Key<LambdaToMethod> unlambdaKey = | 137 private static final Context.Key<LambdaToMethod> unlambdaKey = |
98 new Context.Key<LambdaToMethod>(); | 138 new Context.Key<LambdaToMethod>(); |
99 | 139 |
110 syms = Symtab.instance(context); | 150 syms = Symtab.instance(context); |
111 rs = Resolve.instance(context); | 151 rs = Resolve.instance(context); |
112 make = TreeMaker.instance(context); | 152 make = TreeMaker.instance(context); |
113 types = Types.instance(context); | 153 types = Types.instance(context); |
114 transTypes = TransTypes.instance(context); | 154 transTypes = TransTypes.instance(context); |
115 this.analyzer = makeAnalyzer(); | 155 analyzer = new LambdaAnalyzer(); |
116 } | |
117 | |
118 private LambdaAnalyzer makeAnalyzer() { | |
119 return new LambdaAnalyzer(); | |
120 } | 156 } |
121 // </editor-fold> | 157 // </editor-fold> |
122 | 158 |
123 // <editor-fold defaultstate="collapsed" desc="translate methods"> | 159 // <editor-fold defaultstate="collapsed" desc="translate methods"> |
124 @Override | 160 @Override |
166 public void visitClassDef(JCClassDecl tree) { | 202 public void visitClassDef(JCClassDecl tree) { |
167 if (tree.sym.owner.kind == PCK) { | 203 if (tree.sym.owner.kind == PCK) { |
168 //analyze class | 204 //analyze class |
169 analyzer.analyzeClass(tree); | 205 analyzer.analyzeClass(tree); |
170 } | 206 } |
171 ListBuffer<JCTree> prevTranslated = translatedMethodList; | 207 KlassInfo prevKlassInfo = kInfo; |
172 try { | 208 try { |
173 translatedMethodList = ListBuffer.lb(); | 209 kInfo = new KlassInfo(tree.sym); |
174 super.visitClassDef(tree); | 210 super.visitClassDef(tree); |
211 if (!kInfo.deserializeCases.isEmpty()) { | |
212 kInfo.addMethod(makeDeserializeMethod(tree.sym)); | |
213 } | |
175 //add all translated instance methods here | 214 //add all translated instance methods here |
176 tree.defs = tree.defs.appendList(translatedMethodList.toList()); | 215 List<JCTree> newMethods = kInfo.appendedMethodList.toList(); |
177 for (JCTree lambda : translatedMethodList) { | 216 tree.defs = tree.defs.appendList(newMethods); |
217 for (JCTree lambda : newMethods) { | |
178 tree.sym.members().enter(((JCMethodDecl)lambda).sym); | 218 tree.sym.members().enter(((JCMethodDecl)lambda).sym); |
179 } | 219 } |
180 result = tree; | 220 result = tree; |
181 } finally { | 221 } finally { |
182 translatedMethodList = prevTranslated; | 222 kInfo = prevKlassInfo; |
183 } | 223 } |
184 } | 224 } |
185 | 225 |
186 /** | 226 /** |
187 * Translate a lambda into a method to be inserted into the class. | 227 * Translate a lambda into a method to be inserted into the class. |
215 //to refer to the static method parameters (rather than i.e. acessing to | 255 //to refer to the static method parameters (rather than i.e. acessing to |
216 //captured members directly). | 256 //captured members directly). |
217 lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl)); | 257 lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl)); |
218 | 258 |
219 //Add the method to the list of methods to be added to this class. | 259 //Add the method to the list of methods to be added to this class. |
220 translatedMethodList = translatedMethodList.prepend(lambdaDecl); | 260 kInfo.addMethod(lambdaDecl); |
221 | 261 |
222 //now that we have generated a method for the lambda expression, | 262 //now that we have generated a method for the lambda expression, |
223 //we can translate the lambda into a method reference pointing to the newly | 263 //we can translate the lambda into a method reference pointing to the newly |
224 //created method. | 264 //created method. |
225 // | 265 // |
232 | 272 |
233 ListBuffer<JCExpression> syntheticInits = ListBuffer.lb(); | 273 ListBuffer<JCExpression> syntheticInits = ListBuffer.lb(); |
234 | 274 |
235 if (!sym.isStatic()) { | 275 if (!sym.isStatic()) { |
236 syntheticInits.append(makeThis( | 276 syntheticInits.append(makeThis( |
237 sym.owner.asType(), | 277 sym.owner.enclClass().asType(), |
238 localContext.owner.enclClass())); | 278 localContext.owner.enclClass())); |
239 } | 279 } |
240 | 280 |
241 //add captured locals | 281 //add captured locals |
242 for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) { | 282 for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) { |
251 | 291 |
252 //build a sam instance using an indy call to the meta-factory | 292 //build a sam instance using an indy call to the meta-factory |
253 int refKind = referenceKind(sym); | 293 int refKind = referenceKind(sym); |
254 | 294 |
255 //convert to an invokedynamic call | 295 //convert to an invokedynamic call |
256 result = makeMetaFactoryIndyCall(tree, refKind, sym, indy_args); | 296 result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args); |
257 } | 297 } |
258 | 298 |
259 private JCIdent makeThis(Type type, Symbol owner) { | 299 private JCIdent makeThis(Type type, Symbol owner) { |
260 VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC, | 300 VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC, |
261 names._this, | 301 names._this, |
289 switch(tree.kind) { | 329 switch(tree.kind) { |
290 | 330 |
291 case IMPLICIT_INNER: /** Inner :: new */ | 331 case IMPLICIT_INNER: /** Inner :: new */ |
292 case SUPER: /** super :: instMethod */ | 332 case SUPER: /** super :: instMethod */ |
293 init = makeThis( | 333 init = makeThis( |
294 localContext.owner.owner.asType(), | 334 localContext.owner.enclClass().asType(), |
295 localContext.owner); | 335 localContext.owner.enclClass()); |
296 break; | 336 break; |
297 | 337 |
298 case BOUND: /** Expr :: instMethod */ | 338 case BOUND: /** Expr :: instMethod */ |
299 init = tree.getQualifierExpression(); | 339 init = tree.getQualifierExpression(); |
300 break; | 340 break; |
312 | 352 |
313 List<JCExpression> indy_args = init==null? List.<JCExpression>nil() : translate(List.of(init), localContext.prev); | 353 List<JCExpression> indy_args = init==null? List.<JCExpression>nil() : translate(List.of(init), localContext.prev); |
314 | 354 |
315 | 355 |
316 //build a sam instance using an indy call to the meta-factory | 356 //build a sam instance using an indy call to the meta-factory |
317 result = makeMetaFactoryIndyCall(tree, localContext.referenceKind(), refSym, indy_args); | 357 result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args); |
318 } | 358 } |
319 | 359 |
320 /** | 360 /** |
321 * Translate identifiers within a lambda to the mapped identifier | 361 * Translate identifiers within a lambda to the mapped identifier |
322 * @param tree | 362 * @param tree |
331 Symbol translatedSym = lambdaContext.getSymbolMap(PARAM).get(tree.sym); | 371 Symbol translatedSym = lambdaContext.getSymbolMap(PARAM).get(tree.sym); |
332 result = make.Ident(translatedSym).setType(tree.type); | 372 result = make.Ident(translatedSym).setType(tree.type); |
333 } else if (lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) { | 373 } else if (lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) { |
334 Symbol translatedSym = lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym); | 374 Symbol translatedSym = lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym); |
335 result = make.Ident(translatedSym).setType(tree.type); | 375 result = make.Ident(translatedSym).setType(tree.type); |
376 } else if (lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) { | |
377 Symbol translatedSym = lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym); | |
378 result = make.Ident(translatedSym).setType(translatedSym.type); | |
336 } else if (lambdaContext.getSymbolMap(CAPTURED_VAR).containsKey(tree.sym)) { | 379 } else if (lambdaContext.getSymbolMap(CAPTURED_VAR).containsKey(tree.sym)) { |
337 Symbol translatedSym = lambdaContext.getSymbolMap(CAPTURED_VAR).get(tree.sym); | 380 Symbol translatedSym = lambdaContext.getSymbolMap(CAPTURED_VAR).get(tree.sym); |
338 result = make.Ident(translatedSym).setType(tree.type); | 381 result = make.Ident(translatedSym).setType(tree.type); |
339 } else { | 382 } else { |
340 if (tree.sym.owner.kind == Kinds.TYP) { | 383 if (tree.sym.owner.kind == Kinds.TYP) { |
360 public void visitVarDef(JCVariableDecl tree) { | 403 public void visitVarDef(JCVariableDecl tree) { |
361 LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context; | 404 LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context; |
362 if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) { | 405 if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) { |
363 JCExpression init = translate(tree.init); | 406 JCExpression init = translate(tree.init); |
364 result = make.VarDef((VarSymbol)lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym), init); | 407 result = make.VarDef((VarSymbol)lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym), init); |
408 } else if (context != null && lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) { | |
409 JCExpression init = translate(tree.init); | |
410 VarSymbol xsym = (VarSymbol)lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym); | |
411 result = make.VarDef(xsym, init); | |
412 // Replace the entered symbol for this variable | |
413 Scope sc = tree.sym.owner.members(); | |
414 if (sc != null) { | |
415 sc.remove(tree.sym); | |
416 sc.enter(xsym); | |
417 } | |
365 } else { | 418 } else { |
366 super.visitVarDef(tree); | 419 super.visitVarDef(tree); |
367 } | 420 } |
368 } | 421 } |
369 | 422 |
449 trans_block.stats = trans_block.stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType))); | 502 trans_block.stats = trans_block.stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType))); |
450 } | 503 } |
451 return trans_block; | 504 return trans_block; |
452 } | 505 } |
453 | 506 |
507 private JCMethodDecl makeDeserializeMethod(Symbol kSym) { | |
508 ListBuffer<JCCase> cases = ListBuffer.lb(); | |
509 ListBuffer<JCBreak> breaks = ListBuffer.lb(); | |
510 for (Map.Entry<String, ListBuffer<JCStatement>> entry : kInfo.deserializeCases.entrySet()) { | |
511 JCBreak br = make.Break(null); | |
512 breaks.add(br); | |
513 List<JCStatement> stmts = entry.getValue().append(br).toList(); | |
514 cases.add(make.Case(make.Literal(entry.getKey()), stmts)); | |
515 } | |
516 JCSwitch sw = make.Switch(deserGetter("getImplMethodName", syms.stringType), cases.toList()); | |
517 for (JCBreak br : breaks) { | |
518 br.target = sw; | |
519 } | |
520 JCBlock body = make.Block(0L, List.<JCStatement>of( | |
521 sw, | |
522 make.Throw(makeNewClass( | |
523 syms.illegalArgumentExceptionType, | |
524 List.<JCExpression>of(make.Literal("Invalid lambda deserialization")))))); | |
525 JCMethodDecl deser = make.MethodDef(make.Modifiers(kInfo.deserMethodSym.flags()), | |
526 names.deserializeLambda, | |
527 make.QualIdent(kInfo.deserMethodSym.getReturnType().tsym), | |
528 List.<JCTypeParameter>nil(), | |
529 List.of(make.VarDef(kInfo.deserParamSym, null)), | |
530 List.<JCExpression>nil(), | |
531 body, | |
532 null); | |
533 deser.sym = kInfo.deserMethodSym; | |
534 deser.type = kInfo.deserMethodSym.type; | |
535 //System.err.printf("DESER: '%s'\n", deser); | |
536 return deser; | |
537 } | |
538 | |
539 /** Make an attributed class instance creation expression. | |
540 * @param ctype The class type. | |
541 * @param args The constructor arguments. | |
542 */ | |
543 JCNewClass makeNewClass(Type ctype, List<JCExpression> args) { | |
544 JCNewClass tree = make.NewClass(null, | |
545 null, make.QualIdent(ctype.tsym), args, null); | |
546 tree.constructor = rs.resolveConstructor( | |
547 null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil()); | |
548 tree.type = ctype; | |
549 return tree; | |
550 } | |
551 | |
552 private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym, | |
553 DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) { | |
554 String functionalInterfaceClass = classSig(targetType); | |
555 String functionalInterfaceMethodName = samSym.getSimpleName().toString(); | |
556 String functionalInterfaceMethodSignature = methodSig(types.erasure(samSym.type)); | |
557 String implClass = classSig(refSym.owner.type); | |
558 String implMethodName = refSym.getQualifiedName().toString(); | |
559 String implMethodSignature = methodSig(types.erasure(refSym.type)); | |
560 | |
561 JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind)); | |
562 ListBuffer<JCExpression> serArgs = ListBuffer.lb(); | |
563 int i = 0; | |
564 for (Type t : indyType.getParameterTypes()) { | |
565 List<JCExpression> indexAsArg = ListBuffer.<JCExpression>lb().append(make.Literal(i)).toList(); | |
566 List<Type> argTypes = ListBuffer.<Type>lb().append(syms.intType).toList(); | |
567 serArgs.add(make.TypeCast(types.erasure(t), deserGetter("getCapturedArg", syms.objectType, argTypes, indexAsArg))); | |
568 ++i; | |
569 } | |
570 JCStatement stmt = make.If( | |
571 deserTest(deserTest(deserTest(deserTest(deserTest( | |
572 kindTest, | |
573 "getFunctionalInterfaceClass", functionalInterfaceClass), | |
574 "getFunctionalInterfaceMethodName", functionalInterfaceMethodName), | |
575 "getFunctionalInterfaceMethodSignature", functionalInterfaceMethodSignature), | |
576 "getImplClass", implClass), | |
577 "getImplMethodSignature", implMethodSignature), | |
578 make.Return(makeIndyCall( | |
579 pos, | |
580 syms.lambdaMetafactory, | |
581 names.altMetaFactory, | |
582 staticArgs, indyType, serArgs.toList())), | |
583 null); | |
584 ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName); | |
585 if (stmts == null) { | |
586 stmts = ListBuffer.lb(); | |
587 kInfo.deserializeCases.put(implMethodName, stmts); | |
588 } | |
589 /**** | |
590 System.err.printf("+++++++++++++++++\n"); | |
591 System.err.printf("*functionalInterfaceClass: '%s'\n", functionalInterfaceClass); | |
592 System.err.printf("*functionalInterfaceMethodName: '%s'\n", functionalInterfaceMethodName); | |
593 System.err.printf("*functionalInterfaceMethodSignature: '%s'\n", functionalInterfaceMethodSignature); | |
594 System.err.printf("*implMethodKind: %d\n", implMethodKind); | |
595 System.err.printf("*implClass: '%s'\n", implClass); | |
596 System.err.printf("*implMethodName: '%s'\n", implMethodName); | |
597 System.err.printf("*implMethodSignature: '%s'\n", implMethodSignature); | |
598 ****/ | |
599 stmts.append(stmt); | |
600 } | |
601 | |
602 private JCExpression eqTest(Type argType, JCExpression arg1, JCExpression arg2) { | |
603 JCBinary testExpr = make.Binary(JCTree.Tag.EQ, arg1, arg2); | |
604 testExpr.operator = rs.resolveBinaryOperator(null, JCTree.Tag.EQ, attrEnv, argType, argType); | |
605 testExpr.setType(syms.booleanType); | |
606 return testExpr; | |
607 } | |
608 | |
609 private JCExpression deserTest(JCExpression prev, String func, String lit) { | |
610 MethodType eqmt = new MethodType(List.of(syms.objectType), syms.booleanType, List.<Type>nil(), syms.methodClass); | |
611 Symbol eqsym = rs.resolveQualifiedMethod(null, attrEnv, syms.objectType, names.equals, List.of(syms.objectType), List.<Type>nil()); | |
612 JCMethodInvocation eqtest = make.Apply( | |
613 List.<JCExpression>nil(), | |
614 make.Select(deserGetter(func, syms.stringType), eqsym).setType(eqmt), | |
615 List.<JCExpression>of(make.Literal(lit))); | |
616 eqtest.setType(syms.booleanType); | |
617 JCBinary compound = make.Binary(JCTree.Tag.AND, prev, eqtest); | |
618 compound.operator = rs.resolveBinaryOperator(null, JCTree.Tag.AND, attrEnv, syms.booleanType, syms.booleanType); | |
619 compound.setType(syms.booleanType); | |
620 return compound; | |
621 } | |
622 | |
623 private JCExpression deserGetter(String func, Type type) { | |
624 return deserGetter(func, type, List.<Type>nil(), List.<JCExpression>nil()); | |
625 } | |
626 | |
627 private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) { | |
628 MethodType getmt = new MethodType(argTypes, type, List.<Type>nil(), syms.methodClass); | |
629 Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.<Type>nil()); | |
630 return make.Apply( | |
631 List.<JCExpression>nil(), | |
632 make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt), | |
633 args).setType(type); | |
634 } | |
635 | |
454 /** | 636 /** |
455 * Create new synthetic method with given flags, name, type, owner | 637 * Create new synthetic method with given flags, name, type, owner |
456 */ | 638 */ |
457 private MethodSymbol makeSyntheticMethod(long flags, Name name, Type type, Symbol owner) { | 639 private MethodSymbol makeSyntheticMethod(long flags, Name name, Type type, Symbol owner) { |
458 return new MethodSymbol(flags | SYNTHETIC, name, type, owner); | 640 return new MethodSymbol(flags | SYNTHETIC, name, type, owner); |
676 * Bridges a member reference - this is needed when: | 858 * Bridges a member reference - this is needed when: |
677 * * Var args in the referenced method need to be flattened away | 859 * * Var args in the referenced method need to be flattened away |
678 * * super is used | 860 * * super is used |
679 */ | 861 */ |
680 private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) { | 862 private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) { |
681 JCMethodDecl bridgeDecl = (new MemberReferenceBridger(tree, localContext).bridge()); | 863 kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge()); |
682 translatedMethodList = translatedMethodList.prepend(bridgeDecl); | |
683 } | 864 } |
684 | 865 |
685 /** | 866 /** |
686 * Generate an indy method call to the meta factory | 867 * Generate an indy method call to the meta factory |
687 */ | 868 */ |
688 private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, int refKind, Symbol refSym, List<JCExpression> indy_args) { | 869 private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory, |
870 boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) { | |
689 //determine the static bsm args | 871 //determine the static bsm args |
690 Type mtype = types.erasure(tree.descriptorType); | 872 Type mtype = types.erasure(tree.descriptorType); |
691 MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym); | 873 MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym); |
692 List<Object> staticArgs = List.<Object>of( | 874 List<Object> staticArgs = List.<Object>of( |
693 new Pool.MethodHandle(ClassFile.REF_invokeInterface, types.findDescriptorSymbol(tree.type.tsym), types), | 875 new Pool.MethodHandle(ClassFile.REF_invokeInterface, types.findDescriptorSymbol(tree.type.tsym), types), |
707 MethodType indyType = new MethodType(indy_args_types.toList(), | 889 MethodType indyType = new MethodType(indy_args_types.toList(), |
708 tree.type, | 890 tree.type, |
709 List.<Type>nil(), | 891 List.<Type>nil(), |
710 syms.methodClass); | 892 syms.methodClass); |
711 | 893 |
712 return makeIndyCall(tree, syms.lambdaMetafactory, names.metaFactory, staticArgs, indyType, indy_args); | 894 Name metafactoryName = needsAltMetafactory ? |
895 names.altMetaFactory : names.metaFactory; | |
896 | |
897 if (needsAltMetafactory) { | |
898 ListBuffer<Object> markers = ListBuffer.lb(); | |
899 for (Symbol t : tree.targets.tail) { | |
900 if (t != syms.serializableType.tsym) { | |
901 markers.append(t); | |
902 } | |
903 } | |
904 int flags = isSerializable? FLAG_SERIALIZABLE : 0; | |
905 boolean hasMarkers = markers.nonEmpty(); | |
906 flags |= hasMarkers ? FLAG_MARKERS : 0; | |
907 staticArgs = staticArgs.append(flags); | |
908 if (hasMarkers) { | |
909 staticArgs = staticArgs.append(markers.length()); | |
910 staticArgs = staticArgs.appendList(markers.toList()); | |
911 } | |
912 if (isSerializable) { | |
913 addDeserializationCase(refKind, refSym, tree.type, samSym, | |
914 tree, staticArgs, indyType); | |
915 } | |
916 } | |
917 | |
918 return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args); | |
713 } | 919 } |
714 | 920 |
715 /** | 921 /** |
716 * Generate an indy method call with given name, type and static bootstrap | 922 * Generate an indy method call with given name, type and static bootstrap |
717 * arguments types | 923 * arguments types |
793 } else { | 999 } else { |
794 return ClassFile.REF_invokeVirtual; | 1000 return ClassFile.REF_invokeVirtual; |
795 } | 1001 } |
796 } | 1002 } |
797 } | 1003 } |
1004 | |
798 // </editor-fold> | 1005 // </editor-fold> |
799 | 1006 |
800 // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">\ | 1007 // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">\ |
801 /** | 1008 /** |
802 * This visitor collects information about translation of a lambda expression. | 1009 * This visitor collects information about translation of a lambda expression. |
812 * keep the count of lambda expression (used to generate unambiguous | 1019 * keep the count of lambda expression (used to generate unambiguous |
813 * names) | 1020 * names) |
814 */ | 1021 */ |
815 private int lambdaCount = 0; | 1022 private int lambdaCount = 0; |
816 | 1023 |
1024 /** | |
1025 * keep the count of lambda expression defined in given context (used to | |
1026 * generate unambiguous names for serializable lambdas) | |
1027 */ | |
1028 private Map<String, Integer> serializableLambdaCounts = | |
1029 new HashMap<String, Integer>(); | |
1030 | |
1031 /** | |
1032 * maps for fake clinit symbols to be used as owners of lambda occurring in | |
1033 * a static var init context | |
1034 */ | |
1035 private Map<ClassSymbol, Symbol> clinits = | |
1036 new HashMap<ClassSymbol, Symbol>(); | |
1037 | |
817 private void analyzeClass(JCClassDecl tree) { | 1038 private void analyzeClass(JCClassDecl tree) { |
818 frameStack = List.nil(); | 1039 frameStack = List.nil(); |
819 scan(tree); | 1040 scan(tree); |
820 } | 1041 } |
821 | 1042 |
834 } | 1055 } |
835 | 1056 |
836 @Override | 1057 @Override |
837 public void visitClassDef(JCClassDecl tree) { | 1058 public void visitClassDef(JCClassDecl tree) { |
838 List<Frame> prevStack = frameStack; | 1059 List<Frame> prevStack = frameStack; |
1060 Map<String, Integer> prevSerializableLambdaCount = serializableLambdaCounts; | |
1061 Map<ClassSymbol, Symbol> prevClinits = clinits; | |
839 try { | 1062 try { |
840 if (frameStack.nonEmpty() && enclosingLambda() != null) { | 1063 serializableLambdaCounts = new HashMap<String, Integer>(); |
1064 prevClinits = new HashMap<ClassSymbol, Symbol>(); | |
1065 if (directlyEnclosingLambda() != null) { | |
841 tree.sym.owner = owner(); | 1066 tree.sym.owner = owner(); |
842 LambdaTranslationContext lambdaContext = (LambdaTranslationContext)contextMap.get(enclosingLambda()); | 1067 LambdaTranslationContext lambdaContext = (LambdaTranslationContext) contextMap.get(directlyEnclosingLambda()); |
843 Type encl = lambdaContext.enclosingType(); | 1068 Type encl = lambdaContext.enclosingType(); |
844 if (encl.hasTag(NONE)) { | 1069 if (encl.hasTag(NONE)) { |
845 //if the translated lambda body occurs in a static context, | 1070 //if the translated lambda body occurs in a static context, |
846 //any class declaration within it must be made static | 1071 //any class declaration within it must be made static |
1072 //@@@TODO: What about nested classes within lambda? | |
847 tree.sym.flags_field |= STATIC; | 1073 tree.sym.flags_field |= STATIC; |
848 ((ClassType)tree.sym.type).setEnclosingType(Type.noType); | 1074 ((ClassType) tree.sym.type).setEnclosingType(Type.noType); |
849 } else { | 1075 } else { |
850 //if the translated lambda body is in an instance context | 1076 //if the translated lambda body is in an instance context |
851 //the enclosing type of any class declaration within it | 1077 //the enclosing type of any class declaration within it |
852 //must be updated to point to the new enclosing type (if any) | 1078 //must be updated to point to the new enclosing type (if any) |
853 ((ClassType)tree.sym.type).setEnclosingType(encl); | 1079 ((ClassType) tree.sym.type).setEnclosingType(encl); |
854 } | 1080 } |
855 } | 1081 } |
856 frameStack = frameStack.prepend(new Frame(tree)); | 1082 frameStack = frameStack.prepend(new Frame(tree)); |
857 super.visitClassDef(tree); | 1083 super.visitClassDef(tree); |
858 } | 1084 } |
859 finally { | 1085 finally { |
860 frameStack = prevStack; | 1086 frameStack = prevStack; |
861 } | 1087 serializableLambdaCounts = prevSerializableLambdaCount; |
862 if (!tree.sym.isStatic() && frameStack.nonEmpty() && enclosingLambda() != null) { | 1088 clinits = prevClinits; |
1089 } | |
1090 if (!tree.sym.isStatic() && directlyEnclosingLambda() != null) { | |
863 // Any (non-static) class defined within a lambda is an implicit 'this' reference | 1091 // Any (non-static) class defined within a lambda is an implicit 'this' reference |
864 // because its constructor will reference the enclosing class | 1092 // because its constructor will reference the enclosing class |
865 ((LambdaTranslationContext) context()).addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS); | 1093 ((LambdaTranslationContext) context()).addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS); |
866 } | 1094 } |
867 } | 1095 } |
868 | 1096 |
869 @Override | 1097 @Override |
870 public void visitIdent(JCIdent tree) { | 1098 public void visitIdent(JCIdent tree) { |
871 if (context() == null || !lambdaIdentSymbolFilter(tree.sym)) { | 1099 if (context() != null && lambdaIdentSymbolFilter(tree.sym)) { |
872 super.visitIdent(tree); | |
873 } else { | |
874 if (tree.sym.kind == VAR && | 1100 if (tree.sym.kind == VAR && |
875 tree.sym.owner.kind == MTH && | 1101 tree.sym.owner.kind == MTH && |
876 tree.type.constValue() == null) { | 1102 tree.type.constValue() == null) { |
877 TranslationContext<?> localContext = context(); | 1103 TranslationContext<?> localContext = context(); |
878 while (localContext != null) { | 1104 while (localContext != null) { |
900 } | 1126 } |
901 localContext = localContext.prev; | 1127 localContext = localContext.prev; |
902 } | 1128 } |
903 } | 1129 } |
904 } | 1130 } |
1131 super.visitIdent(tree); | |
905 } | 1132 } |
906 | 1133 |
907 @Override | 1134 @Override |
908 public void visitLambda(JCLambda tree) { | 1135 public void visitLambda(JCLambda tree) { |
909 List<Frame> prevStack = frameStack; | 1136 List<Frame> prevStack = frameStack; |
967 } | 1194 } |
968 } | 1195 } |
969 | 1196 |
970 @Override | 1197 @Override |
971 public void visitVarDef(JCVariableDecl tree) { | 1198 public void visitVarDef(JCVariableDecl tree) { |
972 if (frameStack.head.tree.hasTag(LAMBDA)) { | 1199 TranslationContext<?> context = context(); |
973 ((LambdaTranslationContext)context()).addSymbol(tree.sym, LOCAL_VAR); | 1200 LambdaTranslationContext ltc = (context != null && context instanceof LambdaTranslationContext)? |
974 } | 1201 (LambdaTranslationContext)context : |
1202 null; | |
1203 if (ltc != null) { | |
1204 if (frameStack.head.tree.hasTag(LAMBDA)) { | |
1205 ltc.addSymbol(tree.sym, LOCAL_VAR); | |
1206 } | |
1207 // Check for type variables (including as type arguments). | |
1208 // If they occur within class nested in a lambda, mark for erasure | |
1209 Type type = tree.sym.asType(); | |
1210 if (inClassWithinLambda() && !types.isSameType(types.erasure(type), type)) { | |
1211 ltc.addSymbol(tree.sym, TYPE_VAR); | |
1212 } | |
1213 } | |
1214 | |
975 List<Frame> prevStack = frameStack; | 1215 List<Frame> prevStack = frameStack; |
976 try { | 1216 try { |
977 if (tree.sym.owner.kind == MTH) { | 1217 if (tree.sym.owner.kind == MTH) { |
978 frameStack.head.addLocal(tree.sym); | 1218 frameStack.head.addLocal(tree.sym); |
979 } | 1219 } |
984 frameStack = prevStack; | 1224 frameStack = prevStack; |
985 } | 1225 } |
986 } | 1226 } |
987 | 1227 |
988 private Name lambdaName() { | 1228 private Name lambdaName() { |
989 return names.lambda.append(names.fromString("$" + lambdaCount++)); | 1229 return names.lambda.append(names.fromString("" + lambdaCount++)); |
1230 } | |
1231 | |
1232 private Name serializedLambdaName(Symbol owner) { | |
1233 StringBuilder buf = new StringBuilder(); | |
1234 buf.append(names.lambda); | |
1235 buf.append(owner.name); | |
1236 buf.append('$'); | |
1237 int methTypeHash = methodSig(owner.type).hashCode(); | |
1238 buf.append(methTypeHash); | |
1239 buf.append('$'); | |
1240 String temp = buf.toString(); | |
1241 Integer count = serializableLambdaCounts.get(temp); | |
1242 if (count == null) { | |
1243 count = 0; | |
1244 } | |
1245 buf.append(count++); | |
1246 serializableLambdaCounts.put(temp, count); | |
1247 return names.fromString(buf.toString()); | |
990 } | 1248 } |
991 | 1249 |
992 /** | 1250 /** |
993 * Return a valid owner given the current declaration stack | 1251 * Return a valid owner given the current declaration stack |
994 * (required to skip synthetic lambda symbols) | 1252 * (required to skip synthetic lambda symbols) |
1006 if (((JCVariableDecl)frameStack2.head.tree).sym.isLocal()) { | 1264 if (((JCVariableDecl)frameStack2.head.tree).sym.isLocal()) { |
1007 frameStack2 = frameStack2.tail; | 1265 frameStack2 = frameStack2.tail; |
1008 break; | 1266 break; |
1009 } | 1267 } |
1010 JCClassDecl cdecl = (JCClassDecl)frameStack2.tail.head.tree; | 1268 JCClassDecl cdecl = (JCClassDecl)frameStack2.tail.head.tree; |
1011 return makeSyntheticMethod(((JCVariableDecl)frameStack2.head.tree).sym.flags() & STATIC, names.empty, null, cdecl.sym); | 1269 return initSym(cdecl.sym, |
1270 ((JCVariableDecl)frameStack2.head.tree).sym.flags() & STATIC); | |
1012 case BLOCK: | 1271 case BLOCK: |
1013 JCClassDecl cdecl2 = (JCClassDecl)frameStack2.tail.head.tree; | 1272 JCClassDecl cdecl2 = (JCClassDecl)frameStack2.tail.head.tree; |
1014 return makeSyntheticMethod(((JCBlock)frameStack2.head.tree).flags & STATIC | Flags.BLOCK, names.empty, null, cdecl2.sym); | 1273 return initSym(cdecl2.sym, |
1274 ((JCBlock)frameStack2.head.tree).flags & STATIC); | |
1015 case CLASSDEF: | 1275 case CLASSDEF: |
1016 return ((JCClassDecl)frameStack2.head.tree).sym; | 1276 return ((JCClassDecl)frameStack2.head.tree).sym; |
1017 case METHODDEF: | 1277 case METHODDEF: |
1018 return ((JCMethodDecl)frameStack2.head.tree).sym; | 1278 return ((JCMethodDecl)frameStack2.head.tree).sym; |
1019 case LAMBDA: | 1279 case LAMBDA: |
1025 } | 1285 } |
1026 Assert.error(); | 1286 Assert.error(); |
1027 return null; | 1287 return null; |
1028 } | 1288 } |
1029 | 1289 |
1030 private JCTree enclosingLambda() { | 1290 private Symbol initSym(ClassSymbol csym, long flags) { |
1291 boolean isStatic = (flags & STATIC) != 0; | |
1292 if (isStatic) { | |
1293 //static clinits are generated in Gen - so we need to fake them | |
1294 Symbol clinit = clinits.get(csym); | |
1295 if (clinit == null) { | |
1296 clinit = makeSyntheticMethod(STATIC, | |
1297 names.clinit, | |
1298 new MethodType(List.<Type>nil(), syms.voidType, List.<Type>nil(), syms.methodClass), | |
1299 csym); | |
1300 clinits.put(csym, clinit); | |
1301 } | |
1302 return clinit; | |
1303 } else { | |
1304 //get the first constructor and treat it as the instance init sym | |
1305 for (Symbol s : csym.members_field.getElementsByName(names.init)) { | |
1306 return s; | |
1307 } | |
1308 } | |
1309 Assert.error("init not found"); | |
1310 return null; | |
1311 } | |
1312 | |
1313 private JCTree directlyEnclosingLambda() { | |
1314 if (frameStack.isEmpty()) { | |
1315 return null; | |
1316 } | |
1031 List<Frame> frameStack2 = frameStack; | 1317 List<Frame> frameStack2 = frameStack; |
1032 while (frameStack2.nonEmpty()) { | 1318 while (frameStack2.nonEmpty()) { |
1033 switch (frameStack2.head.tree.getTag()) { | 1319 switch (frameStack2.head.tree.getTag()) { |
1034 case CLASSDEF: | 1320 case CLASSDEF: |
1035 case METHODDEF: | 1321 case METHODDEF: |
1040 frameStack2 = frameStack2.tail; | 1326 frameStack2 = frameStack2.tail; |
1041 } | 1327 } |
1042 } | 1328 } |
1043 Assert.error(); | 1329 Assert.error(); |
1044 return null; | 1330 return null; |
1331 } | |
1332 | |
1333 private boolean inClassWithinLambda() { | |
1334 if (frameStack.isEmpty()) { | |
1335 return false; | |
1336 } | |
1337 List<Frame> frameStack2 = frameStack; | |
1338 boolean classFound = false; | |
1339 while (frameStack2.nonEmpty()) { | |
1340 switch (frameStack2.head.tree.getTag()) { | |
1341 case LAMBDA: | |
1342 return classFound; | |
1343 case CLASSDEF: | |
1344 classFound = true; | |
1345 frameStack2 = frameStack2.tail; | |
1346 break; | |
1347 default: | |
1348 frameStack2 = frameStack2.tail; | |
1349 } | |
1350 } | |
1351 // No lambda | |
1352 return false; | |
1045 } | 1353 } |
1046 | 1354 |
1047 /** | 1355 /** |
1048 * Return the declaration corresponding to a symbol in the enclosing | 1356 * Return the declaration corresponding to a symbol in the enclosing |
1049 * scope; the depth parameter is used to filter out symbols defined | 1357 * scope; the depth parameter is used to filter out symbols defined |
1176 this.tree = tree; | 1484 this.tree = tree; |
1177 this.owner = owner(); | 1485 this.owner = owner(); |
1178 this.depth = frameStack.size() - 1; | 1486 this.depth = frameStack.size() - 1; |
1179 this.prev = context(); | 1487 this.prev = context(); |
1180 } | 1488 } |
1489 | |
1490 /** does this functional expression need to be created using alternate metafactory? */ | |
1491 boolean needsAltMetafactory() { | |
1492 return (tree.targets.length() > 1 || | |
1493 isSerializable()); | |
1494 } | |
1495 | |
1496 /** does this functional expression require serialization support? */ | |
1497 boolean isSerializable() { | |
1498 for (Symbol target : tree.targets) { | |
1499 if (types.asSuper(target.type, syms.serializableType.tsym) != null) { | |
1500 return true; | |
1501 } | |
1502 } | |
1503 return false; | |
1504 } | |
1181 } | 1505 } |
1182 | 1506 |
1183 /** | 1507 /** |
1184 * This class retains all the useful information about a lambda expression; | 1508 * This class retains all the useful information about a lambda expression; |
1185 * the contents of this class are filled by the LambdaAnalyzer visitor, | 1509 * the contents of this class are filled by the LambdaAnalyzer visitor, |
1201 Map<Symbol, Symbol> capturedLocals = new LinkedHashMap<Symbol, Symbol>(); | 1525 Map<Symbol, Symbol> capturedLocals = new LinkedHashMap<Symbol, Symbol>(); |
1202 | 1526 |
1203 /** map from class symbols to translated synthetic parameters (for captured member access) */ | 1527 /** map from class symbols to translated synthetic parameters (for captured member access) */ |
1204 Map<Symbol, Symbol> capturedThis = new LinkedHashMap<Symbol, Symbol>(); | 1528 Map<Symbol, Symbol> capturedThis = new LinkedHashMap<Symbol, Symbol>(); |
1205 | 1529 |
1530 /** map from original to translated lambda locals */ | |
1531 Map<Symbol, Symbol> typeVars = new LinkedHashMap<Symbol, Symbol>(); | |
1532 | |
1206 /** the synthetic symbol for the method hoisting the translated lambda */ | 1533 /** the synthetic symbol for the method hoisting the translated lambda */ |
1207 Symbol translatedSym; | 1534 Symbol translatedSym; |
1208 | 1535 |
1209 List<JCVariableDecl> syntheticParams; | 1536 List<JCVariableDecl> syntheticParams; |
1210 | 1537 |
1212 super(tree); | 1539 super(tree); |
1213 Frame frame = frameStack.head; | 1540 Frame frame = frameStack.head; |
1214 if (frame.tree.hasTag(VARDEF)) { | 1541 if (frame.tree.hasTag(VARDEF)) { |
1215 self = ((JCVariableDecl)frame.tree).sym; | 1542 self = ((JCVariableDecl)frame.tree).sym; |
1216 } | 1543 } |
1217 this.translatedSym = makeSyntheticMethod(0, lambdaName(), null, owner.enclClass()); | 1544 Name name = isSerializable() ? serializedLambdaName(owner) : lambdaName(); |
1545 this.translatedSym = makeSyntheticMethod(0, name, null, owner.enclClass()); | |
1218 } | 1546 } |
1219 | 1547 |
1220 /** | 1548 /** |
1221 * Translate a symbol of a given kind into something suitable for the | 1549 * Translate a symbol of a given kind into something suitable for the |
1222 * synthetic lambda body | 1550 * synthetic lambda body |
1223 */ | 1551 */ |
1224 Symbol translate(String name, Symbol sym, LambdaSymbolKind skind) { | 1552 Symbol translate(String name, Symbol sym, LambdaSymbolKind skind) { |
1225 if (skind == CAPTURED_THIS) { | 1553 switch (skind) { |
1226 return sym; // self represented | 1554 case CAPTURED_THIS: |
1227 } else { | 1555 return sym; // self represented |
1228 return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym); | 1556 case TYPE_VAR: |
1557 // Just erase the type var | |
1558 return new VarSymbol(sym.flags(), names.fromString(name), types.erasure(sym.type), sym.owner); | |
1559 default: | |
1560 return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym); | |
1229 } | 1561 } |
1230 } | 1562 } |
1231 | 1563 |
1232 void addSymbol(Symbol sym, LambdaSymbolKind skind) { | 1564 void addSymbol(Symbol sym, LambdaSymbolKind skind) { |
1233 Map<Symbol, Symbol> transMap = null; | 1565 Map<Symbol, Symbol> transMap = null; |
1247 break; | 1579 break; |
1248 case PARAM: | 1580 case PARAM: |
1249 transMap = lambdaParams; | 1581 transMap = lambdaParams; |
1250 preferredName = sym.name.toString(); | 1582 preferredName = sym.name.toString(); |
1251 break; | 1583 break; |
1584 case TYPE_VAR: | |
1585 transMap = typeVars; | |
1586 preferredName = sym.name.toString(); | |
1587 break; | |
1252 default: throw new AssertionError(); | 1588 default: throw new AssertionError(); |
1253 } | 1589 } |
1254 if (!transMap.containsKey(sym)) { | 1590 if (!transMap.containsKey(sym)) { |
1255 transMap.put(sym, translate(preferredName, sym, skind)); | 1591 transMap.put(sym, translate(preferredName, sym, skind)); |
1256 } | 1592 } |
1270 translationMap.putAll(lambdaLocals); | 1606 translationMap.putAll(lambdaLocals); |
1271 break; | 1607 break; |
1272 case PARAM: | 1608 case PARAM: |
1273 translationMap.putAll(lambdaParams); | 1609 translationMap.putAll(lambdaParams); |
1274 break; | 1610 break; |
1611 case TYPE_VAR: | |
1612 translationMap.putAll(typeVars); | |
1613 break; | |
1275 default: throw new AssertionError(); | 1614 default: throw new AssertionError(); |
1276 } | 1615 } |
1277 } | 1616 } |
1278 return translationMap; | 1617 return translationMap; |
1279 } | 1618 } |
1309 } | 1648 } |
1310 | 1649 |
1311 syntheticParams = params.toList(); | 1650 syntheticParams = params.toList(); |
1312 | 1651 |
1313 //prepend synthetic args to translated lambda method signature | 1652 //prepend synthetic args to translated lambda method signature |
1314 translatedSym.type = (MethodType) types.createMethodTypeWithParameters( | 1653 translatedSym.type = types.createMethodTypeWithParameters( |
1315 (MethodType) generatedLambdaSig(), | 1654 generatedLambdaSig(), |
1316 TreeInfo.types(syntheticParams)); | 1655 TreeInfo.types(syntheticParams)); |
1317 } | 1656 } |
1318 | 1657 |
1319 Type enclosingType() { | 1658 Type enclosingType() { |
1320 return owner.isStatic() ? | 1659 return owner.isStatic() ? |
1387 | 1726 |
1388 enum LambdaSymbolKind { | 1727 enum LambdaSymbolKind { |
1389 CAPTURED_VAR, | 1728 CAPTURED_VAR, |
1390 CAPTURED_THIS, | 1729 CAPTURED_THIS, |
1391 LOCAL_VAR, | 1730 LOCAL_VAR, |
1392 PARAM; | 1731 PARAM, |
1732 TYPE_VAR; | |
1733 } | |
1734 | |
1735 /** | |
1736 * **************************************************************** | |
1737 * Signature Generation | |
1738 * **************************************************************** | |
1739 */ | |
1740 | |
1741 private String methodSig(Type type) { | |
1742 L2MSignatureGenerator sg = new L2MSignatureGenerator(); | |
1743 sg.assembleSig(type); | |
1744 return sg.toString(); | |
1745 } | |
1746 | |
1747 private String classSig(Type type) { | |
1748 L2MSignatureGenerator sg = new L2MSignatureGenerator(); | |
1749 sg.assembleClassSig(type); | |
1750 return sg.toString(); | |
1751 } | |
1752 | |
1753 /** | |
1754 * Signature Generation | |
1755 */ | |
1756 private class L2MSignatureGenerator extends Types.SignatureGenerator { | |
1757 | |
1758 /** | |
1759 * An output buffer for type signatures. | |
1760 */ | |
1761 StringBuilder sb = new StringBuilder(); | |
1762 | |
1763 L2MSignatureGenerator() { | |
1764 super(types); | |
1765 } | |
1766 | |
1767 @Override | |
1768 protected void append(char ch) { | |
1769 sb.append(ch); | |
1770 } | |
1771 | |
1772 @Override | |
1773 protected void append(byte[] ba) { | |
1774 sb.append(new String(ba)); | |
1775 } | |
1776 | |
1777 @Override | |
1778 protected void append(Name name) { | |
1779 sb.append(name.toString()); | |
1780 } | |
1781 | |
1782 @Override | |
1783 public String toString() { | |
1784 return sb.toString(); | |
1785 } | |
1393 } | 1786 } |
1394 } | 1787 } |