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