changeset 1235:25fa5d41689a

Improved code-generation logic for method/constructor references. Cleanup code-generation logic for method/constructor references by leveraging a new classficiation of method/constructor references available in JCMemberReference.
author mcimadamore
date Wed, 30 Nov 2011 16:51:10 +0000
parents f7ee8488cea5
children 3ba4789b8899
files src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java src/share/classes/com/sun/tools/javac/tree/JCTree.java
diffstat 5 files changed, 149 insertions(+), 96 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Nov 29 18:12:54 2011 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Nov 30 16:51:10 2011 +0000
@@ -41,6 +41,7 @@
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
 import com.sun.tools.javac.code.Type.ForAll.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.comp.Infer.InferenceContext;
@@ -2535,9 +2536,6 @@
             //if the qualifier is a type, validate it
             chk.validate(that.expr, env);
         }
-        
-        Assert.check(that.mode == JCMemberReference.ReferenceMode.INVOKE ||
-                that.mode == JCMemberReference.ReferenceMode.NEW);
 
         final ForAll owntype = new SAMDeferredAttribution<JCMemberReference>(POLY_REFERENCE, env, that) {
 
@@ -2571,9 +2569,6 @@
 
     //where
     private Type attribMethodReference(Env<AttrContext> localEnv, InferenceContext inferenceContext, JCMemberReference tree, Type to, boolean allowBoxing) {
-        Assert.check(tree.mode == JCMemberReference.ReferenceMode.INVOKE ||
-                tree.mode == JCMemberReference.ReferenceMode.NEW);
-        
         Type samDesc = types.findDescriptor(to);
 
         //attrib type-arguments and receiver expr
@@ -2622,12 +2617,9 @@
         }
 
         tree.sym = refSym;
-
-        tree.isUnbound = tree.getMode() == ReferenceMode.INVOKE ?
-                    (!tree.sym.isStatic() && TreeInfo.isStaticSelector(tree.getQualifierExpression(), names)) :
-                    (tree.sym.owner.type.getEnclosingType() != Type.noType && !rs.hasEnclosingInstance(env, tree.sym.owner.type));
+        setReferenceKind(tree);
         
-        Type refType = checkReference(tree.expr.type, refSym, localEnv, argtypes, typeargtypes, tree.isUnbound);
+        Type refType = checkReference(tree, localEnv, argtypes, typeargtypes);
         Type returnType = tree.getMode() == ReferenceMode.INVOKE ?
                 refType.getReturnType() : tree.expr.type;
 
@@ -2638,12 +2630,40 @@
         return tree.targetType = to;
     }
     //where
