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; |
41 import com.sun.tools.javac.code.Symtab; |
41 import com.sun.tools.javac.code.Symtab; |
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; |
|
44 import com.sun.tools.javac.code.Type.MethodType; |
43 import com.sun.tools.javac.code.Type.MethodType; |
45 import com.sun.tools.javac.code.Types; |
44 import com.sun.tools.javac.code.Types; |
46 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzer.*; |
45 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*; |
47 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector; |
46 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector; |
48 import com.sun.tools.javac.jvm.*; |
47 import com.sun.tools.javac.jvm.*; |
49 import com.sun.tools.javac.util.*; |
48 import com.sun.tools.javac.util.*; |
50 import com.sun.tools.javac.util.List; |
49 import com.sun.tools.javac.util.List; |
51 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
50 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
79 private Types types; |
78 private Types types; |
80 private TransTypes transTypes; |
79 private TransTypes transTypes; |
81 private Env<AttrContext> attrEnv; |
80 private Env<AttrContext> attrEnv; |
82 |
81 |
83 /** the analyzer scanner */ |
82 /** the analyzer scanner */ |
84 private LambdaAnalyzer analyzer; |
83 private LambdaAnalyzerPreprocessor analyzer; |
85 |
84 |
86 /** map from lambda trees to translation contexts */ |
85 /** map from lambda trees to translation contexts */ |
87 private Map<JCTree, TranslationContext<?>> contextMap; |
86 private Map<JCTree, TranslationContext<?>> contextMap; |
88 |
87 |
89 /** current translation context (visitor argument) */ |
88 /** current translation context (visitor argument) */ |
154 syms = Symtab.instance(context); |
153 syms = Symtab.instance(context); |
155 rs = Resolve.instance(context); |
154 rs = Resolve.instance(context); |
156 make = TreeMaker.instance(context); |
155 make = TreeMaker.instance(context); |
157 types = Types.instance(context); |
156 types = Types.instance(context); |
158 transTypes = TransTypes.instance(context); |
157 transTypes = TransTypes.instance(context); |
159 analyzer = new LambdaAnalyzer(); |
158 analyzer = new LambdaAnalyzerPreprocessor(); |
160 } |
159 } |
161 // </editor-fold> |
160 // </editor-fold> |
162 |
161 |
163 // <editor-fold defaultstate="collapsed" desc="translate methods"> |
162 // <editor-fold defaultstate="collapsed" desc="translate methods"> |
164 @Override |
163 @Override |
204 */ |
203 */ |
205 @Override |
204 @Override |
206 public void visitClassDef(JCClassDecl tree) { |
205 public void visitClassDef(JCClassDecl tree) { |
207 if (tree.sym.owner.kind == PCK) { |
206 if (tree.sym.owner.kind == PCK) { |
208 //analyze class |
207 //analyze class |
209 analyzer.analyzeClass(tree); |
208 tree = analyzer.analyzeAndPreprocessClass(tree); |
210 } |
209 } |
211 KlassInfo prevKlassInfo = kInfo; |
210 KlassInfo prevKlassInfo = kInfo; |
212 try { |
211 try { |
213 kInfo = new KlassInfo(tree.sym); |
212 kInfo = new KlassInfo(tree.sym); |
214 super.visitClassDef(tree); |
213 super.visitClassDef(tree); |
529 } |
528 } |
530 |
529 |
531 /** Make an attributed class instance creation expression. |
530 /** Make an attributed class instance creation expression. |
532 * @param ctype The class type. |
531 * @param ctype The class type. |
533 * @param args The constructor arguments. |
532 * @param args The constructor arguments. |
|
533 * @param cons The constructor symbol |
|
534 */ |
|
535 JCNewClass makeNewClass(Type ctype, List<JCExpression> args, Symbol cons) { |
|
536 JCNewClass tree = make.NewClass(null, |
|
537 null, make.QualIdent(ctype.tsym), args, null); |
|
538 tree.constructor = cons; |
|
539 tree.type = ctype; |
|
540 return tree; |
|
541 } |
|
542 |
|
543 /** Make an attributed class instance creation expression. |
|
544 * @param ctype The class type. |
|
545 * @param args The constructor arguments. |
534 */ |
546 */ |
535 JCNewClass makeNewClass(Type ctype, List<JCExpression> args) { |
547 JCNewClass makeNewClass(Type ctype, List<JCExpression> args) { |
536 JCNewClass tree = make.NewClass(null, |
548 return makeNewClass(ctype, args, |
537 null, make.QualIdent(ctype.tsym), args, null); |
549 rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil())); |
538 tree.constructor = rs.resolveConstructor( |
550 } |
539 null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil()); |
|
540 tree.type = ctype; |
|
541 return tree; |
|
542 } |
|
543 |
551 |
544 private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym, |
552 private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym, |
545 DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) { |
553 DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) { |
546 String functionalInterfaceClass = classSig(targetType); |
554 String functionalInterfaceClass = classSig(targetType); |
547 String functionalInterfaceMethodName = samSym.getSimpleName().toString(); |
555 String functionalInterfaceMethodName = samSym.getSimpleName().toString(); |
1017 // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer"> |
1025 // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer"> |
1018 /** |
1026 /** |
1019 * This visitor collects information about translation of a lambda expression. |
1027 * This visitor collects information about translation of a lambda expression. |
1020 * More specifically, it keeps track of the enclosing contexts and captured locals |
1028 * More specifically, it keeps track of the enclosing contexts and captured locals |
1021 * accessed by the lambda being translated (as well as other useful info). |
1029 * accessed by the lambda being translated (as well as other useful info). |
|
1030 * It also translates away problems for LambdaToMethod. |
1022 */ |
1031 */ |
1023 class LambdaAnalyzer extends TreeScanner { |
1032 class LambdaAnalyzerPreprocessor extends TreeTranslator { |
1024 |
1033 |
1025 /** the frame stack - used to reconstruct translation info about enclosing scopes */ |
1034 /** the frame stack - used to reconstruct translation info about enclosing scopes */ |
1026 private List<Frame> frameStack; |
1035 private List<Frame> frameStack; |
1027 |
1036 |
1028 /** |
1037 /** |
1045 * a static var init context |
1054 * a static var init context |
1046 */ |
1055 */ |
1047 private Map<ClassSymbol, Symbol> clinits = |
1056 private Map<ClassSymbol, Symbol> clinits = |
1048 new HashMap<ClassSymbol, Symbol>(); |
1057 new HashMap<ClassSymbol, Symbol>(); |
1049 |
1058 |
1050 private void analyzeClass(JCClassDecl tree) { |
1059 private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) { |
1051 frameStack = List.nil(); |
1060 frameStack = List.nil(); |
1052 localClassDefs = new HashMap<Symbol, JCClassDecl>(); |
1061 localClassDefs = new HashMap<Symbol, JCClassDecl>(); |
1053 scan(tree); |
1062 return translate(tree); |
1054 } |
1063 } |
1055 |
1064 |
1056 @Override |
1065 @Override |
1057 public void visitBlock(JCBlock tree) { |
1066 public void visitBlock(JCBlock tree) { |
1058 List<Frame> prevStack = frameStack; |
1067 List<Frame> prevStack = frameStack; |
1152 for (JCVariableDecl param : tree.params) { |
1161 for (JCVariableDecl param : tree.params) { |
1153 context.addSymbol(param.sym, PARAM); |
1162 context.addSymbol(param.sym, PARAM); |
1154 frameStack.head.addLocal(param.sym); |
1163 frameStack.head.addLocal(param.sym); |
1155 } |
1164 } |
1156 contextMap.put(tree, context); |
1165 contextMap.put(tree, context); |
1157 scan(tree.body); |
1166 super.visitLambda(tree); |
1158 context.complete(); |
1167 context.complete(); |
1159 } |
1168 } |
1160 finally { |
1169 finally { |
1161 frameStack = prevStack; |
1170 frameStack = prevStack; |
1162 } |
1171 } |
1218 } |
1227 } |
1219 } |
1228 } |
1220 }; |
1229 }; |
1221 fvc.scan(localCDef); |
1230 fvc.scan(localCDef); |
1222 } |
1231 } |
1223 } |
1232 } |
1224 |
1233 |
|
1234 /** |
|
1235 * Method references to local class constructors, may, if the local |
|
1236 * class references local variables, have implicit constructor |
|
1237 * parameters added in Lower; As a result, the invokedynamic bootstrap |
|
1238 * information added in the LambdaToMethod pass will have the wrong |
|
1239 * signature. Hooks between Lower and LambdaToMethod have been added to |
|
1240 * handle normal "new" in this case. This visitor converts potentially |
|
1241 * effected method references into a lambda containing a normal "new" of |
|
1242 * the class. |
|
1243 * |
|
1244 * @param tree |
|
1245 */ |
1225 @Override |
1246 @Override |
1226 public void visitReference(JCMemberReference tree) { |
1247 public void visitReference(JCMemberReference tree) { |
1227 scan(tree.getQualifierExpression()); |
1248 if (tree.getMode() == ReferenceMode.NEW |
1228 contextMap.put(tree, makeReferenceContext(tree)); |
1249 && tree.kind != ReferenceKind.ARRAY_CTOR |
|
1250 && tree.sym.owner.isLocal()) { |
|
1251 MethodSymbol consSym = (MethodSymbol) tree.sym; |
|
1252 List<Type> ptypes = ((MethodType) consSym.type).getParameterTypes(); |
|
1253 Type classType = consSym.owner.type; |
|
1254 |
|
1255 // Make new-class call |
|
1256 List<JCVariableDecl> params = make.Params(ptypes, owner()); |
|
1257 JCNewClass nc = makeNewClass(classType, make.Idents(params)); |
|
1258 nc.pos = tree.pos; |
|
1259 |
|
1260 // Make lambda holding the new-class call |
|
1261 JCLambda slam = make.Lambda(params, nc); |
|
1262 slam.descriptorType = tree.descriptorType; |
|
1263 slam.targets = tree.targets; |
|
1264 slam.type = tree.type; |
|
1265 slam.pos = tree.pos; |
|
1266 |
|
1267 // Now it is a lambda, process as such |
|
1268 visitLambda(slam); |
|
1269 } else { |
|
1270 super.visitReference(tree); |
|
1271 contextMap.put(tree, makeReferenceContext(tree)); |
|
1272 } |
1229 } |
1273 } |
1230 |
1274 |
1231 @Override |
1275 @Override |
1232 public void visitSelect(JCFieldAccess tree) { |
1276 public void visitSelect(JCFieldAccess tree) { |
1233 if (context() != null && lambdaSelectSymbolFilter(tree.sym)) { |
1277 if (context() != null && lambdaSelectSymbolFilter(tree.sym)) { |
1238 if (clazz == null) break; |
1282 if (clazz == null) break; |
1239 ((LambdaTranslationContext)localContext).addSymbol(clazz.sym, CAPTURED_THIS); |
1283 ((LambdaTranslationContext)localContext).addSymbol(clazz.sym, CAPTURED_THIS); |
1240 } |
1284 } |
1241 localContext = localContext.prev; |
1285 localContext = localContext.prev; |
1242 } |
1286 } |
1243 scan(tree.selected); |
1287 } |
1244 } else { |
1288 super.visitSelect(tree); |
1245 super.visitSelect(tree); |
|
1246 } |
|
1247 } |
1289 } |
1248 |
1290 |
1249 @Override |
1291 @Override |
1250 public void visitVarDef(JCVariableDecl tree) { |
1292 public void visitVarDef(JCVariableDecl tree) { |
1251 TranslationContext<?> context = context(); |
1293 TranslationContext<?> context = context(); |