1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Mar 01 10:47:39 2013 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Tue Mar 05 14:04:57 2013 +0000 1.3 @@ -163,6 +163,12 @@ 1.4 */ 1.5 JCTree outermostMemberDef; 1.6 1.7 + /** A map from local variable symbols to their translation (as per LambdaToMethod). 1.8 + * This is required when a capturing local class is created from a lambda (in which 1.9 + * case the captured symbols should be replaced with the translated lambda symbols). 1.10 + */ 1.11 + Map<Symbol, Symbol> lambdaTranslationMap = null; 1.12 + 1.13 /** A navigator class for assembling a mapping from local class symbols 1.14 * to class definition trees. 1.15 * There is only one case; all other cases simply traverse down the tree. 1.16 @@ -206,10 +212,51 @@ 1.17 Map<ClassSymbol,List<VarSymbol>> freevarCache; 1.18 1.19 /** A navigator class for collecting the free variables accessed 1.20 - * from a local class. 1.21 - * There is only one case; all other cases simply traverse down the tree. 1.22 + * from a local class. There is only one case; all other cases simply 1.23 + * traverse down the tree. This class doesn't deal with the specific 1.24 + * of Lower - it's an abstract visitor that is meant to be reused in 1.25 + * order to share the local variable capture logic. 1.26 */ 1.27 - class FreeVarCollector extends TreeScanner { 1.28 + abstract class BasicFreeVarCollector extends TreeScanner { 1.29 + 1.30 + /** Add all free variables of class c to fvs list 1.31 + * unless they are already there. 1.32 + */ 1.33 + abstract void addFreeVars(ClassSymbol c); 1.34 + 1.35 + /** If tree refers to a variable in owner of local class, add it to 1.36 + * free variables list. 1.37 + */ 1.38 + public void visitIdent(JCIdent tree) { 1.39 + visitSymbol(tree.sym); 1.40 + } 1.41 + // where 1.42 + abstract void visitSymbol(Symbol _sym); 1.43 + 1.44 + /** If tree refers to a class instance creation expression 1.45 + * add all free variables of the freshly created class. 1.46 + */ 1.47 + public void visitNewClass(JCNewClass tree) { 1.48 + ClassSymbol c = (ClassSymbol)tree.constructor.owner; 1.49 + addFreeVars(c); 1.50 + super.visitNewClass(tree); 1.51 + } 1.52 + 1.53 + /** If tree refers to a superclass constructor call, 1.54 + * add all free variables of the superclass. 1.55 + */ 1.56 + public void visitApply(JCMethodInvocation tree) { 1.57 + if (TreeInfo.name(tree.meth) == names._super) { 1.58 + addFreeVars((ClassSymbol) TreeInfo.symbol(tree.meth).owner); 1.59 + } 1.60 + super.visitApply(tree); 1.61 + } 1.62 + } 1.63 + 1.64 + /** 1.65 + * Lower-specific subclass of {@code BasicFreeVarCollector}. 1.66 + */ 1.67 + class FreeVarCollector extends BasicFreeVarCollector { 1.68 1.69 /** The owner of the local class. 1.70 */ 1.71 @@ -238,10 +285,8 @@ 1.72 fvs = fvs.prepend(v); 1.73 } 1.74 1.75 - /** Add all free variables of class c to fvs list 1.76 - * unless they are already there. 1.77 - */ 1.78 - private void addFreeVars(ClassSymbol c) { 1.79 + @Override 1.80 + void addFreeVars(ClassSymbol c) { 1.81 List<VarSymbol> fvs = freevarCache.get(c); 1.82 if (fvs != null) { 1.83 for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) { 1.84 @@ -250,15 +295,8 @@ 1.85 } 1.86 } 1.87 1.88 - /** If tree refers to a variable in owner of local class, add it to 1.89 - * free variables list. 1.90 - */ 1.91 - public void visitIdent(JCIdent tree) { 1.92 - result = tree; 1.93 - visitSymbol(tree.sym); 1.94 - } 1.95 - // where 1.96 - private void visitSymbol(Symbol _sym) { 1.97 + @Override 1.98 + void visitSymbol(Symbol _sym) { 1.99 Symbol sym = _sym; 1.100 if (sym.kind == VAR || sym.kind == MTH) { 1.101 while (sym != null && sym.owner != owner) 1.102 @@ -281,7 +319,6 @@ 1.103 */ 1.104 public void visitNewClass(JCNewClass tree) { 1.105 ClassSymbol c = (ClassSymbol)tree.constructor.owner; 1.106 - addFreeVars(c); 1.107 if (tree.encl == null && 1.108 c.hasOuterInstance() && 1.109 outerThisStack.head != null) 1.110 @@ -306,7 +343,6 @@ 1.111 */ 1.112 public void visitApply(JCMethodInvocation tree) { 1.113 if (TreeInfo.name(tree.meth) == names._super) { 1.114 - addFreeVars((ClassSymbol) TreeInfo.symbol(tree.meth).owner); 1.115 Symbol constructor = TreeInfo.symbol(tree.meth); 1.116 ClassSymbol c = (ClassSymbol)constructor.owner; 1.117 if (c.hasOuterInstance() && 1.118 @@ -1171,6 +1207,14 @@ 1.119 accessBase(tree.pos(), sym), sym).setType(tree.type); 1.120 } 1.121 } 1.122 + } else if (sym.owner.kind == MTH && lambdaTranslationMap != null) { 1.123 + //sym is a local variable - check the lambda translation map to 1.124 + //see if sym has been translated to something else in the current 1.125 + //scope (by LambdaToMethod) 1.126 + Symbol translatedSym = lambdaTranslationMap.get(sym); 1.127 + if (translatedSym != null) { 1.128 + tree = make.at(tree.pos).Ident(translatedSym); 1.129 + } 1.130 } 1.131 } 1.132 return tree; 1.133 @@ -2725,10 +2769,30 @@ 1.134 1.135 outerThisStack = prevOuterThisStack; 1.136 } else { 1.137 - super.visitMethodDef(tree); 1.138 + Map<Symbol, Symbol> prevLambdaTranslationMap = 1.139 + lambdaTranslationMap; 1.140 + try { 1.141 + lambdaTranslationMap = (tree.sym.flags() & SYNTHETIC) != 0 && 1.142 + tree.sym.name.startsWith(names.lambda) ? 1.143 + makeTranslationMap(tree) : null; 1.144 + super.visitMethodDef(tree); 1.145 + } finally { 1.146 + lambdaTranslationMap = prevLambdaTranslationMap; 1.147 + } 1.148 } 1.149 result = tree; 1.150 } 1.151 + //where 1.152 + private Map<Symbol, Symbol> makeTranslationMap(JCMethodDecl tree) { 1.153 + Map<Symbol, Symbol> translationMap = new HashMap<Symbol,Symbol>(); 1.154 + for (JCVariableDecl vd : tree.params) { 1.155 + Symbol p = vd.sym; 1.156 + if (p != p.baseSymbol()) { 1.157 + translationMap.put(p.baseSymbol(), p); 1.158 + } 1.159 + } 1.160 + return translationMap; 1.161 + } 1.162 1.163 public void visitAnnotatedType(JCAnnotatedType tree) { 1.164 // No need to retain type annotations any longer.