src/share/classes/com/sun/tools/javac/comp/Lower.java

changeset 1612
69cd2bfd4a31
parent 1565
d04960f05593
child 1621
823fb9229724
     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.

mercurial