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

changeset 1717
8e27e84de2e9
parent 1667
a200d8ccfe47
child 1727
68142e69cafb
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Tue Apr 30 17:53:30 2013 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Wed May 01 08:46:04 2013 -0700
     1.3 @@ -40,10 +40,9 @@
     1.4  import com.sun.tools.javac.code.Symbol.VarSymbol;
     1.5  import com.sun.tools.javac.code.Symtab;
     1.6  import com.sun.tools.javac.code.Type;
     1.7 -import com.sun.tools.javac.code.Type.ClassType;
     1.8  import com.sun.tools.javac.code.Type.MethodType;
     1.9  import com.sun.tools.javac.code.Types;
    1.10 -import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzer.*;
    1.11 +import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
    1.12  import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
    1.13  import com.sun.tools.javac.jvm.*;
    1.14  import com.sun.tools.javac.util.*;
    1.15 @@ -81,7 +80,7 @@
    1.16      private Env<AttrContext> attrEnv;
    1.17  
    1.18      /** the analyzer scanner */
    1.19 -    private LambdaAnalyzer analyzer;
    1.20 +    private LambdaAnalyzerPreprocessor analyzer;
    1.21  
    1.22      /** map from lambda trees to translation contexts */
    1.23      private Map<JCTree, TranslationContext<?>> contextMap;
    1.24 @@ -156,7 +155,7 @@
    1.25          make = TreeMaker.instance(context);
    1.26          types = Types.instance(context);
    1.27          transTypes = TransTypes.instance(context);
    1.28 -        analyzer = new LambdaAnalyzer();
    1.29 +        analyzer = new LambdaAnalyzerPreprocessor();
    1.30      }
    1.31      // </editor-fold>
    1.32  
    1.33 @@ -206,7 +205,7 @@
    1.34      public void visitClassDef(JCClassDecl tree) {
    1.35          if (tree.sym.owner.kind == PCK) {
    1.36              //analyze class
    1.37 -            analyzer.analyzeClass(tree);
    1.38 +            tree = analyzer.analyzeAndPreprocessClass(tree);
    1.39          }
    1.40          KlassInfo prevKlassInfo = kInfo;
    1.41          try {
    1.42 @@ -531,16 +530,25 @@
    1.43      /** Make an attributed class instance creation expression.
    1.44       *  @param ctype    The class type.
    1.45       *  @param args     The constructor arguments.
    1.46 +     *  @param cons     The constructor symbol
    1.47       */
    1.48 -    JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
    1.49 +    JCNewClass makeNewClass(Type ctype, List<JCExpression> args, Symbol cons) {
    1.50          JCNewClass tree = make.NewClass(null,
    1.51              null, make.QualIdent(ctype.tsym), args, null);
    1.52 -        tree.constructor = rs.resolveConstructor(
    1.53 -            null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil());
    1.54 +        tree.constructor = cons;
    1.55          tree.type = ctype;
    1.56          return tree;
    1.57      }
    1.58  
    1.59 +    /** Make an attributed class instance creation expression.
    1.60 +     *  @param ctype    The class type.
    1.61 +     *  @param args     The constructor arguments.
    1.62 +     */
    1.63 +    JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
    1.64 +        return makeNewClass(ctype, args,
    1.65 +                rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil()));
    1.66 +     }
    1.67 +
    1.68      private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
    1.69              DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
    1.70          String functionalInterfaceClass = classSig(targetType);
    1.71 @@ -1019,8 +1027,9 @@
    1.72       * This visitor collects information about translation of a lambda expression.
    1.73       * More specifically, it keeps track of the enclosing contexts and captured locals
    1.74       * accessed by the lambda being translated (as well as other useful info).
    1.75 +     * It also translates away problems for LambdaToMethod.
    1.76       */
    1.77 -    class LambdaAnalyzer extends TreeScanner {
    1.78 +    class LambdaAnalyzerPreprocessor extends TreeTranslator {
    1.79  
    1.80          /** the frame stack - used to reconstruct translation info about enclosing scopes */
    1.81          private List<Frame> frameStack;
    1.82 @@ -1047,10 +1056,10 @@
    1.83          private Map<ClassSymbol, Symbol> clinits =
    1.84                  new HashMap<ClassSymbol, Symbol>();
    1.85  
    1.86 -        private void analyzeClass(JCClassDecl tree) {
    1.87 +        private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) {
    1.88              frameStack = List.nil();
    1.89              localClassDefs = new HashMap<Symbol, JCClassDecl>();
    1.90 -            scan(tree);
    1.91 +            return translate(tree);
    1.92          }
    1.93  
    1.94          @Override
    1.95 @@ -1154,7 +1163,7 @@
    1.96                      frameStack.head.addLocal(param.sym);
    1.97                  }
    1.98                  contextMap.put(tree, context);
    1.99 -                scan(tree.body);
   1.100 +                super.visitLambda(tree);
   1.101                  context.complete();
   1.102              }
   1.103              finally {
   1.104 @@ -1220,12 +1229,47 @@
   1.105                      };
   1.106                      fvc.scan(localCDef);
   1.107                  }
   1.108 -            }
   1.109 +        }
   1.110  
   1.111 +        /**
   1.112 +         * Method references to local class constructors, may, if the local
   1.113 +         * class references local variables, have implicit constructor
   1.114 +         * parameters added in Lower; As a result, the invokedynamic bootstrap
   1.115 +         * information added in the LambdaToMethod pass will have the wrong
   1.116 +         * signature. Hooks between Lower and LambdaToMethod have been added to
   1.117 +         * handle normal "new" in this case. This visitor converts potentially
   1.118 +         * effected method references into a lambda containing a normal "new" of
   1.119 +         * the class.
   1.120 +         *
   1.121 +         * @param tree
   1.122 +         */
   1.123          @Override
   1.124          public void visitReference(JCMemberReference tree) {
   1.125 -            scan(tree.getQualifierExpression());
   1.126 -            contextMap.put(tree, makeReferenceContext(tree));
   1.127 +            if (tree.getMode() == ReferenceMode.NEW
   1.128 +                    && tree.kind != ReferenceKind.ARRAY_CTOR
   1.129 +                    && tree.sym.owner.isLocal()) {
   1.130 +                MethodSymbol consSym = (MethodSymbol) tree.sym;
   1.131 +                List<Type> ptypes = ((MethodType) consSym.type).getParameterTypes();
   1.132 +                Type classType = consSym.owner.type;
   1.133 +
   1.134 +                // Make new-class call
   1.135 +                List<JCVariableDecl> params = make.Params(ptypes, owner());
   1.136 +                JCNewClass nc = makeNewClass(classType, make.Idents(params));
   1.137 +                nc.pos = tree.pos;
   1.138 +
   1.139 +                // Make lambda holding the new-class call
   1.140 +                JCLambda slam = make.Lambda(params, nc);
   1.141 +                slam.descriptorType = tree.descriptorType;
   1.142 +                slam.targets = tree.targets;
   1.143 +                slam.type = tree.type;
   1.144 +                slam.pos = tree.pos;
   1.145 +
   1.146 +                // Now it is a lambda, process as such
   1.147 +                visitLambda(slam);
   1.148 +            } else {
   1.149 +                super.visitReference(tree);
   1.150 +                contextMap.put(tree, makeReferenceContext(tree));
   1.151 +            }
   1.152          }
   1.153  
   1.154          @Override
   1.155 @@ -1240,10 +1284,8 @@
   1.156                      }
   1.157                      localContext = localContext.prev;
   1.158                  }
   1.159 -                scan(tree.selected);
   1.160 -            } else {
   1.161 -                super.visitSelect(tree);
   1.162              }
   1.163 +            super.visitSelect(tree);
   1.164          }
   1.165  
   1.166          @Override

mercurial