42 import com.sun.tools.javac.code.Type; |
42 import com.sun.tools.javac.code.Type; |
43 import com.sun.tools.javac.code.Type.ClassType; |
43 import com.sun.tools.javac.code.Type.ClassType; |
44 import com.sun.tools.javac.code.Type.MethodType; |
44 import com.sun.tools.javac.code.Type.MethodType; |
45 import com.sun.tools.javac.code.Types; |
45 import com.sun.tools.javac.code.Types; |
46 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzer.*; |
46 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzer.*; |
|
47 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector; |
47 import com.sun.tools.javac.jvm.*; |
48 import com.sun.tools.javac.jvm.*; |
48 import com.sun.tools.javac.util.*; |
49 import com.sun.tools.javac.util.*; |
49 import com.sun.tools.javac.util.List; |
50 import com.sun.tools.javac.util.List; |
50 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
51 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
51 import com.sun.source.tree.MemberReferenceTree.ReferenceMode; |
52 import com.sun.source.tree.MemberReferenceTree.ReferenceMode; |
145 } |
147 } |
146 return instance; |
148 return instance; |
147 } |
149 } |
148 |
150 |
149 private LambdaToMethod(Context context) { |
151 private LambdaToMethod(Context context) { |
|
152 lower = Lower.instance(context); |
150 names = Names.instance(context); |
153 names = Names.instance(context); |
151 syms = Symtab.instance(context); |
154 syms = Symtab.instance(context); |
152 rs = Resolve.instance(context); |
155 rs = Resolve.instance(context); |
153 make = TreeMaker.instance(context); |
156 make = TreeMaker.instance(context); |
154 types = Types.instance(context); |
157 types = Types.instance(context); |
1035 * generate unambiguous names for serializable lambdas) |
1038 * generate unambiguous names for serializable lambdas) |
1036 */ |
1039 */ |
1037 private Map<String, Integer> serializableLambdaCounts = |
1040 private Map<String, Integer> serializableLambdaCounts = |
1038 new HashMap<String, Integer>(); |
1041 new HashMap<String, Integer>(); |
1039 |
1042 |
|
1043 private Map<Symbol, JCClassDecl> localClassDefs; |
|
1044 |
1040 /** |
1045 /** |
1041 * maps for fake clinit symbols to be used as owners of lambda occurring in |
1046 * maps for fake clinit symbols to be used as owners of lambda occurring in |
1042 * a static var init context |
1047 * a static var init context |
1043 */ |
1048 */ |
1044 private Map<ClassSymbol, Symbol> clinits = |
1049 private Map<ClassSymbol, Symbol> clinits = |
1045 new HashMap<ClassSymbol, Symbol>(); |
1050 new HashMap<ClassSymbol, Symbol>(); |
1046 |
1051 |
1047 private void analyzeClass(JCClassDecl tree) { |
1052 private void analyzeClass(JCClassDecl tree) { |
1048 frameStack = List.nil(); |
1053 frameStack = List.nil(); |
|
1054 localClassDefs = new HashMap<Symbol, JCClassDecl>(); |
1049 scan(tree); |
1055 scan(tree); |
1050 } |
1056 } |
1051 |
1057 |
1052 @Override |
1058 @Override |
1053 public void visitBlock(JCBlock tree) { |
1059 public void visitBlock(JCBlock tree) { |
1070 serializableLambdaCounts; |
1076 serializableLambdaCounts; |
1071 Map<ClassSymbol, Symbol> prevClinits = clinits; |
1077 Map<ClassSymbol, Symbol> prevClinits = clinits; |
1072 try { |
1078 try { |
1073 serializableLambdaCounts = new HashMap<String, Integer>(); |
1079 serializableLambdaCounts = new HashMap<String, Integer>(); |
1074 prevClinits = new HashMap<ClassSymbol, Symbol>(); |
1080 prevClinits = new HashMap<ClassSymbol, Symbol>(); |
|
1081 if (tree.sym.owner.kind == MTH) { |
|
1082 localClassDefs.put(tree.sym, tree); |
|
1083 } |
1075 if (directlyEnclosingLambda() != null) { |
1084 if (directlyEnclosingLambda() != null) { |
1076 tree.sym.owner = owner(); |
1085 tree.sym.owner = owner(); |
1077 if (tree.sym.hasOuterInstance()) { |
1086 if (tree.sym.hasOuterInstance()) { |
1078 //if a class is defined within a lambda, the lambda must capture |
1087 //if a class is defined within a lambda, the lambda must capture |
1079 //its enclosing instance (if any) |
1088 //its enclosing instance (if any) |
1080 ((LambdaTranslationContext) context()) |
1089 TranslationContext<?> localContext = context(); |
1081 .addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS); |
1090 while (localContext != null) { |
|
1091 if (localContext.tree.getTag() == LAMBDA) { |
|
1092 ((LambdaTranslationContext)localContext) |
|
1093 .addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS); |
|
1094 } |
|
1095 localContext = localContext.prev; |
|
1096 } |
1082 } |
1097 } |
1083 } |
1098 } |
1084 frameStack = frameStack.prepend(new Frame(tree)); |
1099 frameStack = frameStack.prepend(new Frame(tree)); |
1085 super.visitClassDef(tree); |
1100 super.visitClassDef(tree); |
1086 } |
1101 } |
1162 } |
1177 } |
1163 |
1178 |
1164 @Override |
1179 @Override |
1165 public void visitNewClass(JCNewClass tree) { |
1180 public void visitNewClass(JCNewClass tree) { |
1166 if (lambdaNewClassFilter(context(), tree)) { |
1181 if (lambdaNewClassFilter(context(), tree)) { |
1167 ((LambdaTranslationContext) context()) |
1182 TranslationContext<?> localContext = context(); |
1168 .addSymbol(tree.type.getEnclosingType().tsym, CAPTURED_THIS); |
1183 while (localContext != null) { |
|
1184 if (localContext.tree.getTag() == LAMBDA) { |
|
1185 ((LambdaTranslationContext)localContext) |
|
1186 .addSymbol(tree.type.getEnclosingType().tsym, CAPTURED_THIS); |
|
1187 } |
|
1188 localContext = localContext.prev; |
|
1189 } |
|
1190 } |
|
1191 if (context() != null && tree.type.tsym.owner.kind == MTH) { |
|
1192 LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context(); |
|
1193 captureLocalClassDefs(tree.type.tsym, lambdaContext); |
1169 } |
1194 } |
1170 super.visitNewClass(tree); |
1195 super.visitNewClass(tree); |
1171 } |
1196 } |
|
1197 //where |
|
1198 void captureLocalClassDefs(Symbol csym, final LambdaTranslationContext lambdaContext) { |
|
1199 JCClassDecl localCDef = localClassDefs.get(csym); |
|
1200 if (localCDef != null && localCDef.pos < lambdaContext.tree.pos) { |
|
1201 BasicFreeVarCollector fvc = lower.new BasicFreeVarCollector() { |
|
1202 @Override |
|
1203 void addFreeVars(ClassSymbol c) { |
|
1204 captureLocalClassDefs(c, lambdaContext); |
|
1205 } |
|
1206 @Override |
|
1207 void visitSymbol(Symbol sym) { |
|
1208 if (sym.kind == VAR && |
|
1209 sym.owner.kind == MTH && |
|
1210 ((VarSymbol)sym).getConstValue() == null) { |
|
1211 TranslationContext<?> localContext = context(); |
|
1212 while (localContext != null) { |
|
1213 if (localContext.tree.getTag() == LAMBDA) { |
|
1214 JCTree block = capturedDecl(localContext.depth, sym); |
|
1215 if (block == null) break; |
|
1216 ((LambdaTranslationContext)localContext).addSymbol(sym, CAPTURED_VAR); |
|
1217 } |
|
1218 localContext = localContext.prev; |
|
1219 } |
|
1220 } |
|
1221 } |
|
1222 }; |
|
1223 fvc.scan(localCDef); |
|
1224 } |
|
1225 } |
1172 |
1226 |
1173 @Override |
1227 @Override |
1174 public void visitReference(JCMemberReference tree) { |
1228 public void visitReference(JCMemberReference tree) { |
1175 scan(tree.getQualifierExpression()); |
1229 scan(tree.getQualifierExpression()); |
1176 contextMap.put(tree, makeReferenceContext(tree)); |
1230 contextMap.put(tree, makeReferenceContext(tree)); |
1548 |
1602 |
1549 /** |
1603 /** |
1550 * Translate a symbol of a given kind into something suitable for the |
1604 * Translate a symbol of a given kind into something suitable for the |
1551 * synthetic lambda body |
1605 * synthetic lambda body |
1552 */ |
1606 */ |
1553 Symbol translate(String name, Symbol sym, LambdaSymbolKind skind) { |
1607 Symbol translate(String name, final Symbol sym, LambdaSymbolKind skind) { |
1554 switch (skind) { |
1608 switch (skind) { |
1555 case CAPTURED_THIS: |
1609 case CAPTURED_THIS: |
1556 return sym; // self represented |
1610 return sym; // self represented |
1557 case TYPE_VAR: |
1611 case TYPE_VAR: |
1558 // Just erase the type var |
1612 // Just erase the type var |
1559 return new VarSymbol(sym.flags(), names.fromString(name), |
1613 return new VarSymbol(sym.flags(), names.fromString(name), |
1560 types.erasure(sym.type), sym.owner); |
1614 types.erasure(sym.type), sym.owner); |
|
1615 case CAPTURED_VAR: |
|
1616 return new VarSymbol(SYNTHETIC | FINAL, names.fromString(name), types.erasure(sym.type), translatedSym) { |
|
1617 @Override |
|
1618 public Symbol baseSymbol() { |
|
1619 //keep mapping with original captured symbol |
|
1620 return sym; |
|
1621 } |
|
1622 }; |
1561 default: |
1623 default: |
1562 return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym); |
1624 return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym); |
1563 } |
1625 } |
1564 } |
1626 } |
1565 |
1627 |