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

changeset 3172
921a7d6ab90d
parent 3167
d5af468ae383
child 3295
859dc787b52b
child 3556
47a91ecb0b87
equal deleted inserted replaced
3171:d203dcc5cd96 3172:921a7d6ab90d
336 if (fv != localContext.self) { 336 if (fv != localContext.self) {
337 JCTree captured_local = make.Ident(fv).setType(fv.type); 337 JCTree captured_local = make.Ident(fv).setType(fv.type);
338 syntheticInits.append((JCExpression) captured_local); 338 syntheticInits.append((JCExpression) captured_local);
339 } 339 }
340 } 340 }
341 // add captured outer this instances (used only when `this' capture itself is illegal)
342 for (Symbol fv : localContext.getSymbolMap(CAPTURED_OUTER_THIS).keySet()) {
343 JCTree captured_local = make.QualThis(fv.type);
344 syntheticInits.append((JCExpression) captured_local);
345 }
341 346
342 //then, determine the arguments to the indy call 347 //then, determine the arguments to the indy call
343 List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev); 348 List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
344 349
345 //build a sam instance using an indy call to the meta-factory 350 //build a sam instance using an indy call to the meta-factory
425 result = ltree; 430 result = ltree;
426 } else { 431 } else {
427 //access to untranslated symbols (i.e. compile-time constants, 432 //access to untranslated symbols (i.e. compile-time constants,
428 //members defined inside the lambda body, etc.) ) 433 //members defined inside the lambda body, etc.) )
429 super.visitIdent(tree); 434 super.visitIdent(tree);
435 }
436 } finally {
437 make.at(prevPos);
438 }
439 }
440 }
441
442 /**
443 * Translate qualified `this' references within a lambda to the mapped identifier
444 * @param tree
445 */
446 @Override
447 public void visitSelect(JCFieldAccess tree) {
448 if (context == null || !analyzer.lambdaFieldAccessFilter(tree)) {
449 super.visitSelect(tree);
450 } else {
451 int prevPos = make.pos;
452 try {
453 make.at(tree);
454
455 LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
456 JCTree ltree = lambdaContext.translate(tree);
457 if (ltree != null) {
458 result = ltree;
459 } else {
460 super.visitSelect(tree);
430 } 461 }
431 } finally { 462 } finally {
432 make.at(prevPos); 463 make.at(prevPos);
433 } 464 }
434 } 465 }
1124 * names) 1155 * names)
1125 */ 1156 */
1126 private int lambdaCount = 0; 1157 private int lambdaCount = 0;
1127 1158
1128 /** 1159 /**
1160 * List of types undergoing construction via explicit constructor chaining.
1161 */
1162 private List<ClassSymbol> typesUnderConstruction;
1163
1164 /**
1129 * keep the count of lambda expression defined in given context (used to 1165 * keep the count of lambda expression defined in given context (used to
1130 * generate unambiguous names for serializable lambdas) 1166 * generate unambiguous names for serializable lambdas)
1131 */ 1167 */
1132 private class SyntheticMethodNameCounter { 1168 private class SyntheticMethodNameCounter {
1133 private Map<String, Integer> map = new HashMap<>(); 1169 private Map<String, Integer> map = new HashMap<>();
1154 private Map<ClassSymbol, Symbol> clinits = 1190 private Map<ClassSymbol, Symbol> clinits =
1155 new HashMap<ClassSymbol, Symbol>(); 1191 new HashMap<ClassSymbol, Symbol>();
1156 1192
1157 private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) { 1193 private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) {
1158 frameStack = List.nil(); 1194 frameStack = List.nil();
1195 typesUnderConstruction = List.nil();
1159 localClassDefs = new HashMap<Symbol, JCClassDecl>(); 1196 localClassDefs = new HashMap<Symbol, JCClassDecl>();
1160 return translate(tree); 1197 return translate(tree);
1161 } 1198 }
1199
1200 @Override
1201 public void visitApply(JCMethodInvocation tree) {
1202 List<ClassSymbol> previousNascentTypes = typesUnderConstruction;
1203 try {
1204 Name methName = TreeInfo.name(tree.meth);
1205 if (methName == names._this || methName == names._super) {
1206 typesUnderConstruction = typesUnderConstruction.prepend(currentClass());
1207 }
1208 super.visitApply(tree);
1209 } finally {
1210 typesUnderConstruction = previousNascentTypes;
1211 }
1212 }
1213 // where
1214 private ClassSymbol currentClass() {
1215 for (Frame frame : frameStack) {
1216 if (frame.tree.hasTag(JCTree.Tag.CLASSDEF)) {
1217 JCClassDecl cdef = (JCClassDecl) frame.tree;
1218 return cdef.sym;
1219 }
1220 }
1221 return null;
1222 }
1162 1223
1163 @Override 1224 @Override
1164 public void visitBlock(JCBlock tree) { 1225 public void visitBlock(JCBlock tree) {
1165 List<Frame> prevStack = frameStack; 1226 List<Frame> prevStack = frameStack;
1166 try { 1227 try {
1622 && !sym.isStatic() 1683 && !sym.isStatic()
1623 && sym.name != names.init; 1684 && sym.name != names.init;
1624 } 1685 }
1625 1686
1626 /** 1687 /**
1688 * This is used to filter out those select nodes that need to be adjusted
1689 * when translating away lambda expressions - at the moment, this is the
1690 * set of nodes that select `this' (qualified this)
1691 */
1692 private boolean lambdaFieldAccessFilter(JCFieldAccess fAccess) {
1693 LambdaTranslationContext lambdaContext =
1694 context instanceof LambdaTranslationContext ?
1695 (LambdaTranslationContext) context : null;
1696 return lambdaContext != null
1697 && !fAccess.sym.isStatic()
1698 && fAccess.name == names._this
1699 && (fAccess.sym.owner.kind == TYP)
1700 && !lambdaContext.translatedSymbols.get(CAPTURED_OUTER_THIS).isEmpty();
1701 }
1702
1703 /**
1627 * This is used to filter out those new class expressions that need to 1704 * This is used to filter out those new class expressions that need to
1628 * be qualified with an enclosing tree 1705 * be qualified with an enclosing tree
1629 */ 1706 */
1630 private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) { 1707 private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) {
1631 if (context != null 1708 if (context != null
1795 1872
1796 translatedSymbols.put(PARAM, new LinkedHashMap<Symbol, Symbol>()); 1873 translatedSymbols.put(PARAM, new LinkedHashMap<Symbol, Symbol>());
1797 translatedSymbols.put(LOCAL_VAR, new LinkedHashMap<Symbol, Symbol>()); 1874 translatedSymbols.put(LOCAL_VAR, new LinkedHashMap<Symbol, Symbol>());
1798 translatedSymbols.put(CAPTURED_VAR, new LinkedHashMap<Symbol, Symbol>()); 1875 translatedSymbols.put(CAPTURED_VAR, new LinkedHashMap<Symbol, Symbol>());
1799 translatedSymbols.put(CAPTURED_THIS, new LinkedHashMap<Symbol, Symbol>()); 1876 translatedSymbols.put(CAPTURED_THIS, new LinkedHashMap<Symbol, Symbol>());
1877 translatedSymbols.put(CAPTURED_OUTER_THIS, new LinkedHashMap<Symbol, Symbol>());
1800 translatedSymbols.put(TYPE_VAR, new LinkedHashMap<Symbol, Symbol>()); 1878 translatedSymbols.put(TYPE_VAR, new LinkedHashMap<Symbol, Symbol>());
1801 1879
1802 freeVarProcessedLocalClasses = new HashSet<>(); 1880 freeVarProcessedLocalClasses = new HashSet<>();
1803 } 1881 }
1804 1882
1907 //keep mapping with original captured symbol 1985 //keep mapping with original captured symbol
1908 return sym; 1986 return sym;
1909 } 1987 }
1910 }; 1988 };
1911 break; 1989 break;
1990 case CAPTURED_OUTER_THIS:
1991 Name name = names.fromString(new String(sym.flatName().toString() + names.dollarThis));
1992 ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, name, types.erasure(sym.type), translatedSym) {
1993 @Override
1994 public Symbol baseSymbol() {
1995 //keep mapping with original captured symbol
1996 return sym;
1997 }
1998 };
1999 break;
1912 case LOCAL_VAR: 2000 case LOCAL_VAR:
1913 ret = new VarSymbol(sym.flags() & FINAL, sym.name, sym.type, translatedSym); 2001 ret = new VarSymbol(sym.flags() & FINAL, sym.name, sym.type, translatedSym);
1914 ((VarSymbol) ret).pos = ((VarSymbol) sym).pos; 2002 ((VarSymbol) ret).pos = ((VarSymbol) sym).pos;
1915 break; 2003 break;
1916 case PARAM: 2004 case PARAM:
1927 } 2015 }
1928 return ret; 2016 return ret;
1929 } 2017 }
1930 2018
1931 void addSymbol(Symbol sym, LambdaSymbolKind skind) { 2019 void addSymbol(Symbol sym, LambdaSymbolKind skind) {
2020 if (skind == CAPTURED_THIS && sym != null && sym.kind == TYP && !typesUnderConstruction.isEmpty()) {
2021 ClassSymbol currentClass = currentClass();
2022 if (currentClass != null && typesUnderConstruction.contains(currentClass)) {
2023 // reference must be to enclosing outer instance, mutate capture kind.
2024 Assert.check(sym != currentClass); // should have been caught right in Attr
2025 skind = CAPTURED_OUTER_THIS;
2026 }
2027 }
1932 Map<Symbol, Symbol> transMap = getSymbolMap(skind); 2028 Map<Symbol, Symbol> transMap = getSymbolMap(skind);
1933 if (!transMap.containsKey(sym)) { 2029 if (!transMap.containsKey(sym)) {
1934 transMap.put(sym, translate(sym, skind)); 2030 transMap.put(sym, translate(sym, skind));
1935 } 2031 }
1936 } 2032 }
1940 Assert.checkNonNull(m); 2036 Assert.checkNonNull(m);
1941 return m; 2037 return m;
1942 } 2038 }
1943 2039
1944 JCTree translate(JCIdent lambdaIdent) { 2040 JCTree translate(JCIdent lambdaIdent) {
1945 for (Map<Symbol, Symbol> m : translatedSymbols.values()) { 2041 for (LambdaSymbolKind kind : LambdaSymbolKind.values()) {
1946 if (m.containsKey(lambdaIdent.sym)) { 2042 Map<Symbol, Symbol> m = getSymbolMap(kind);
1947 Symbol tSym = m.get(lambdaIdent.sym); 2043 switch(kind) {
1948 JCTree t = make.Ident(tSym).setType(lambdaIdent.type); 2044 default:
1949 tSym.setTypeAttributes(lambdaIdent.sym.getRawTypeAttributes()); 2045 if (m.containsKey(lambdaIdent.sym)) {
1950 return t; 2046 Symbol tSym = m.get(lambdaIdent.sym);
2047 JCTree t = make.Ident(tSym).setType(lambdaIdent.type);
2048 tSym.setTypeAttributes(lambdaIdent.sym.getRawTypeAttributes());
2049 return t;
2050 }
2051 break;
2052 case CAPTURED_OUTER_THIS:
2053 if (lambdaIdent.sym.owner.kind == TYP && m.containsKey(lambdaIdent.sym.owner)) {
2054 // Transform outer instance variable references anchoring them to the captured synthetic.
2055 Symbol tSym = m.get(lambdaIdent.sym.owner);
2056 JCExpression t = make.Ident(tSym).setType(lambdaIdent.sym.owner.type);
2057 tSym.setTypeAttributes(lambdaIdent.sym.owner.getRawTypeAttributes());
2058 t = make.Select(t, lambdaIdent.name);
2059 t.setType(lambdaIdent.type);
2060 TreeInfo.setSymbol(t, lambdaIdent.sym);
2061 return t;
2062 }
2063 break;
1951 } 2064 }
2065 }
2066 return null;
2067 }
2068
2069 /* Translate away qualified this expressions, anchoring them to synthetic parameters that
2070 capture the qualified this handle. `fieldAccess' is guaranteed to one such.
2071 */
2072 public JCTree translate(JCFieldAccess fieldAccess) {
2073 Assert.check(fieldAccess.name == names._this);
2074 Map<Symbol, Symbol> m = translatedSymbols.get(LambdaSymbolKind.CAPTURED_OUTER_THIS);
2075 if (m.containsKey(fieldAccess.sym.owner)) {
2076 Symbol tSym = m.get(fieldAccess.sym.owner);
2077 JCExpression t = make.Ident(tSym).setType(fieldAccess.sym.owner.type);
2078 tSym.setTypeAttributes(fieldAccess.sym.owner.getRawTypeAttributes());
2079 return t;
1952 } 2080 }
1953 return null; 2081 return null;
1954 } 2082 }
1955 2083
1956 /** 2084 /**
1985 // synthetic parameters: 2113 // synthetic parameters:
1986 // 2114 //
1987 // 1) reference to enclosing contexts captured by the lambda expression 2115 // 1) reference to enclosing contexts captured by the lambda expression
1988 // 2) enclosing locals captured by the lambda expression 2116 // 2) enclosing locals captured by the lambda expression
1989 for (Symbol thisSym : getSymbolMap(CAPTURED_VAR).values()) { 2117 for (Symbol thisSym : getSymbolMap(CAPTURED_VAR).values()) {
2118 params.append(make.VarDef((VarSymbol) thisSym, null));
2119 parameterSymbols.append((VarSymbol) thisSym);
2120 }
2121 for (Symbol thisSym : getSymbolMap(CAPTURED_OUTER_THIS).values()) {
1990 params.append(make.VarDef((VarSymbol) thisSym, null)); 2122 params.append(make.VarDef((VarSymbol) thisSym, null));
1991 parameterSymbols.append((VarSymbol) thisSym); 2123 parameterSymbols.append((VarSymbol) thisSym);
1992 } 2124 }
1993 for (Symbol thisSym : getSymbolMap(PARAM).values()) { 2125 for (Symbol thisSym : getSymbolMap(PARAM).values()) {
1994 params.append(make.VarDef((VarSymbol) thisSym, null)); 2126 params.append(make.VarDef((VarSymbol) thisSym, null));
2136 enum LambdaSymbolKind { 2268 enum LambdaSymbolKind {
2137 PARAM, // original to translated lambda parameters 2269 PARAM, // original to translated lambda parameters
2138 LOCAL_VAR, // original to translated lambda locals 2270 LOCAL_VAR, // original to translated lambda locals
2139 CAPTURED_VAR, // variables in enclosing scope to translated synthetic parameters 2271 CAPTURED_VAR, // variables in enclosing scope to translated synthetic parameters
2140 CAPTURED_THIS, // class symbols to translated synthetic parameters (for captured member access) 2272 CAPTURED_THIS, // class symbols to translated synthetic parameters (for captured member access)
2273 CAPTURED_OUTER_THIS, // used when `this' capture is illegal, but outer this capture is legit (JDK-8129740)
2141 TYPE_VAR; // original to translated lambda type variables 2274 TYPE_VAR; // original to translated lambda type variables
2142 } 2275 }
2143 2276
2144 /** 2277 /**
2145 * **************************************************************** 2278 * ****************************************************************

mercurial