Mon, 29 Oct 2012 10:39:49 -0700
8000694: Add generation of lambda implementation code: invokedynamic call, lambda method, adaptor methods
Summary: Add lambda implementation code with calling/supporting code elsewhere in the compiler
Reviewed-by: mcimadamore, jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Symtab.java Fri Oct 26 18:40:13 2012 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java Mon Oct 29 10:39:49 2012 -0700 1.3 @@ -127,6 +127,7 @@ 1.4 public final Type cloneableType; 1.5 public final Type serializableType; 1.6 public final Type methodHandleType; 1.7 + public final Type methodHandleLookupType; 1.8 public final Type methodTypeType; 1.9 public final Type nativeHeaderType; 1.10 public final Type throwableType; 1.11 @@ -158,6 +159,7 @@ 1.12 public final Type systemType; 1.13 public final Type autoCloseableType; 1.14 public final Type trustMeType; 1.15 + public final Type lambdaMetafactory; 1.16 public final Type containedByType; 1.17 public final Type containerForType; 1.18 public final Type documentedType; 1.19 @@ -456,6 +458,7 @@ 1.20 throwableType = enterClass("java.lang.Throwable"); 1.21 serializableType = enterClass("java.io.Serializable"); 1.22 methodHandleType = enterClass("java.lang.invoke.MethodHandle"); 1.23 + methodHandleLookupType = enterClass("java.lang.invoke.MethodHandles$Lookup"); 1.24 methodTypeType = enterClass("java.lang.invoke.MethodType"); 1.25 errorType = enterClass("java.lang.Error"); 1.26 illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException"); 1.27 @@ -503,10 +506,12 @@ 1.28 autoCloseableType.tsym); 1.29 trustMeType = enterClass("java.lang.SafeVarargs"); 1.30 nativeHeaderType = enterClass("javax.tools.annotation.GenerateNativeHeader"); 1.31 + lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory"); 1.32 1.33 synthesizeEmptyInterfaceIfMissing(autoCloseableType); 1.34 synthesizeEmptyInterfaceIfMissing(cloneableType); 1.35 synthesizeEmptyInterfaceIfMissing(serializableType); 1.36 + synthesizeEmptyInterfaceIfMissing(lambdaMetafactory); 1.37 synthesizeBoxTypeIfMissing(doubleType); 1.38 synthesizeBoxTypeIfMissing(floatType); 1.39 synthesizeBoxTypeIfMissing(voidType);
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Mon Oct 29 10:39:49 2012 -0700 2.3 @@ -0,0 +1,1398 @@ 2.4 +/* 2.5 + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. Oracle designates this 2.11 + * particular file as subject to the "Classpath" exception as provided 2.12 + * by Oracle in the LICENSE file that accompanied this code. 2.13 + * 2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.17 + * version 2 for more details (a copy is included in the LICENSE file that 2.18 + * accompanied this code). 2.19 + * 2.20 + * You should have received a copy of the GNU General Public License version 2.21 + * 2 along with this work; if not, write to the Free Software Foundation, 2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.23 + * 2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.25 + * or visit www.oracle.com if you need additional information or have any 2.26 + * questions. 2.27 + */ 2.28 +package com.sun.tools.javac.comp; 2.29 + 2.30 +import com.sun.tools.javac.tree.*; 2.31 +import com.sun.tools.javac.tree.JCTree; 2.32 +import com.sun.tools.javac.tree.JCTree.*; 2.33 +import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; 2.34 +import com.sun.tools.javac.tree.TreeMaker; 2.35 +import com.sun.tools.javac.tree.TreeScanner; 2.36 +import com.sun.tools.javac.tree.TreeTranslator; 2.37 +import com.sun.tools.javac.code.Flags; 2.38 +import com.sun.tools.javac.code.Kinds; 2.39 +import com.sun.tools.javac.code.Symbol; 2.40 +import com.sun.tools.javac.code.Symbol.ClassSymbol; 2.41 +import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol; 2.42 +import com.sun.tools.javac.code.Symbol.MethodSymbol; 2.43 +import com.sun.tools.javac.code.Symbol.VarSymbol; 2.44 +import com.sun.tools.javac.code.Symtab; 2.45 +import com.sun.tools.javac.code.Type; 2.46 +import com.sun.tools.javac.code.Type.ClassType; 2.47 +import com.sun.tools.javac.code.Type.MethodType; 2.48 +import com.sun.tools.javac.code.Types; 2.49 +import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzer.*; 2.50 +import com.sun.tools.javac.jvm.*; 2.51 +import com.sun.tools.javac.util.*; 2.52 +import com.sun.tools.javac.util.List; 2.53 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 2.54 +import com.sun.source.tree.MemberReferenceTree.ReferenceMode; 2.55 + 2.56 +import java.util.HashMap; 2.57 +import java.util.LinkedHashMap; 2.58 +import java.util.Map; 2.59 + 2.60 +import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*; 2.61 +import static com.sun.tools.javac.code.Flags.*; 2.62 +import static com.sun.tools.javac.code.Kinds.*; 2.63 +import static com.sun.tools.javac.code.TypeTag.BOT; 2.64 +import static com.sun.tools.javac.code.TypeTag.NONE; 2.65 +import static com.sun.tools.javac.code.TypeTag.VOID; 2.66 +import static com.sun.tools.javac.tree.JCTree.Tag.*; 2.67 + 2.68 +/** 2.69 + * This pass desugars lambda expressions into static methods 2.70 + * 2.71 + * <p><b>This is NOT part of any supported API. 2.72 + * If you write code that depends on this, you do so at your own risk. 2.73 + * This code and its internal interfaces are subject to change or 2.74 + * deletion without notice.</b> 2.75 + */ 2.76 +public class LambdaToMethod extends TreeTranslator { 2.77 + 2.78 + private Names names; 2.79 + private Symtab syms; 2.80 + private Resolve rs; 2.81 + private TreeMaker make; 2.82 + private Types types; 2.83 + private TransTypes transTypes; 2.84 + private Env<AttrContext> attrEnv; 2.85 + 2.86 + /** the analyzer scanner */ 2.87 + private LambdaAnalyzer analyzer; 2.88 + 2.89 + /** map from lambda trees to translation contexts */ 2.90 + private Map<JCTree, TranslationContext<?>> contextMap; 2.91 + 2.92 + /** current translation context (visitor argument) */ 2.93 + private TranslationContext<?> context; 2.94 + 2.95 + /** list of translated methods 2.96 + **/ 2.97 + private ListBuffer<JCTree> translatedMethodList; 2.98 + 2.99 + // <editor-fold defaultstate="collapsed" desc="Instantiating"> 2.100 + private static final Context.Key<LambdaToMethod> unlambdaKey = 2.101 + new Context.Key<LambdaToMethod>(); 2.102 + 2.103 + public static LambdaToMethod instance(Context context) { 2.104 + LambdaToMethod instance = context.get(unlambdaKey); 2.105 + if (instance == null) { 2.106 + instance = new LambdaToMethod(context); 2.107 + } 2.108 + return instance; 2.109 + } 2.110 + 2.111 + private LambdaToMethod(Context context) { 2.112 + names = Names.instance(context); 2.113 + syms = Symtab.instance(context); 2.114 + rs = Resolve.instance(context); 2.115 + make = TreeMaker.instance(context); 2.116 + types = Types.instance(context); 2.117 + transTypes = TransTypes.instance(context); 2.118 + this.analyzer = makeAnalyzer(); 2.119 + } 2.120 + 2.121 + private LambdaAnalyzer makeAnalyzer() { 2.122 + return new LambdaAnalyzer(); 2.123 + } 2.124 + // </editor-fold> 2.125 + 2.126 + // <editor-fold defaultstate="collapsed" desc="translate methods"> 2.127 + @Override 2.128 + public <T extends JCTree> T translate(T tree) { 2.129 + TranslationContext<?> newContext = contextMap.get(tree); 2.130 + return translate(tree, newContext != null ? newContext : context); 2.131 + } 2.132 + 2.133 + public <T extends JCTree> T translate(T tree, TranslationContext<?> newContext) { 2.134 + TranslationContext<?> prevContext = context; 2.135 + try { 2.136 + context = newContext; 2.137 + return super.translate(tree); 2.138 + } 2.139 + finally { 2.140 + context = prevContext; 2.141 + } 2.142 + } 2.143 + 2.144 + public <T extends JCTree> List<T> translate(List<T> trees, TranslationContext<?> newContext) { 2.145 + ListBuffer<T> buf = ListBuffer.lb(); 2.146 + for (T tree : trees) { 2.147 + buf.append(translate(tree, newContext)); 2.148 + } 2.149 + return buf.toList(); 2.150 + } 2.151 + 2.152 + public JCTree translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) { 2.153 + this.make = make; 2.154 + this.attrEnv = env; 2.155 + this.context = null; 2.156 + this.contextMap = new HashMap<JCTree, TranslationContext<?>>(); 2.157 + return translate(cdef); 2.158 + } 2.159 + // </editor-fold> 2.160 + 2.161 + // <editor-fold defaultstate="collapsed" desc="visitor methods"> 2.162 + /** 2.163 + * Visit a class. 2.164 + * Maintain the translatedMethodList across nested classes. 2.165 + * Append the translatedMethodList to the class after it is translated. 2.166 + * @param tree 2.167 + */ 2.168 + @Override 2.169 + public void visitClassDef(JCClassDecl tree) { 2.170 + if (tree.sym.owner.kind == PCK) { 2.171 + //analyze class 2.172 + analyzer.analyzeClass(tree); 2.173 + } 2.174 + ListBuffer<JCTree> prevTranslated = translatedMethodList; 2.175 + try { 2.176 + translatedMethodList = ListBuffer.lb(); 2.177 + super.visitClassDef(tree); 2.178 + //add all translated instance methods here 2.179 + tree.defs = tree.defs.appendList(translatedMethodList.toList()); 2.180 + for (JCTree lambda : translatedMethodList) { 2.181 + tree.sym.members().enter(((JCMethodDecl)lambda).sym); 2.182 + } 2.183 + result = tree; 2.184 + } finally { 2.185 + translatedMethodList = prevTranslated; 2.186 + } 2.187 + } 2.188 + 2.189 + /** 2.190 + * Translate a lambda into a method to be inserted into the class. 2.191 + * Then replace the lambda site with an invokedynamic call of to lambda 2.192 + * meta-factory, which will use the lambda method. 2.193 + * @param tree 2.194 + */ 2.195 + @Override 2.196 + public void visitLambda(JCLambda tree) { 2.197 + LambdaTranslationContext localContext = (LambdaTranslationContext)context; 2.198 + MethodSymbol sym = (MethodSymbol)localContext.translatedSym; 2.199 + MethodType lambdaType = (MethodType) sym.type; 2.200 + 2.201 + //create the method declaration hoisting the lambda body 2.202 + JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field), 2.203 + sym.name, 2.204 + make.QualIdent(lambdaType.getReturnType().tsym), 2.205 + List.<JCTypeParameter>nil(), 2.206 + localContext.syntheticParams, 2.207 + lambdaType.getThrownTypes() == null ? 2.208 + List.<JCExpression>nil() : 2.209 + make.Types(lambdaType.getThrownTypes()), 2.210 + null, 2.211 + null); 2.212 + lambdaDecl.sym = sym; 2.213 + lambdaDecl.type = lambdaType; 2.214 + 2.215 + //translate lambda body 2.216 + //As the lambda body is translated, all references to lambda locals, 2.217 + //captured variables, enclosing members are adjusted accordingly 2.218 + //to refer to the static method parameters (rather than i.e. acessing to 2.219 + //captured members directly). 2.220 + lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl)); 2.221 + 2.222 + //Add the method to the list of methods to be added to this class. 2.223 + translatedMethodList = translatedMethodList.prepend(lambdaDecl); 2.224 + 2.225 + //now that we have generated a method for the lambda expression, 2.226 + //we can translate the lambda into a method reference pointing to the newly 2.227 + //created method. 2.228 + // 2.229 + //Note that we need to adjust the method handle so that it will match the 2.230 + //signature of the SAM descriptor - this means that the method reference 2.231 + //should be added the following synthetic arguments: 2.232 + // 2.233 + // * the "this" argument if it is an instance method 2.234 + // * enclosing locals captured by the lambda expression 2.235 + 2.236 + ListBuffer<JCExpression> syntheticInits = ListBuffer.lb(); 2.237 + 2.238 + if (!sym.isStatic()) { 2.239 + syntheticInits.append(makeThis( 2.240 + sym.owner.asType(), 2.241 + localContext.owner.enclClass())); 2.242 + } 2.243 + 2.244 + //add captured locals 2.245 + for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) { 2.246 + if (fv != localContext.self) { 2.247 + JCTree captured_local = make.Ident(fv).setType(fv.type); 2.248 + syntheticInits.append((JCExpression) captured_local); 2.249 + } 2.250 + } 2.251 + 2.252 + //then, determine the arguments to the indy call 2.253 + List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev); 2.254 + 2.255 + //build a sam instance using an indy call to the meta-factory 2.256 + int refKind = referenceKind(sym); 2.257 + 2.258 + //convert to an invokedynamic call 2.259 + result = makeMetaFactoryIndyCall(tree, tree.targetType, refKind, sym, indy_args); 2.260 + } 2.261 + 2.262 + private JCIdent makeThis(Type type, Symbol owner) { 2.263 + VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC, 2.264 + names._this, 2.265 + type, 2.266 + owner); 2.267 + return make.Ident(_this); 2.268 + } 2.269 + 2.270 + /** 2.271 + * Translate a method reference into an invokedynamic call to the 2.272 + * meta-factory. 2.273 + * @param tree 2.274 + */ 2.275 + @Override 2.276 + public void visitReference(JCMemberReference tree) { 2.277 + ReferenceTranslationContext localContext = (ReferenceTranslationContext)context; 2.278 + 2.279 + //first determine the method symbol to be used to generate the sam instance 2.280 + //this is either the method reference symbol, or the bridged reference symbol 2.281 + Symbol refSym = localContext.needsBridge() ? 2.282 + localContext.bridgeSym : 2.283 + tree.sym; 2.284 + 2.285 + //build the bridge method, if needed 2.286 + if (localContext.needsBridge()) { 2.287 + bridgeMemberReference(tree, localContext); 2.288 + } 2.289 + 2.290 + //the qualifying expression is treated as a special captured arg 2.291 + JCExpression init; 2.292 + switch(tree.kind) { 2.293 + 2.294 + case IMPLICIT_INNER: /** Inner # new */ 2.295 + case SUPER: /** super # instMethod */ 2.296 + init = makeThis( 2.297 + localContext.owner.owner.asType(), 2.298 + localContext.owner); 2.299 + break; 2.300 + 2.301 + case BOUND: /** Expr # instMethod */ 2.302 + init = tree.getQualifierExpression(); 2.303 + break; 2.304 + 2.305 + case STATIC_EVAL: /** Expr # staticMethod */ 2.306 + case UNBOUND: /** Type # instMethod */ 2.307 + case STATIC: /** Type # staticMethod */ 2.308 + case TOPLEVEL: /** Top level # new */ 2.309 + init = null; 2.310 + break; 2.311 + 2.312 + default: 2.313 + throw new InternalError("Should not have an invalid kind"); 2.314 + } 2.315 + 2.316 + List<JCExpression> indy_args = init==null? List.<JCExpression>nil() : translate(List.of(init), localContext.prev); 2.317 + 2.318 + 2.319 + //build a sam instance using an indy call to the meta-factory 2.320 + result = makeMetaFactoryIndyCall(tree, tree.targetType, localContext.referenceKind(), refSym, indy_args); 2.321 + 2.322 + //if we had a static reference with non-static qualifier, add a let 2.323 + //expression to force the evaluation of the qualifier expr 2.324 + if (tree.hasKind(ReferenceKind.STATIC_EVAL)) { 2.325 + VarSymbol rec = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner); 2.326 + JCVariableDecl recDef = make.VarDef(rec, tree.getQualifierExpression()); 2.327 + result = make.LetExpr(recDef, result).setType(tree.type); 2.328 + } 2.329 + } 2.330 + 2.331 + /** 2.332 + * Translate identifiers within a lambda to the mapped identifier 2.333 + * @param tree 2.334 + */ 2.335 + @Override 2.336 + public void visitIdent(JCIdent tree) { 2.337 + if (context == null || !analyzer.lambdaIdentSymbolFilter(tree.sym)) { 2.338 + super.visitIdent(tree); 2.339 + } else { 2.340 + LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context; 2.341 + if (lambdaContext.getSymbolMap(PARAM).containsKey(tree.sym)) { 2.342 + Symbol translatedSym = lambdaContext.getSymbolMap(PARAM).get(tree.sym); 2.343 + result = make.Ident(translatedSym).setType(tree.type); 2.344 + } else if (lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) { 2.345 + Symbol translatedSym = lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym); 2.346 + result = make.Ident(translatedSym).setType(tree.type); 2.347 + } else if (lambdaContext.getSymbolMap(CAPTURED_VAR).containsKey(tree.sym)) { 2.348 + Symbol translatedSym = lambdaContext.getSymbolMap(CAPTURED_VAR).get(tree.sym); 2.349 + result = make.Ident(translatedSym).setType(tree.type); 2.350 + } else { 2.351 + if (tree.sym.owner.kind == Kinds.TYP) { 2.352 + for (Map.Entry<Symbol, Symbol> encl_entry : lambdaContext.getSymbolMap(CAPTURED_THIS).entrySet()) { 2.353 + if (tree.sym.isMemberOf((ClassSymbol) encl_entry.getKey(), types)) { 2.354 + JCExpression enclRef = make.Ident(encl_entry.getValue()); 2.355 + result = tree.sym.name == names._this 2.356 + ? enclRef.setType(tree.type) 2.357 + : make.Select(enclRef, tree.sym).setType(tree.type); 2.358 + result = tree; 2.359 + return; 2.360 + } 2.361 + } 2.362 + } 2.363 + //access to untranslated symbols (i.e. compile-time constants, 2.364 + //members defined inside the lambda body, etc.) ) 2.365 + super.visitIdent(tree); 2.366 + } 2.367 + } 2.368 + } 2.369 + 2.370 + @Override 2.371 + public void visitVarDef(JCVariableDecl tree) { 2.372 + LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context; 2.373 + if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) { 2.374 + JCExpression init = translate(tree.init); 2.375 + result = make.VarDef((VarSymbol)lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym), init); 2.376 + } else { 2.377 + super.visitVarDef(tree); 2.378 + } 2.379 + } 2.380 + 2.381 + // </editor-fold> 2.382 + 2.383 + // <editor-fold defaultstate="collapsed" desc="Translation helper methods"> 2.384 + 2.385 + private JCBlock makeLambdaBody(JCLambda tree, JCMethodDecl lambdaMethodDecl) { 2.386 + return tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION ? 2.387 + makeLambdaExpressionBody((JCExpression)tree.body, lambdaMethodDecl) : 2.388 + makeLambdaStatementBody((JCBlock)tree.body, lambdaMethodDecl, tree.canCompleteNormally); 2.389 + } 2.390 + 2.391 + private JCBlock makeLambdaExpressionBody(JCExpression expr, JCMethodDecl lambdaMethodDecl) { 2.392 + Type restype = lambdaMethodDecl.type.getReturnType(); 2.393 + boolean isLambda_void = expr.type.hasTag(VOID); 2.394 + boolean isTarget_void = restype.hasTag(VOID); 2.395 + boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type); 2.396 + if (isTarget_void) { 2.397 + //target is void: 2.398 + // BODY; 2.399 + JCStatement stat = make.Exec(expr); 2.400 + return make.Block(0, List.<JCStatement>of(stat)); 2.401 + } else if (isLambda_void && isTarget_Void) { 2.402 + //void to Void conversion: 2.403 + // BODY; return null; 2.404 + ListBuffer<JCStatement> stats = ListBuffer.lb(); 2.405 + stats.append(make.Exec(expr)); 2.406 + stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType))); 2.407 + return make.Block(0, stats.toList()); 2.408 + } else { 2.409 + //non-void to non-void conversion: 2.410 + // return (TYPE)BODY; 2.411 + JCExpression retExpr = transTypes.coerce(attrEnv, expr, restype); 2.412 + return make.Block(0, List.<JCStatement>of(make.Return(retExpr))); 2.413 + } 2.414 + } 2.415 + 2.416 + private JCBlock makeLambdaStatementBody(JCBlock block, final JCMethodDecl lambdaMethodDecl, boolean completeNormally) { 2.417 + final Type restype = lambdaMethodDecl.type.getReturnType(); 2.418 + final boolean isTarget_void = restype.hasTag(VOID); 2.419 + boolean isTarget_Void = types.isSameType(restype, types.boxedClass(syms.voidType).type); 2.420 + 2.421 + class LambdaBodyTranslator extends TreeTranslator { 2.422 + 2.423 + @Override 2.424 + public void visitClassDef(JCClassDecl tree) { 2.425 + //do NOT recurse on any inner classes 2.426 + result = tree; 2.427 + } 2.428 + 2.429 + @Override 2.430 + public void visitLambda(JCLambda tree) { 2.431 + //do NOT recurse on any nested lambdas 2.432 + result = tree; 2.433 + } 2.434 + 2.435 + @Override 2.436 + public void visitReturn(JCReturn tree) { 2.437 + boolean isLambda_void = tree.expr == null; 2.438 + if (isTarget_void && !isLambda_void) { 2.439 + //Void to void conversion: 2.440 + // { TYPE $loc = RET-EXPR; return; } 2.441 + VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym); 2.442 + JCVariableDecl varDef = make.VarDef(loc, tree.expr); 2.443 + result = make.Block(0, List.<JCStatement>of(varDef, make.Return(null))); 2.444 + } else if (!isTarget_void || !isLambda_void) { 2.445 + //non-void to non-void conversion: 2.446 + // return (TYPE)RET-EXPR; 2.447 + tree.expr = transTypes.coerce(attrEnv, tree.expr, restype); 2.448 + result = tree; 2.449 + } else { 2.450 + result = tree; 2.451 + } 2.452 + 2.453 + } 2.454 + } 2.455 + 2.456 + JCBlock trans_block = new LambdaBodyTranslator().translate(block); 2.457 + if (completeNormally && isTarget_Void) { 2.458 + //there's no return statement and the lambda (possibly inferred) 2.459 + //return type is java.lang.Void; emit a synthetic return statement 2.460 + trans_block.stats = trans_block.stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType))); 2.461 + } 2.462 + return trans_block; 2.463 + } 2.464 + 2.465 + /** 2.466 + * Create new synthetic method with given flags, name, type, owner 2.467 + */ 2.468 + private MethodSymbol makeSyntheticMethod(long flags, Name name, Type type, Symbol owner) { 2.469 + return new MethodSymbol(flags | SYNTHETIC, name, type, owner); 2.470 + } 2.471 + 2.472 + /** 2.473 + * Create new synthetic variable with given flags, name, type, owner 2.474 + */ 2.475 + private VarSymbol makeSyntheticVar(long flags, String name, Type type, Symbol owner) { 2.476 + return makeSyntheticVar(flags, names.fromString(name), type, owner); 2.477 + } 2.478 + 2.479 + /** 2.480 + * Create new synthetic variable with given flags, name, type, owner 2.481 + */ 2.482 + private VarSymbol makeSyntheticVar(long flags, Name name, Type type, Symbol owner) { 2.483 + return new VarSymbol(flags | SYNTHETIC, name, type, owner); 2.484 + } 2.485 + 2.486 + /** 2.487 + * Set varargsElement field on a given tree (must be either a new class tree 2.488 + * or a method call tree) 2.489 + */ 2.490 + private void setVarargsIfNeeded(JCTree tree, Type varargsElement) { 2.491 + if (varargsElement != null) { 2.492 + switch (tree.getTag()) { 2.493 + case APPLY: ((JCMethodInvocation)tree).varargsElement = varargsElement; break; 2.494 + case NEWCLASS: ((JCNewClass)tree).varargsElement = varargsElement; break; 2.495 + default: throw new AssertionError(); 2.496 + } 2.497 + } 2.498 + } 2.499 + 2.500 + /** 2.501 + * Convert method/constructor arguments by inserting appropriate cast 2.502 + * as required by type-erasure - this is needed when bridging a lambda/method 2.503 + * reference, as the bridged signature might require downcast to be compatible 2.504 + * with the generated signature. 2.505 + */ 2.506 + private List<JCExpression> convertArgs(Symbol meth, List<JCExpression> args, Type varargsElement) { 2.507 + Assert.check(meth.kind == Kinds.MTH); 2.508 + List<Type> formals = types.erasure(meth.type).getParameterTypes(); 2.509 + if (varargsElement != null) { 2.510 + Assert.check((meth.flags() & VARARGS) != 0); 2.511 + } 2.512 + return transTypes.translateArgs(args, formals, varargsElement, attrEnv); 2.513 + } 2.514 + 2.515 + // </editor-fold> 2.516 + 2.517 + private MethodSymbol makeSamDescriptor(Type targetType) { 2.518 + return (MethodSymbol)types.findDescriptorSymbol(targetType.tsym); 2.519 + } 2.520 + 2.521 + private Type makeFunctionalDescriptorType(Type targetType, MethodSymbol samDescriptor, boolean erased) { 2.522 + Type descType = types.memberType(targetType, samDescriptor); 2.523 + return erased ? types.erasure(descType) : descType; 2.524 + } 2.525 + 2.526 + private Type makeFunctionalDescriptorType(Type targetType, boolean erased) { 2.527 + return makeFunctionalDescriptorType(targetType, makeSamDescriptor(targetType), erased); 2.528 + } 2.529 + 2.530 + /** 2.531 + * Generate an adapter method "bridge" for a method reference which cannot 2.532 + * be used directly. 2.533 + */ 2.534 + private class MemberReferenceBridger { 2.535 + 2.536 + private final JCMemberReference tree; 2.537 + private final ReferenceTranslationContext localContext; 2.538 + private final ListBuffer<JCExpression> args = ListBuffer.lb(); 2.539 + private final ListBuffer<JCVariableDecl> params = ListBuffer.lb(); 2.540 + 2.541 + MemberReferenceBridger(JCMemberReference tree, ReferenceTranslationContext localContext) { 2.542 + this.tree = tree; 2.543 + this.localContext = localContext; 2.544 + } 2.545 + 2.546 + /** 2.547 + * Generate the bridge 2.548 + */ 2.549 + JCMethodDecl bridge() { 2.550 + int prevPos = make.pos; 2.551 + try { 2.552 + make.at(tree); 2.553 + Type samDesc = localContext.bridgedRefSig(); 2.554 + List<Type> samPTypes = samDesc.getParameterTypes(); 2.555 + 2.556 + //an extra argument is prepended to the signature of the bridge in case 2.557 + //the member reference is an instance method reference (in which case 2.558 + //the receiver expression is passed to the bridge itself). 2.559 + Type recType = null; 2.560 + switch (tree.kind) { 2.561 + case IMPLICIT_INNER: 2.562 + recType = tree.sym.owner.type.getEnclosingType(); 2.563 + break; 2.564 + case BOUND: 2.565 + recType = tree.getQualifierExpression().type; 2.566 + break; 2.567 + case UNBOUND: 2.568 + recType = samPTypes.head; 2.569 + samPTypes = samPTypes.tail; 2.570 + break; 2.571 + } 2.572 + 2.573 + //generate the parameter list for the bridged member reference - the 2.574 + //bridge signature will match the signature of the target sam descriptor 2.575 + 2.576 + VarSymbol rcvr = (recType == null) 2.577 + ? null 2.578 + : addParameter("rec$", recType, false); 2.579 + 2.580 + List<Type> refPTypes = tree.sym.type.getParameterTypes(); 2.581 + int refSize = refPTypes.size(); 2.582 + int samSize = samPTypes.size(); 2.583 + int last = localContext.needsVarArgsConversion() ? refSize - 1 : refSize; // Last parameter to copy from referenced method 2.584 + 2.585 + List<Type> l = refPTypes; 2.586 + // Use parameter types of the referenced method, excluding final var args 2.587 + for (int i = 0; l.nonEmpty() && i < last; ++i) { 2.588 + addParameter("x$" + i, l.head, true); 2.589 + l = l.tail; 2.590 + } 2.591 + // Flatten out the var args 2.592 + for (int i = last; i < samSize; ++i) { 2.593 + addParameter("xva$" + i, tree.varargsElement, true); 2.594 + } 2.595 + 2.596 + //generate the bridge method declaration 2.597 + JCMethodDecl bridgeDecl = make.MethodDef(make.Modifiers(localContext.bridgeSym.flags()), 2.598 + localContext.bridgeSym.name, 2.599 + make.QualIdent(samDesc.getReturnType().tsym), 2.600 + List.<JCTypeParameter>nil(), 2.601 + params.toList(), 2.602 + tree.sym.type.getThrownTypes() == null 2.603 + ? List.<JCExpression>nil() 2.604 + : make.Types(tree.sym.type.getThrownTypes()), 2.605 + null, 2.606 + null); 2.607 + bridgeDecl.sym = (MethodSymbol) localContext.bridgeSym; 2.608 + bridgeDecl.type = localContext.bridgeSym.type = types.createMethodTypeWithParameters(samDesc, TreeInfo.types(params.toList())); 2.609 + 2.610 + //bridge method body generation - this can be either a method call or a 2.611 + //new instance creation expression, depending on the member reference kind 2.612 + JCExpression bridgeExpr = (tree.getMode() == ReferenceMode.INVOKE) 2.613 + ? bridgeExpressionInvoke(rcvr) 2.614 + : bridgeExpressionNew(); 2.615 + 2.616 + //the body is either a return expression containing a method call, 2.617 + //or the method call itself, depending on whether the return type of 2.618 + //the bridge is non-void/void. 2.619 + bridgeDecl.body = makeLambdaExpressionBody(bridgeExpr, bridgeDecl); 2.620 + 2.621 + return bridgeDecl; 2.622 + } finally { 2.623 + make.at(prevPos); 2.624 + } 2.625 + } 2.626 + 2.627 + /** 2.628 + * determine the receiver of the bridged method call - the receiver can 2.629 + * be either the synthetic receiver parameter or a type qualifier; the 2.630 + * original qualifier expression is never used here, as it might refer 2.631 + * to symbols not available in the static context of the bridge 2.632 + */ 2.633 + private JCExpression bridgeExpressionInvoke(VarSymbol rcvr) { 2.634 + JCExpression qualifier = 2.635 + tree.sym.isStatic() ? 2.636 + make.Type(tree.sym.owner.type) : 2.637 + (rcvr != null) ? 2.638 + make.Ident(rcvr) : 2.639 + tree.getQualifierExpression(); 2.640 + 2.641 + //create the qualifier expression 2.642 + JCFieldAccess select = make.Select(qualifier, tree.sym.name); 2.643 + select.sym = tree.sym; 2.644 + select.type = tree.sym.erasure(types); 2.645 + 2.646 + //create the method call expression 2.647 + JCExpression apply = make.Apply(List.<JCExpression>nil(), select, 2.648 + convertArgs(tree.sym, args.toList(), tree.varargsElement)).setType(tree.sym.erasure(types).getReturnType()); 2.649 + 2.650 + apply = transTypes.coerce(apply, localContext.generatedRefSig().getReturnType()); 2.651 + setVarargsIfNeeded(apply, tree.varargsElement); 2.652 + return apply; 2.653 + } 2.654 + 2.655 + /** 2.656 + * the enclosing expression is either 'null' (no enclosing type) or set 2.657 + * to the first bridge synthetic parameter 2.658 + */ 2.659 + private JCExpression bridgeExpressionNew() { 2.660 + JCExpression encl = null; 2.661 + switch (tree.kind) { 2.662 + case UNBOUND: 2.663 + case IMPLICIT_INNER: 2.664 + encl = make.Ident(params.first()); 2.665 + } 2.666 + 2.667 + //create the instance creation expression 2.668 + JCNewClass newClass = make.NewClass(encl, 2.669 + List.<JCExpression>nil(), 2.670 + make.Type(tree.getQualifierExpression().type), 2.671 + convertArgs(tree.sym, args.toList(), tree.varargsElement), 2.672 + null); 2.673 + newClass.constructor = tree.sym; 2.674 + newClass.constructorType = tree.sym.erasure(types); 2.675 + newClass.type = tree.getQualifierExpression().type; 2.676 + setVarargsIfNeeded(newClass, tree.varargsElement); 2.677 + return newClass; 2.678 + } 2.679 + 2.680 + private VarSymbol addParameter(String name, Type p, boolean genArg) { 2.681 + VarSymbol vsym = new VarSymbol(0, names.fromString(name), p, localContext.bridgeSym); 2.682 + params.append(make.VarDef(vsym, null)); 2.683 + if (genArg) { 2.684 + args.append(make.Ident(vsym)); 2.685 + } 2.686 + return vsym; 2.687 + } 2.688 + } 2.689 + 2.690 + /** 2.691 + * Bridges a member reference - this is needed when: 2.692 + * * Var args in the referenced method need to be flattened away 2.693 + * * super is used 2.694 + */ 2.695 + private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) { 2.696 + JCMethodDecl bridgeDecl = (new MemberReferenceBridger(tree, localContext).bridge()); 2.697 + translatedMethodList = translatedMethodList.prepend(bridgeDecl); 2.698 + } 2.699 + 2.700 + /** 2.701 + * Generate an indy method call to the meta factory 2.702 + */ 2.703 + private JCExpression makeMetaFactoryIndyCall(JCExpression tree, Type targetType, int refKind, Symbol refSym, List<JCExpression> indy_args) { 2.704 + //determine the static bsm args 2.705 + Type mtype = makeFunctionalDescriptorType(targetType, true); 2.706 + List<Object> staticArgs = List.<Object>of( 2.707 + new Pool.MethodHandle(ClassFile.REF_invokeInterface, types.findDescriptorSymbol(targetType.tsym)), 2.708 + new Pool.MethodHandle(refKind, refSym), 2.709 + new MethodType(mtype.getParameterTypes(), 2.710 + mtype.getReturnType(), 2.711 + mtype.getThrownTypes(), 2.712 + syms.methodClass)); 2.713 + 2.714 + //computed indy arg types 2.715 + ListBuffer<Type> indy_args_types = ListBuffer.lb(); 2.716 + for (JCExpression arg : indy_args) { 2.717 + indy_args_types.append(arg.type); 2.718 + } 2.719 + 2.720 + //finally, compute the type of the indy call 2.721 + MethodType indyType = new MethodType(indy_args_types.toList(), 2.722 + tree.type, 2.723 + List.<Type>nil(), 2.724 + syms.methodClass); 2.725 + 2.726 + return makeIndyCall(tree, syms.lambdaMetafactory, names.metaFactory, staticArgs, indyType, indy_args); 2.727 + } 2.728 + 2.729 + /** 2.730 + * Generate an indy method call with given name, type and static bootstrap 2.731 + * arguments types 2.732 + */ 2.733 + private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName, List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs) { 2.734 + int prevPos = make.pos; 2.735 + try { 2.736 + make.at(pos); 2.737 + List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType, 2.738 + syms.stringType, 2.739 + syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs)); 2.740 + 2.741 + Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site, 2.742 + bsmName, bsm_staticArgs, List.<Type>nil()); 2.743 + 2.744 + DynamicMethodSymbol dynSym = 2.745 + new DynamicMethodSymbol(names.lambda, 2.746 + syms.noSymbol, 2.747 + bsm.isStatic() ? ClassFile.REF_invokeStatic : ClassFile.REF_invokeVirtual, 2.748 + (MethodSymbol)bsm, 2.749 + indyType, 2.750 + staticArgs.toArray()); 2.751 + 2.752 + JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName); 2.753 + qualifier.sym = dynSym; 2.754 + qualifier.type = indyType.getReturnType(); 2.755 + 2.756 + JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, indyArgs); 2.757 + proxyCall.type = indyType.getReturnType(); 2.758 + return proxyCall; 2.759 + } finally { 2.760 + make.at(prevPos); 2.761 + } 2.762 + } 2.763 + //where 2.764 + private List<Type> bsmStaticArgToTypes(List<Object> args) { 2.765 + ListBuffer<Type> argtypes = ListBuffer.lb(); 2.766 + for (Object arg : args) { 2.767 + argtypes.append(bsmStaticArgToType(arg)); 2.768 + } 2.769 + return argtypes.toList(); 2.770 + } 2.771 + 2.772 + private Type bsmStaticArgToType(Object arg) { 2.773 + Assert.checkNonNull(arg); 2.774 + if (arg instanceof ClassSymbol) { 2.775 + return syms.classType; 2.776 + } else if (arg instanceof Integer) { 2.777 + return syms.intType; 2.778 + } else if (arg instanceof Long) { 2.779 + return syms.longType; 2.780 + } else if (arg instanceof Float) { 2.781 + return syms.floatType; 2.782 + } else if (arg instanceof Double) { 2.783 + return syms.doubleType; 2.784 + } else if (arg instanceof String) { 2.785 + return syms.stringType; 2.786 + } else if (arg instanceof Pool.MethodHandle) { 2.787 + return syms.methodHandleType; 2.788 + } else if (arg instanceof MethodType) { 2.789 + return syms.methodTypeType; 2.790 + } else { 2.791 + Assert.error("bad static arg " + arg.getClass()); 2.792 + return null; 2.793 + } 2.794 + } 2.795 + 2.796 + /** 2.797 + * Get the opcode associated with this method reference 2.798 + */ 2.799 + private int referenceKind(Symbol refSym) { 2.800 + if (refSym.isConstructor()) { 2.801 + return ClassFile.REF_newInvokeSpecial; 2.802 + } else { 2.803 + if (refSym.isStatic()) { 2.804 + return ClassFile.REF_invokeStatic; 2.805 + } else if (refSym.enclClass().isInterface()) { 2.806 + return ClassFile.REF_invokeInterface; 2.807 + } else { 2.808 + return ClassFile.REF_invokeVirtual; 2.809 + } 2.810 + } 2.811 + } 2.812 + // </editor-fold> 2.813 + 2.814 + // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">\ 2.815 + /** 2.816 + * This visitor collects information about translation of a lambda expression. 2.817 + * More specifically, it keeps track of the enclosing contexts and captured locals 2.818 + * accessed by the lambda being translated (as well as other useful info). 2.819 + */ 2.820 + class LambdaAnalyzer extends TreeScanner { 2.821 + 2.822 + /** the frame stack - used to reconstruct translation info about enclosing scopes */ 2.823 + private List<Frame> frameStack; 2.824 + 2.825 + /** 2.826 + * keep the count of lambda expression (used to generate unambiguous 2.827 + * names) 2.828 + */ 2.829 + private int lambdaCount = 0; 2.830 + 2.831 + private void analyzeClass(JCClassDecl tree) { 2.832 + frameStack = List.nil(); 2.833 + scan(tree); 2.834 + } 2.835 + 2.836 + @Override 2.837 + public void visitBlock(JCBlock tree) { 2.838 + List<Frame> prevStack = frameStack; 2.839 + try { 2.840 + if (frameStack.nonEmpty() && frameStack.head.tree.hasTag(CLASSDEF)) { 2.841 + frameStack = frameStack.prepend(new Frame(tree)); 2.842 + } 2.843 + super.visitBlock(tree); 2.844 + } 2.845 + finally { 2.846 + frameStack = prevStack; 2.847 + } 2.848 + } 2.849 + 2.850 + @Override 2.851 + public void visitClassDef(JCClassDecl tree) { 2.852 + List<Frame> prevStack = frameStack; 2.853 + try { 2.854 + if (frameStack.nonEmpty() && enclosingLambda() != null) { 2.855 + tree.sym.owner = owner(); 2.856 + LambdaTranslationContext lambdaContext = (LambdaTranslationContext)contextMap.get(enclosingLambda()); 2.857 + Type encl = lambdaContext.enclosingType(); 2.858 + if (encl.hasTag(NONE)) { 2.859 + //if the translated lambda body occurs in a static context, 2.860 + //any class declaration within it must be made static 2.861 + tree.sym.flags_field |= STATIC; 2.862 + ((ClassType)tree.sym.type).setEnclosingType(Type.noType); 2.863 + } else { 2.864 + //if the translated lambda body is in an instance context 2.865 + //the enclosing type of any class declaration within it 2.866 + //must be updated to point to the new enclosing type (if any) 2.867 + ((ClassType)tree.sym.type).setEnclosingType(encl); 2.868 + } 2.869 + } 2.870 + frameStack = frameStack.prepend(new Frame(tree)); 2.871 + super.visitClassDef(tree); 2.872 + } 2.873 + finally { 2.874 + frameStack = prevStack; 2.875 + } 2.876 + if (frameStack.nonEmpty() && enclosingLambda() != null) { 2.877 + // Any class defined within a lambda is an implicit 'this' reference 2.878 + // because its constructor will reference the enclosing class 2.879 + ((LambdaTranslationContext) context()).addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS); 2.880 + } 2.881 + } 2.882 + 2.883 + @Override 2.884 + public void visitIdent(JCIdent tree) { 2.885 + if (context() == null || !lambdaIdentSymbolFilter(tree.sym)) { 2.886 + super.visitIdent(tree); 2.887 + } else { 2.888 + if (tree.sym.kind == VAR && 2.889 + tree.sym.owner.kind == MTH && 2.890 + tree.type.constValue() == null) { 2.891 + TranslationContext<?> localContext = context(); 2.892 + while (localContext != null) { 2.893 + if (localContext.tree.getTag() == LAMBDA) { 2.894 + JCTree block = capturedDecl(localContext.depth, tree.sym); 2.895 + if (block == null) break; 2.896 + ((LambdaTranslationContext)localContext).addSymbol(tree.sym, CAPTURED_VAR); 2.897 + } 2.898 + localContext = localContext.prev; 2.899 + } 2.900 + } else if (tree.sym.owner.kind == TYP) { 2.901 + TranslationContext<?> localContext = context(); 2.902 + while (localContext != null) { 2.903 + if (localContext.tree.hasTag(LAMBDA)) { 2.904 + JCTree block = capturedDecl(localContext.depth, tree.sym); 2.905 + if (block == null) break; 2.906 + switch (block.getTag()) { 2.907 + case CLASSDEF: 2.908 + JCClassDecl cdecl = (JCClassDecl)block; 2.909 + ((LambdaTranslationContext)localContext).addSymbol(cdecl.sym, CAPTURED_THIS); 2.910 + break; 2.911 + default: 2.912 + Assert.error("bad block kind"); 2.913 + } 2.914 + } 2.915 + localContext = localContext.prev; 2.916 + } 2.917 + } 2.918 + } 2.919 + } 2.920 + 2.921 + @Override 2.922 + public void visitLambda(JCLambda tree) { 2.923 + List<Frame> prevStack = frameStack; 2.924 + try { 2.925 + LambdaTranslationContext context = (LambdaTranslationContext)makeLambdaContext(tree); 2.926 + frameStack = frameStack.prepend(new Frame(tree)); 2.927 + for (JCVariableDecl param : tree.params) { 2.928 + context.addSymbol(param.sym, PARAM); 2.929 + frameStack.head.addLocal(param.sym); 2.930 + } 2.931 + contextMap.put(tree, context); 2.932 + scan(tree.body); 2.933 + context.complete(); 2.934 + } 2.935 + finally { 2.936 + frameStack = prevStack; 2.937 + } 2.938 + } 2.939 + 2.940 + @Override 2.941 + public void visitMethodDef(JCMethodDecl tree) { 2.942 + List<Frame> prevStack = frameStack; 2.943 + try { 2.944 + frameStack = frameStack.prepend(new Frame(tree)); 2.945 + super.visitMethodDef(tree); 2.946 + } 2.947 + finally { 2.948 + frameStack = prevStack; 2.949 + } 2.950 + } 2.951 + 2.952 + @Override 2.953 + public void visitNewClass(JCNewClass tree) { 2.954 + if (lambdaNewClassFilter(context(), tree)) { 2.955 + ((LambdaTranslationContext) context()).addSymbol(tree.type.getEnclosingType().tsym, CAPTURED_THIS); 2.956 + } 2.957 + super.visitNewClass(tree); 2.958 + } 2.959 + 2.960 + @Override 2.961 + public void visitReference(JCMemberReference tree) { 2.962 + scan(tree.getQualifierExpression()); 2.963 + contextMap.put(tree, makeReferenceContext(tree)); 2.964 + } 2.965 + 2.966 + @Override 2.967 + public void visitSelect(JCFieldAccess tree) { 2.968 + if (context() != null && lambdaSelectSymbolFilter(tree.sym)) { 2.969 + TranslationContext<?> localContext = context(); 2.970 + while (localContext != null) { 2.971 + if (localContext.tree.hasTag(LAMBDA)) { 2.972 + JCClassDecl clazz = (JCClassDecl)capturedDecl(localContext.depth, tree.sym); 2.973 + if (clazz == null) break; 2.974 + ((LambdaTranslationContext)localContext).addSymbol(clazz.sym, CAPTURED_THIS); 2.975 + } 2.976 + localContext = localContext.prev; 2.977 + } 2.978 + scan(tree.selected); 2.979 + } else { 2.980 + super.visitSelect(tree); 2.981 + } 2.982 + } 2.983 + 2.984 + @Override 2.985 + public void visitVarDef(JCVariableDecl tree) { 2.986 + if (frameStack.head.tree.hasTag(LAMBDA)) { 2.987 + ((LambdaTranslationContext)context()).addSymbol(tree.sym, LOCAL_VAR); 2.988 + } 2.989 + List<Frame> prevStack = frameStack; 2.990 + try { 2.991 + if (tree.sym.owner.kind == MTH) { 2.992 + frameStack.head.addLocal(tree.sym); 2.993 + } 2.994 + frameStack = frameStack.prepend(new Frame(tree)); 2.995 + super.visitVarDef(tree); 2.996 + } 2.997 + finally { 2.998 + frameStack = prevStack; 2.999 + } 2.1000 + } 2.1001 + 2.1002 + private Name lambdaName() { 2.1003 + return names.lambda.append(names.fromString("$" + lambdaCount++)); 2.1004 + } 2.1005 + 2.1006 + /** 2.1007 + * Return a valid owner given the current declaration stack 2.1008 + * (required to skip synthetic lambda symbols) 2.1009 + */ 2.1010 + private Symbol owner() { 2.1011 + List<Frame> frameStack2 = frameStack; 2.1012 + while (frameStack2.nonEmpty()) { 2.1013 + switch (frameStack2.head.tree.getTag()) { 2.1014 + case VARDEF: 2.1015 + if (((JCVariableDecl)frameStack2.head.tree).sym.isLocal()) { 2.1016 + frameStack2 = frameStack2.tail; 2.1017 + break; 2.1018 + } 2.1019 + JCClassDecl cdecl = (JCClassDecl)frameStack2.tail.head.tree; 2.1020 + return makeSyntheticMethod(((JCVariableDecl)frameStack2.head.tree).sym.flags() & STATIC, names.empty, null, cdecl.sym); 2.1021 + case BLOCK: 2.1022 + JCClassDecl cdecl2 = (JCClassDecl)frameStack2.tail.head.tree; 2.1023 + return makeSyntheticMethod(((JCBlock)frameStack2.head.tree).flags & STATIC | Flags.BLOCK, names.empty, null, cdecl2.sym); 2.1024 + case CLASSDEF: 2.1025 + return ((JCClassDecl)frameStack2.head.tree).sym; 2.1026 + case METHODDEF: 2.1027 + return ((JCMethodDecl)frameStack2.head.tree).sym; 2.1028 + case LAMBDA: 2.1029 + return ((LambdaTranslationContext)contextMap.get(frameStack2.head.tree)).translatedSym; 2.1030 + default: 2.1031 + frameStack2 = frameStack2.tail; 2.1032 + } 2.1033 + } 2.1034 + Assert.error(); 2.1035 + return null; 2.1036 + } 2.1037 + 2.1038 + private JCTree enclosingLambda() { 2.1039 + List<Frame> frameStack2 = frameStack; 2.1040 + while (frameStack2.nonEmpty()) { 2.1041 + switch (frameStack2.head.tree.getTag()) { 2.1042 + case CLASSDEF: 2.1043 + case METHODDEF: 2.1044 + return null; 2.1045 + case LAMBDA: 2.1046 + return frameStack2.head.tree; 2.1047 + default: 2.1048 + frameStack2 = frameStack2.tail; 2.1049 + } 2.1050 + } 2.1051 + Assert.error(); 2.1052 + return null; 2.1053 + } 2.1054 + 2.1055 + /** 2.1056 + * Return the declaration corresponding to a symbol in the enclosing 2.1057 + * scope; the depth parameter is used to filter out symbols defined 2.1058 + * in nested scopes (which do not need to undergo capture). 2.1059 + */ 2.1060 + private JCTree capturedDecl(int depth, Symbol sym) { 2.1061 + int currentDepth = frameStack.size() - 1; 2.1062 + for (Frame block : frameStack) { 2.1063 + switch (block.tree.getTag()) { 2.1064 + case CLASSDEF: 2.1065 + ClassSymbol clazz = ((JCClassDecl)block.tree).sym; 2.1066 + if (sym.isMemberOf(clazz, types)) { 2.1067 + return currentDepth > depth ? null : block.tree; 2.1068 + } 2.1069 + break; 2.1070 + case VARDEF: 2.1071 + if (((JCVariableDecl)block.tree).sym == sym && 2.1072 + sym.owner.kind == MTH) { //only locals are captured 2.1073 + return currentDepth > depth ? null : block.tree; 2.1074 + } 2.1075 + break; 2.1076 + case BLOCK: 2.1077 + case METHODDEF: 2.1078 + case LAMBDA: 2.1079 + if (block.locals != null && block.locals.contains(sym)) { 2.1080 + return currentDepth > depth ? null : block.tree; 2.1081 + } 2.1082 + break; 2.1083 + default: 2.1084 + Assert.error("bad decl kind " + block.tree.getTag()); 2.1085 + } 2.1086 + currentDepth--; 2.1087 + } 2.1088 + return null; 2.1089 + } 2.1090 + 2.1091 + private TranslationContext<?> context() { 2.1092 + for (Frame frame : frameStack) { 2.1093 + TranslationContext<?> context = contextMap.get(frame.tree); 2.1094 + if (context != null) { 2.1095 + return context; 2.1096 + } 2.1097 + } 2.1098 + return null; 2.1099 + } 2.1100 + 2.1101 + /** 2.1102 + * This is used to filter out those identifiers that needs to be adjusted 2.1103 + * when translating away lambda expressions 2.1104 + */ 2.1105 + private boolean lambdaIdentSymbolFilter(Symbol sym) { 2.1106 + return (sym.kind == VAR || sym.kind == MTH) 2.1107 + && !sym.isStatic() 2.1108 + && sym.name != names.init; 2.1109 + } 2.1110 + 2.1111 + private boolean lambdaSelectSymbolFilter(Symbol sym) { 2.1112 + return (sym.kind == VAR || sym.kind == MTH) && 2.1113 + !sym.isStatic() && 2.1114 + (sym.name == names._this || 2.1115 + sym.name == names._super); 2.1116 + } 2.1117 + 2.1118 + /** 2.1119 + * This is used to filter out those new class expressions that need to 2.1120 + * be qualified with an enclosing tree 2.1121 + */ 2.1122 + private boolean lambdaNewClassFilter(TranslationContext<?> context, JCNewClass tree) { 2.1123 + if (context != null 2.1124 + && tree.encl == null 2.1125 + && tree.def == null 2.1126 + && tree.type.getEnclosingType().hasTag(NONE)) { 2.1127 + Type encl = tree.type.getEnclosingType(); 2.1128 + Type current = context.owner.enclClass().type; 2.1129 + while (current.hasTag(NONE)) { 2.1130 + if (current.tsym.isSubClass(encl.tsym, types)) { 2.1131 + return true; 2.1132 + } 2.1133 + current = current.getEnclosingType(); 2.1134 + } 2.1135 + return false; 2.1136 + } else { 2.1137 + return false; 2.1138 + } 2.1139 + } 2.1140 + 2.1141 + private TranslationContext<JCLambda> makeLambdaContext(JCLambda tree) { 2.1142 + return new LambdaTranslationContext(tree); 2.1143 + } 2.1144 + 2.1145 + private TranslationContext<JCMemberReference> makeReferenceContext(JCMemberReference tree) { 2.1146 + return new ReferenceTranslationContext(tree); 2.1147 + } 2.1148 + 2.1149 + private class Frame { 2.1150 + final JCTree tree; 2.1151 + List<Symbol> locals; 2.1152 + 2.1153 + public Frame(JCTree tree) { 2.1154 + this.tree = tree; 2.1155 + } 2.1156 + 2.1157 + void addLocal(Symbol sym) { 2.1158 + if (locals == null) { 2.1159 + locals = List.nil(); 2.1160 + } 2.1161 + locals = locals.prepend(sym); 2.1162 + } 2.1163 + } 2.1164 + 2.1165 + /** 2.1166 + * This class is used to store important information regarding translation of 2.1167 + * lambda expression/method references (see subclasses). 2.1168 + */ 2.1169 + private abstract class TranslationContext<T extends JCTree> { 2.1170 + 2.1171 + /** the underlying (untranslated) tree */ 2.1172 + T tree; 2.1173 + 2.1174 + /** points to the adjusted enclosing scope in which this lambda/mref expression occurs */ 2.1175 + Symbol owner; 2.1176 + 2.1177 + /** the depth of this lambda expression in the frame stack */ 2.1178 + int depth; 2.1179 + 2.1180 + /** the enclosing translation context (set for nested lambdas/mref) */ 2.1181 + TranslationContext<?> prev; 2.1182 + 2.1183 + TranslationContext(T tree) { 2.1184 + this.tree = tree; 2.1185 + this.owner = owner(); 2.1186 + this.depth = frameStack.size() - 1; 2.1187 + this.prev = context(); 2.1188 + } 2.1189 + } 2.1190 + 2.1191 + /** 2.1192 + * This class retains all the useful information about a lambda expression; 2.1193 + * the contents of this class are filled by the LambdaAnalyzer visitor, 2.1194 + * and the used by the main translation routines in order to adjust references 2.1195 + * to captured locals/members, etc. 2.1196 + */ 2.1197 + private class LambdaTranslationContext extends TranslationContext<JCLambda> { 2.1198 + 2.1199 + /** variable in the enclosing context to which this lambda is assigned */ 2.1200 + Symbol self; 2.1201 + 2.1202 + /** map from original to translated lambda parameters */ 2.1203 + Map<Symbol, Symbol> lambdaParams = new LinkedHashMap<Symbol, Symbol>(); 2.1204 + 2.1205 + /** map from original to translated lambda locals */ 2.1206 + Map<Symbol, Symbol> lambdaLocals = new LinkedHashMap<Symbol, Symbol>(); 2.1207 + 2.1208 + /** map from variables in enclosing scope to translated synthetic parameters */ 2.1209 + Map<Symbol, Symbol> capturedLocals = new LinkedHashMap<Symbol, Symbol>(); 2.1210 + 2.1211 + /** map from class symbols to translated synthetic parameters (for captured member access) */ 2.1212 + Map<Symbol, Symbol> capturedThis = new LinkedHashMap<Symbol, Symbol>(); 2.1213 + 2.1214 + /** the synthetic symbol for the method hoisting the translated lambda */ 2.1215 + Symbol translatedSym; 2.1216 + 2.1217 + List<JCVariableDecl> syntheticParams; 2.1218 + 2.1219 + LambdaTranslationContext(JCLambda tree) { 2.1220 + super(tree); 2.1221 + Frame frame = frameStack.head; 2.1222 + if (frame.tree.hasTag(VARDEF)) { 2.1223 + self = ((JCVariableDecl)frame.tree).sym; 2.1224 + } 2.1225 + this.translatedSym = makeSyntheticMethod(0, lambdaName(), null, owner.enclClass()); 2.1226 + } 2.1227 + 2.1228 + /** 2.1229 + * Translate a symbol of a given kind into something suitable for the 2.1230 + * synthetic lambda body 2.1231 + */ 2.1232 + Symbol translate(String name, Symbol sym, LambdaSymbolKind skind) { 2.1233 + if (skind == CAPTURED_THIS) { 2.1234 + return sym; // self represented 2.1235 + } else { 2.1236 + return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym); 2.1237 + } 2.1238 + } 2.1239 + 2.1240 + void addSymbol(Symbol sym, LambdaSymbolKind skind) { 2.1241 + Map<Symbol, Symbol> transMap = null; 2.1242 + String preferredName; 2.1243 + switch (skind) { 2.1244 + case CAPTURED_THIS: 2.1245 + transMap = capturedThis; 2.1246 + preferredName = "encl$" + capturedThis.size(); 2.1247 + break; 2.1248 + case CAPTURED_VAR: 2.1249 + transMap = capturedLocals; 2.1250 + preferredName = "cap$" + capturedLocals.size(); 2.1251 + break; 2.1252 + case LOCAL_VAR: 2.1253 + transMap = lambdaLocals; 2.1254 + preferredName = sym.name.toString(); 2.1255 + break; 2.1256 + case PARAM: 2.1257 + transMap = lambdaParams; 2.1258 + preferredName = sym.name.toString(); 2.1259 + break; 2.1260 + default: throw new AssertionError(); 2.1261 + } 2.1262 + if (!transMap.containsKey(sym)) { 2.1263 + transMap.put(sym, translate(preferredName, sym, skind)); 2.1264 + } 2.1265 + } 2.1266 + 2.1267 + Map<Symbol, Symbol> getSymbolMap(LambdaSymbolKind... skinds) { 2.1268 + LinkedHashMap<Symbol, Symbol> translationMap = new LinkedHashMap<Symbol, Symbol>(); 2.1269 + for (LambdaSymbolKind skind : skinds) { 2.1270 + switch (skind) { 2.1271 + case CAPTURED_THIS: 2.1272 + translationMap.putAll(capturedThis); 2.1273 + break; 2.1274 + case CAPTURED_VAR: 2.1275 + translationMap.putAll(capturedLocals); 2.1276 + break; 2.1277 + case LOCAL_VAR: 2.1278 + translationMap.putAll(lambdaLocals); 2.1279 + break; 2.1280 + case PARAM: 2.1281 + translationMap.putAll(lambdaParams); 2.1282 + break; 2.1283 + default: throw new AssertionError(); 2.1284 + } 2.1285 + } 2.1286 + return translationMap; 2.1287 + } 2.1288 + 2.1289 + /** 2.1290 + * The translatedSym is not complete/accurate until the analysis is 2.1291 + * finished. Once the analysis is finished, the translatedSym is 2.1292 + * "completed" -- updated with type information, access modifiers, 2.1293 + * and full parameter list. 2.1294 + */ 2.1295 + void complete() { 2.1296 + if (syntheticParams != null) { 2.1297 + return; 2.1298 + } 2.1299 + boolean inInterface = translatedSym.owner.isInterface(); 2.1300 + boolean thisReferenced = !getSymbolMap(CAPTURED_THIS).isEmpty(); 2.1301 + boolean needInstance = thisReferenced || inInterface; 2.1302 + 2.1303 + // If instance access isn't needed, make it static 2.1304 + // Interface methods much be public default methods, otherwise make it private 2.1305 + translatedSym.flags_field = SYNTHETIC | (needInstance? 0 : STATIC) | (inInterface? PUBLIC | DEFAULT : PRIVATE); 2.1306 + 2.1307 + //compute synthetic params 2.1308 + ListBuffer<JCVariableDecl> params = ListBuffer.lb(); 2.1309 + 2.1310 + // The signature of the method is augmented with the following 2.1311 + // synthetic parameters: 2.1312 + // 2.1313 + // 1) reference to enclosing contexts captured by the lambda expression 2.1314 + // 2) enclosing locals captured by the lambda expression 2.1315 + for (Symbol thisSym : getSymbolMap(CAPTURED_VAR, PARAM).values()) { 2.1316 + params.append(make.VarDef((VarSymbol) thisSym, null)); 2.1317 + } 2.1318 + 2.1319 + syntheticParams = params.toList(); 2.1320 + 2.1321 + //prepend synthetic args to translated lambda method signature 2.1322 + translatedSym.type = (MethodType) types.createMethodTypeWithParameters( 2.1323 + (MethodType) generatedLambdaSig(), 2.1324 + TreeInfo.types(syntheticParams)); 2.1325 + } 2.1326 + 2.1327 + Type enclosingType() { 2.1328 + //local inner classes defined inside a lambda are always non-static 2.1329 + return owner.enclClass().type; 2.1330 + } 2.1331 + 2.1332 + Type generatedLambdaSig() { 2.1333 + return types.erasure(types.findDescriptorType(tree.targetType)); 2.1334 + } 2.1335 + } 2.1336 + 2.1337 + /** 2.1338 + * This class retains all the useful information about a method reference; 2.1339 + * the contents of this class are filled by the LambdaAnalyzer visitor, 2.1340 + * and the used by the main translation routines in order to adjust method 2.1341 + * references (i.e. in case a bridge is needed) 2.1342 + */ 2.1343 + private class ReferenceTranslationContext extends TranslationContext<JCMemberReference> { 2.1344 + 2.1345 + final boolean isSuper; 2.1346 + final Symbol bridgeSym; 2.1347 + 2.1348 + ReferenceTranslationContext(JCMemberReference tree) { 2.1349 + super(tree); 2.1350 + this.isSuper = tree.hasKind(ReferenceKind.SUPER); 2.1351 + this.bridgeSym = needsBridge() 2.1352 + ? makeSyntheticMethod(isSuper ? 0 : STATIC, 2.1353 + lambdaName().append(names.fromString("$bridge")), null, 2.1354 + owner.enclClass()) 2.1355 + : null; 2.1356 + } 2.1357 + 2.1358 + /** 2.1359 + * Get the opcode associated with this method reference 2.1360 + */ 2.1361 + int referenceKind() { 2.1362 + return LambdaToMethod.this.referenceKind(needsBridge() ? bridgeSym : tree.sym); 2.1363 + } 2.1364 + 2.1365 + boolean needsVarArgsConversion() { 2.1366 + return tree.varargsElement != null; 2.1367 + } 2.1368 + 2.1369 + /** 2.1370 + * @return Is this an array operation like clone() 2.1371 + */ 2.1372 + boolean isArrayOp() { 2.1373 + return tree.sym.owner == syms.arrayClass; 2.1374 + } 2.1375 + 2.1376 + /** 2.1377 + * Does this reference needs a bridge (i.e. var args need to be 2.1378 + * expanded or "super" is used) 2.1379 + */ 2.1380 + final boolean needsBridge() { 2.1381 + return isSuper || needsVarArgsConversion() || isArrayOp(); 2.1382 + } 2.1383 + 2.1384 + Type generatedRefSig() { 2.1385 + return types.erasure(tree.sym.type); 2.1386 + } 2.1387 + 2.1388 + Type bridgedRefSig() { 2.1389 + return types.erasure(types.findDescriptorSymbol(tree.targetType.tsym).type); 2.1390 + } 2.1391 + } 2.1392 + } 2.1393 + // </editor-fold> 2.1394 + 2.1395 + enum LambdaSymbolKind { 2.1396 + CAPTURED_VAR, 2.1397 + CAPTURED_THIS, 2.1398 + LOCAL_VAR, 2.1399 + PARAM; 2.1400 + } 2.1401 +}
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Fri Oct 26 18:40:13 2012 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Mon Oct 29 10:39:49 2012 -0700 3.3 @@ -120,6 +120,16 @@ 3.4 * @param tree The expression tree. 3.5 * @param target The target type. 3.6 */ 3.7 + public JCExpression coerce(Env<AttrContext> env, JCExpression tree, Type target) { 3.8 + Env<AttrContext> prevEnv = this.env; 3.9 + try { 3.10 + this.env = env; 3.11 + return coerce(tree, target); 3.12 + } 3.13 + finally { 3.14 + this.env = prevEnv; 3.15 + } 3.16 + } 3.17 JCExpression coerce(JCExpression tree, Type target) { 3.18 Type btarget = target.baseType(); 3.19 if (tree.type.isPrimitive() == target.isPrimitive()) { 3.20 @@ -196,6 +206,20 @@ 3.21 return _args; 3.22 } 3.23 3.24 + public <T extends JCTree> List<T> translateArgs(List<T> _args, 3.25 + List<Type> parameters, 3.26 + Type varargsElement, 3.27 + Env<AttrContext> localEnv) { 3.28 + Env<AttrContext> prevEnv = env; 3.29 + try { 3.30 + env = localEnv; 3.31 + return translateArgs(_args, parameters, varargsElement); 3.32 + } 3.33 + finally { 3.34 + env = prevEnv; 3.35 + } 3.36 + } 3.37 + 3.38 /** Add a bridge definition and enter corresponding method symbol in 3.39 * local scope of origin. 3.40 * 3.41 @@ -451,9 +475,9 @@ 3.42 result = tree; 3.43 } 3.44 3.45 - JCMethodDecl currentMethod = null; 3.46 + JCTree currentMethod = null; 3.47 public void visitMethodDef(JCMethodDecl tree) { 3.48 - JCMethodDecl previousMethod = currentMethod; 3.49 + JCTree previousMethod = currentMethod; 3.50 try { 3.51 currentMethod = tree; 3.52 tree.restype = translate(tree.restype, null); 3.53 @@ -519,6 +543,22 @@ 3.54 result = tree; 3.55 } 3.56 3.57 + public void visitLambda(JCLambda tree) { 3.58 + JCTree prevMethod = currentMethod; 3.59 + try { 3.60 + currentMethod = null; 3.61 + tree.params = translate(tree.params); 3.62 + tree.body = translate(tree.body, null); 3.63 + //save non-erased target 3.64 + tree.targetType = tree.type; 3.65 + tree.type = erasure(tree.type); 3.66 + result = tree; 3.67 + } 3.68 + finally { 3.69 + currentMethod = prevMethod; 3.70 + } 3.71 + } 3.72 + 3.73 public void visitSwitch(JCSwitch tree) { 3.74 Type selsuper = types.supertype(tree.selector.type); 3.75 boolean enumSwitch = selsuper != null && 3.76 @@ -570,7 +610,7 @@ 3.77 } 3.78 3.79 public void visitReturn(JCReturn tree) { 3.80 - tree.expr = translate(tree.expr, currentMethod.sym.erasure(types).getReturnType()); 3.81 + tree.expr = translate(tree.expr, currentMethod != null ? types.erasure(currentMethod.type).getReturnType() : null); 3.82 result = tree; 3.83 } 3.84 3.85 @@ -601,6 +641,7 @@ 3.86 Assert.check(tree.args.length() == argtypes.length()); 3.87 tree.args = translateArgs(tree.args, argtypes, tree.varargsElement); 3.88 3.89 + tree.type = types.erasure(tree.type); 3.90 // Insert casts of method invocation results as needed. 3.91 result = retype(tree, mt.getReturnType(), pt); 3.92 } 3.93 @@ -614,6 +655,8 @@ 3.94 tree.args = translateArgs( 3.95 tree.args, tree.constructor.erasure(types).getParameterTypes(), tree.varargsElement); 3.96 tree.def = translate(tree.def, null); 3.97 + if (tree.constructorType != null) 3.98 + tree.constructorType = erasure(tree.constructorType); 3.99 tree.type = erasure(tree.type); 3.100 result = tree; 3.101 } 3.102 @@ -631,16 +674,6 @@ 3.103 result = tree; 3.104 } 3.105 3.106 - @Override 3.107 - public void visitLambda(JCLambda tree) { 3.108 - Assert.error("Translation of lambda expression not supported yet"); 3.109 - } 3.110 - 3.111 - @Override 3.112 - public void visitReference(JCMemberReference tree) { 3.113 - Assert.error("Translation of method reference not supported yet"); 3.114 - } 3.115 - 3.116 public void visitParens(JCParens tree) { 3.117 tree.expr = translate(tree.expr, pt); 3.118 tree.type = erasure(tree.type); 3.119 @@ -749,6 +782,14 @@ 3.120 } 3.121 } 3.122 3.123 + public void visitReference(JCMemberReference tree) { 3.124 + tree.expr = translate(tree.expr, null); 3.125 + //save non-erased target 3.126 + tree.targetType = tree.type; 3.127 + tree.type = erasure(tree.type); 3.128 + result = tree; 3.129 + } 3.130 + 3.131 public void visitTypeArray(JCArrayTypeTree tree) { 3.132 tree.elemtype = translate(tree.elemtype, null); 3.133 tree.type = erasure(tree.type);
4.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Oct 26 18:40:13 2012 -0700 4.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Oct 29 10:39:49 2012 -0700 4.3 @@ -271,6 +271,10 @@ 4.4 */ 4.5 protected TransTypes transTypes; 4.6 4.7 + /** The lambda translator. 4.8 + */ 4.9 + protected LambdaToMethod lambdaToMethod; 4.10 + 4.11 /** The syntactic sugar desweetener. 4.12 */ 4.13 protected Lower lower; 4.14 @@ -369,6 +373,8 @@ 4.15 4.16 options = Options.instance(context); 4.17 4.18 + lambdaToMethod = LambdaToMethod.instance(context); 4.19 + 4.20 verbose = options.isSet(VERBOSE); 4.21 sourceOutput = options.isSet(PRINTSOURCE); // used to be -s 4.22 stubOutput = options.isSet("-stubs"); 4.23 @@ -524,8 +530,10 @@ 4.24 ATTR(4), 4.25 FLOW(5), 4.26 TRANSTYPES(6), 4.27 - LOWER(7), 4.28 - GENERATE(8); 4.29 + UNLAMBDA(7), 4.30 + LOWER(8), 4.31 + GENERATE(9); 4.32 + 4.33 CompileState(int value) { 4.34 this.value = value; 4.35 } 4.36 @@ -1418,6 +1426,12 @@ 4.37 env.tree = transTypes.translateTopLevelClass(env.tree, localMake); 4.38 compileStates.put(env, CompileState.TRANSTYPES); 4.39 4.40 + if (shouldStop(CompileState.UNLAMBDA)) 4.41 + return; 4.42 + 4.43 + env.tree = lambdaToMethod.translateTopLevelClass(env, env.tree, localMake); 4.44 + compileStates.put(env, CompileState.UNLAMBDA); 4.45 + 4.46 if (shouldStop(CompileState.LOWER)) 4.47 return; 4.48
5.1 --- a/src/share/classes/com/sun/tools/javac/util/Names.java Fri Oct 26 18:40:13 2012 -0700 5.2 +++ b/src/share/classes/com/sun/tools/javac/util/Names.java Mon Oct 29 10:39:49 2012 -0700 5.3 @@ -170,6 +170,10 @@ 5.4 public final Name ex; 5.5 public final Name package_info; 5.6 5.7 + //lambda-related 5.8 + public final Name lambda; 5.9 + public final Name metaFactory; 5.10 + 5.11 public final Name.Table table; 5.12 5.13 public Names(Context context) { 5.14 @@ -298,6 +302,10 @@ 5.15 deprecated = fromString("deprecated"); 5.16 ex = fromString("ex"); 5.17 package_info = fromString("package-info"); 5.18 + 5.19 + //lambda-related 5.20 + lambda = fromString("lambda"); 5.21 + metaFactory = fromString("metaFactory"); 5.22 } 5.23 5.24 protected Name.Table createTable(Options options) {