langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
changeset 16325 088a91896245
parent 16310 af1565438e63
child 16327 01a0c0cb811c
equal deleted inserted replaced
16324:332d7f5fdf62 16325:088a91896245
    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;
    68  *  This code and its internal interfaces are subject to change or
    69  *  This code and its internal interfaces are subject to change or
    69  *  deletion without notice.</b>
    70  *  deletion without notice.</b>
    70  */
    71  */
    71 public class LambdaToMethod extends TreeTranslator {
    72 public class LambdaToMethod extends TreeTranslator {
    72 
    73 
       
    74     private Lower lower;
    73     private Names names;
    75     private Names names;
    74     private Symtab syms;
    76     private Symtab syms;
    75     private Resolve rs;
    77     private Resolve rs;
    76     private TreeMaker make;
    78     private TreeMaker make;
    77     private Types types;
    79     private Types types;
   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