-        private Type checkReference(Type site, Symbol sym, Env<AttrContext> env,
-                                    List<Type> argtypes, List<Type> typeargtypes, boolean isUnbound) {
-            if (isUnbound) {
+        private Type checkReference(JCMemberReference tree, Env<AttrContext> env,
+                                    List<Type> argtypes, List<Type> typeargtypes) {
+            if (tree.kind.isUnbound()) {
                 argtypes = argtypes.tail;
             }
-            return checkMethod(site, sym, env, null, argtypes, typeargtypes, env.info.varArgs);
+            return checkMethod(tree.expr.type, tree.sym, env, null, argtypes, typeargtypes, env.info.varArgs);
+        }
+        
+        private void setReferenceKind(JCMemberReference tree) {
+            if (tree.name == names.init) {
+                //Constructor reference
+                if (tree.sym.owner.type.getEnclosingType() == Type.noType) {
+                    tree.kind = ReferenceKind.TOPLEVEL;
+                } else if (!rs.hasEnclosingInstance(env, tree.sym.owner.type)) {
+                    tree.kind = ReferenceKind.UNBOUND_INNER;
+                } else {
+                    tree.kind = ReferenceKind.IMPLICIT_INNER;
+                }
+            } else if (TreeInfo.isStaticSelector(tree.getQualifierExpression(), names)) {
+                if (tree.sym.isStatic()) {
+                    tree.kind = ReferenceKind.STATIC;
+                } else {
+                    tree.kind = ReferenceKind.UNBOUND;
+                }
+            } else {
+                Name name = TreeInfo.name(tree.getQualifierExpression());
+                if (name != null && name == names._super) {
+                    tree.kind = ReferenceKind.SUPER;
+                } else if (tree.sym.isStatic()) {
+                    tree.kind = ReferenceKind.STATIC_EVAL;
+                } else {
+                    tree.kind = ReferenceKind.BOUND;
+                }
+            }
         }
 
     /**
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Tue Nov 29 18:12:54 2011 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Wed Nov 30 16:51:10 2011 +0000
@@ -29,6 +29,7 @@
 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
 import com.sun.tools.javac.comp.LambdaTranslator.LambdaAnalyzer;
 import com.sun.tools.javac.comp.LambdaToInnerClass.LambdaToInnerAnalyzer.*;
 import com.sun.tools.javac.util.*;
@@ -165,7 +166,7 @@
     public void visitReference(JCMemberReference tree) {
         ReferenceToInnerTranslationContext localContext = (ReferenceToInnerTranslationContext)context;
         
-        Symbol refSym = localContext.isSpecial() ?
+        Symbol refSym = tree.hasKind(ReferenceKind.SUPER) ?
             bridgeMemberReference(tree, localContext) :
             tree.sym;
             
@@ -184,7 +185,7 @@
         samClassDecl.type = localContext.referenceClassSym.type;
 
         ListBuffer<JCVariableDecl> capturedFields = ListBuffer.lb();
-        if (localContext.isInstanceRef() && !localContext.isSpecial()) {
+        if (tree.hasKind(ReferenceKind.BOUND)) {
             Symbol recField = makeSyntheticVar(0, "rec$", tree.getQualifierExpression().type, localContext.referenceClassSym);
             capturedFields.append(make.at(tree.pos).VarDef((VarSymbol)recField, null));
             samClassDecl.sym.members().enter(recField);
@@ -211,20 +212,23 @@
         samMethodDecl.params = params.toList();
 
         JCExpression rec = null;
-        if (localContext.isInstanceRef()) {
-            rec = localContext.isSpecial() ?
-                    null :
-                    make.Ident(capturedFields.toList().head.sym);
-        } else if (tree.isUnbound) {
-            rec = make.Ident(params.toList().head.sym);
-        } else {
-            rec = tree.mode == ReferenceMode.INVOKE ?
+        switch (tree.kind) {
+            case BOUND:
+                rec = make.Ident(capturedFields.toList().head.sym);
+                break;
+            case SUPER: break;
+            case UNBOUND:
+            case UNBOUND_INNER:
+                rec = make.Ident(params.toList().head.sym);
+                break;
+            default:
+                rec = tree.mode == ReferenceMode.INVOKE ?
                     make.Type(refSym.owner.type) : null;
         }
 
         ListBuffer<JCExpression> args = ListBuffer.lb();
         for (JCVariableDecl param : params) {
-            if (param == params.first() && tree.isUnbound) continue;
+            if (param == params.first() && tree.kind.isUnbound()) continue;
             args.append(make.Ident(param.sym));
         }
         JCExpression ref_call = null;
@@ -254,7 +258,7 @@
 
         ListBuffer<JCExpression> syntheticInits = ListBuffer.lb();
 
-        if (localContext.isInstanceRef() && !localContext.isSpecial()) {
+        if (tree.hasKind(ReferenceKind.BOUND)) {
             syntheticInits.append(localContext.tree.getQualifierExpression());
         }
 
@@ -270,7 +274,7 @@
         
         //if we had a static reference with non-static qualifier, add a let
         //expression to force the evaluation of the qualifier expr
-        if (localContext.needsReceiverEval()) {
+        if (tree.hasKind(ReferenceKind.STATIC_EVAL)) {
             VarSymbol recVar = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner);
             JCVariableDecl recDef = make.VarDef(recVar, tree.getQualifierExpression());
             result = make.LetExpr(recDef, result).setType(tree.type);
@@ -445,10 +449,11 @@
 
             ReferenceToInnerTranslationContext(JCMemberReference tree) {
                 super(tree);
-                long flags = isSpecial() || isImplicitInner() ? 0 : STATIC;
+                long flags = tree.hasKind(ReferenceKind.SUPER) ||
+                        tree.hasKind(ReferenceKind.IMPLICIT_INNER) ? 0 : STATIC;
                 this.referenceClassSym = makeFunctionalClassSym(flags, tree.targetType, owner);
                 this.translatedSym = makeFunctionalDescriptorSym(tree.targetType, referenceClassSym);
-                if (isSpecial()) {
+                if (tree.hasKind(ReferenceKind.SUPER)) {
                     this.bridgeSym = makeSyntheticMethod(0, "$bridge$" + tree.pos, translatedSym.type, owner.enclClass());
                 }
             }   
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Tue Nov 29 18:12:54 2011 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Wed Nov 30 16:51:10 2011 +0000
@@ -33,6 +33,7 @@
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
 import com.sun.tools.javac.comp.LambdaTranslator.LambdaAnalyzer;
 import com.sun.tools.javac.comp.LambdaToMethod.LambdaToMethodAnalyzer.*;
 import com.sun.tools.javac.util.*;
@@ -192,14 +193,18 @@
 
         //third, determine the arguments to the indy call
         JCExpression qualifierExpr = null;
-        if (localContext.needsBridge() && (localContext.isSpecial() || localContext.isImplicitInner())) {
-            VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
+        switch (tree.kind) {
+            case SUPER:
+            case IMPLICIT_INNER:
+                VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
                 names._this,
                 localContext.owner.enclClass().type, localContext.owner);
-            JCIdent _thisRef = (JCIdent)make.Ident(_this).setType(localContext.owner.enclClass().type);
-            qualifierExpr = _thisRef;
-        } else if (localContext.isInstanceRef()) {
-            qualifierExpr = tree.getQualifierExpression();
+                JCIdent _thisRef = (JCIdent)make.Ident(_this).setType(localContext.owner.enclClass().type);
+                qualifierExpr = _thisRef;
+                break;
+            case BOUND:
+                qualifierExpr = tree.getQualifierExpression();
+                break;
         }
 
         List<JCExpression> indy_args = List.of(Bool(false));
@@ -221,7 +226,7 @@
 
         //if we had a static reference with non-static qualifier, add a let
         //expression to force the evaluation of the qualifier expr
-        if (localContext.needsReceiverEval()) {
+        if (tree.hasKind(ReferenceKind.STATIC_EVAL)) {
             VarSymbol rec = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner);
             JCVariableDecl recDef = make.VarDef(rec, tree.getQualifierExpression());
             result = make.LetExpr(recDef, result).setType(tree.type);
@@ -313,7 +318,7 @@
         for (Type p : samDesc.getParameterTypes()) {
             VarSymbol vsym = new VarSymbol(0, names.fromString("x$" + i), p, localContext.bridgeSym);
             params.append(make.VarDef(vsym, null));
-            if (!tree.isUnbound || i != 0) {
+            if (!tree.kind.isUnbound() || i != 0) {
                 args.append(make.Ident(vsym));
             }
             i++;
@@ -321,16 +326,20 @@
         //an extra argument is prepended to the signature of the bridge in case
         //the member reference is an instance method reference (in which case
         //the receiver expression is passed to the bridge itself).
-        if ((localContext.isInstanceRef() && !localContext.isSpecial()) || localContext.isImplicitInner()) {
-            Type recType = localContext.isImplicitInner() ?
-                    tree.sym.owner.type.getEnclosingType() :
-                    tree.getQualifierExpression().type;
+        Type recType = null;
+        switch (tree.kind) {
+            case IMPLICIT_INNER:
+                recType = tree.sym.owner.type.getEnclosingType(); break;
+            case BOUND:
+                recType = tree.getQualifierExpression().type; break;
+        }
+        if (recType != null) {
             VarSymbol vsym = new VarSymbol(0, names.fromString("rec$" + i), recType, localContext.bridgeSym);
             params.prepend(make.VarDef(vsym, null));
         }
-
+        
         //generate the bridge method declaration
-        JCMethodDecl bridgeDecl = make.MethodDef(make.Modifiers((localContext.isSpecial() ? 0 : STATIC) | SYNTHETIC),
+        JCMethodDecl bridgeDecl = make.MethodDef(make.Modifiers(localContext.bridgeSym.flags()),
                 localContext.bridgeSym.name,
                 make.QualIdent(samDesc.getReturnType().tsym),
                 List.<JCTypeParameter>nil(),
@@ -351,14 +360,17 @@
             //qualifier expression is never used here, as it might refer to symbols
             //not available in the static context of the bridge
             JCExpression qualifier = null;
-            if (localContext.isSpecial()) {
-                qualifier = tree.getQualifierExpression();
-            }
-            else if (tree.isUnbound || localContext.isInstanceRef()) {
-                qualifier = make.Ident(params.first());
-            } else {
-                Assert.check(tree.sym.isStatic());
-                qualifier = make.Type(tree.sym.owner.type);
+            switch (tree.kind) {
+                case SUPER:
+                    qualifier = tree.getQualifierExpression();
+                    break;
+                case UNBOUND:
+                case BOUND:
+                    qualifier = make.Ident(params.first());
+                    break;
+                default:
+                    Assert.check(tree.sym.isStatic());
+                    qualifier = make.Type(tree.sym.owner.type);    
             }
 
             //create the qualifier expression
@@ -382,7 +394,13 @@
         } else {
             //the enclosing expression is either 'null' (no enclosing type) or
             //set to the first bridge synthetic parameter
-            JCExpression encl = tree.isUnbound || localContext.isImplicitInner() ? make.Ident(params.first()) : null;
+            JCExpression encl = null;
+            switch (tree.kind) {
+                case UNBOUND:
+                case UNBOUND_INNER:
+                case IMPLICIT_INNER:
+                    encl = make.Ident(params.first());
+            }
 
             //create the instance creation expression
             JCNewClass newClass = make.NewClass(encl,
@@ -400,7 +418,7 @@
             bridgeDecl.body = make.Block(0, List.<JCStatement>of(make.Return(newClass)));
         }
 
-        if (localContext.isSpecial()) {
+        if (tree.hasKind(ReferenceKind.SUPER)) {
             trans_instance = trans_instance.prepend(bridgeDecl);
         } else {
             trans_static = trans_static.prepend(bridgeDecl);
@@ -531,9 +549,10 @@
             ReferenceToMethodTranslationContext(JCMemberReference tree) {
                 super(tree);
                 if (needsBridge()) {
-                    this.bridgeSym = makeSyntheticMethod(isSpecial() ? 0 : STATIC,
+                    boolean isSuper = tree.hasKind(ReferenceKind.SUPER);
+                    this.bridgeSym = makeSyntheticMethod(isSuper ? 0 : STATIC,
                             lambdaName().append(names.fromString("$bridge")), null,
-                            isSpecial() ? owner.enclClass() : owner.outermostClass());
+                            isSuper ? owner.enclClass() : owner.outermostClass());
                 }
             }
 
@@ -542,9 +561,7 @@
              */
             int referenceKind() {
                 Symbol refSym = needsBridge() ? bridgeSym : tree.sym;
-                if (tree.getQualifierExpression().getTag() == JCTree.IDENT && !needsBridge() && isSpecial()) {
-                    return Pool.MemberReference.specialRefKind(refSym.isConstructor());
-                } else if (refSym.isConstructor()) {
+                if (refSym.isConstructor()) {
                     return Pool.MemberReference.specialRefKind(refSym.isConstructor());
                 } else {
                     return Pool.MemberReference.methodRefKind(refSym.isStatic(), refSym.enclClass().isInterface());
@@ -563,7 +580,15 @@
              * descriptor
              */
             protected boolean needsBridge() {
-                return sigMismatch() || tree.isUnbound || isSpecial() || isImplicitInner();
+                switch (tree.kind) {
+                    case UNBOUND:
+                    case UNBOUND_INNER:
+                    case SUPER:
+                    case IMPLICIT_INNER:
+                        return true;
+                    default:
+                        return sigMismatch();
+                }
             }
             
             protected Type generatedRefSig() {
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Tue Nov 29 18:12:54 2011 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Wed Nov 30 16:51:10 2011 +0000
@@ -751,41 +751,6 @@
             protected ReferenceTranslationContext(JCMemberReference tree) {
                 super(tree);
             }
-
-            /**
-             * Is this an instance method reference with a non-static qualifier?
-             */
-            boolean isInstanceRef() {
-                return tree.getMode() == ReferenceMode.INVOKE &&
-                        !TreeInfo.isStaticSelector(tree.getQualifierExpression(), names) &&
-                        !tree.sym.isStatic();
-            }
-
-            /**
-             * Is this a static reference with a non-static qualifier (which needs
-             * to be evaluated separately) ?
-             */
-            boolean needsReceiverEval() {
-                return tree.getMode() == ReferenceMode.INVOKE &&
-                    !TreeInfo.isStaticSelector(tree.getQualifierExpression(), names) &&
-                    tree.sym.isStatic();
-            }
-
-            /**
-             * Is this a static reference with a non-static qualifier (which needs
-             * to be evaluated separately) ?
-             */
-            boolean isSpecial() {
-                Name name = TreeInfo.name(tree.getQualifierExpression());
-                return !tree.sym.isStatic() &&
-                        name != null &&
-                        (name == names._super || name == names._this);
-            }
-            
-            boolean isImplicitInner() {
-                return !tree.isUnbound &&
-                        tree.sym.owner.type.getEnclosingType().tag != TypeTags.NONE;
-            }
         }
         // </editor-fold>
     }
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Tue Nov 29 18:12:54 2011 +0000
+++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Wed Nov 30 16:51:10 2011 +0000
@@ -1792,12 +1792,47 @@
      */
     public static class JCMemberReference extends JCExpression implements MemberReferenceTree {
         public ReferenceMode mode;
+        public ReferenceKind kind;
         public Name name;
         public JCExpression expr;
         public List<JCExpression> typeargs;
         public Type targetType;
         public Symbol sym;
-        public boolean isUnbound;
+        
+        /**
+         * Javac-dependent classification for member references, based
+         * on relevant properties w.r.t. code-generation
+         */
+        public enum ReferenceKind {
+            /** super # instMethod */
+            SUPER(ReferenceMode.INVOKE, false),
+            /** Type # instMethod */
+            UNBOUND(ReferenceMode.INVOKE, true),
+            /** Type # staticMethod */
+            STATIC(ReferenceMode.INVOKE, false),
+            /** Expr # instMethod */
+            BOUND(ReferenceMode.INVOKE, false),
+            /** Expr # staticMethod */
+            STATIC_EVAL(ReferenceMode.INVOKE, false),
+            /** Outer.Inner # new */
+            UNBOUND_INNER(ReferenceMode.NEW, true),
+            /** Inner # new */
+            IMPLICIT_INNER(ReferenceMode.NEW, false),
+            /** Toplevel # new */
+            TOPLEVEL(ReferenceMode.NEW, false);
+            
+            ReferenceMode mode;
+            boolean unbound;
+
+            private ReferenceKind(ReferenceMode mode, boolean unbound) {
+                this.mode = mode;
+                this.unbound = unbound;
+            }
+            
+            public boolean isUnbound() {
+                return unbound;
+            }
+        }
 
         protected JCMemberReference(ReferenceMode mode, Name name, JCExpression expr, List<JCExpression> typeargs) {
             this.mode = mode;
@@ -1826,6 +1861,9 @@
         public int getTag() {
             return REFERENCE;
         }
+        public boolean hasKind(ReferenceKind kind) {
+            return this.kind == kind;
+        }
     }
 
     /**