changeset 1464:0e71dd95f7ef

Lambda compilation: move translatedSym completion into translation context. Misc clean-up. Documentation
author robert.field@oracle.com
date Wed, 26 Sep 2012 22:29:05 -0700
parents e23bb5d64f58
children a5521ef3db10
files src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
diffstat 1 files changed, 80 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Tue Sep 25 14:45:58 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Wed Sep 26 22:29:05 2012 -0700
@@ -80,6 +80,12 @@
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="visitor methods">
+    /**
+     * Visit a class.  
+     * Maintain the translatedMethodList across nested classes.
+     * Append the translatedMethodList to the class after it is translated.
+     * @param tree 
+     */
     @Override
     public void visitClassDef(JCClassDecl tree) {
         if (tree.sym.owner.kind == PCK) {
@@ -101,75 +107,44 @@
         }
     }
 
+    /**
+     * Translate a lambda into a method to be inserted into the class.
+     * Then replace the lambda site with an invokedynamic call of to lambda 
+     * meta-factory, which will use the lambda method.
+     * @param tree 
+     */
     @Override
     public void visitLambda(JCLambda tree) {
-        //Step One:
-        //translate the lambda expression into a static method. The signature of
-        //the static method is augmented with the following synthetic parameters:
-        //
-        //1) reference to enclosing contexts captured by the lambda expression
-        //2) enclosing locals captured by the lambda expression
-        //3) reference to self (for recursive lambdas only)
-        //
-        //As the lambda body is translated, all references to lambda locals,
-        //captured variables, enclosing members are adjusted accordingly
-        //to refer to the static method parameters (rather than i.e. acessing to
-        //captured members directly).
+        LambdaToMethodTranslationContext localContext = (LambdaToMethodTranslationContext)context;
+        MethodSymbol sym = (MethodSymbol)localContext.translatedSym;
+        MethodType lambdaType = (MethodType) sym.type;
+        boolean isStatic = sym.isStatic();
 
-        LambdaToMethodTranslationContext localContext = (LambdaToMethodTranslationContext)context;
-        boolean inInterface = localContext.translatedSym.owner.isInterface();
-        boolean isBound = !localContext.getSymbolMap(CAPTURED_THIS).isEmpty() || inInterface;
-        
-        // @@@ flag fix-up -- Robert, clean this up
-        if (isBound) {
-            // Need access to implicit or explicit 'this'
-            localContext.translatedSym.flags_field &= ~STATIC;
-        }
-        if (inInterface) {
-            // Interface methods much public default methods
-            localContext.translatedSym.flags_field |= PUBLIC | DEFENDER;
-        } else {
-            // All other introduced methods can be private
-            localContext.translatedSym.flags_field |= PRIVATE;
-        }
-
-        //compute synthetic params
-        ListBuffer<JCVariableDecl> syntheticParams = ListBuffer.lb();
-
-        //add cap$n and $n if needed
-        for (Symbol thisSym : localContext.getSymbolMap(CAPTURED_VAR, PARAM).values()) {
-            syntheticParams.append(make.VarDef((VarSymbol)thisSym, null));
-        }
-
-        //prepend synthetic args to translated lambda method signature
-        MethodType lambdaType = (MethodType)localContext.generatedLambdaSig();
-        localContext.translatedSym.type = lambdaType = (MethodType)types.createMethodTypeWithParameters(lambdaType, TreeInfo.types(syntheticParams.toList()));
-
-        //create method declaration hoisting the lambda body
-
-        long mods = SYNTHETIC;
-        if (!isBound) {
-            mods |= STATIC;
-        }
+        //create the method declaration hoisting the lambda body
+        long mods = isStatic? (STATIC | SYNTHETIC) : (SYNTHETIC);
         JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(mods),
-                localContext.translatedSym.name,
+                sym.name,
                 make.QualIdent(lambdaType.getReturnType().tsym),
                 List.<JCTypeParameter>nil(),
-                syntheticParams.toList(),
+                localContext.syntheticParams,
                 lambdaType.getThrownTypes() == null ?
                     List.<JCExpression>nil() :
                     make.Types(lambdaType.getThrownTypes()),
                 null,
                 null);
-        lambdaDecl.sym = (MethodSymbol)localContext.translatedSym;
+        lambdaDecl.sym = sym;
         lambdaDecl.type = lambdaType;
 
         //translate lambda body
+        //As the lambda body is translated, all references to lambda locals,
+        //captured variables, enclosing members are adjusted accordingly
+        //to refer to the static method parameters (rather than i.e. acessing to
+        //captured members directly).
         lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
 
+        //Add the method to the list of methods to be added to this class.
         translatedMethodList = translatedMethodList.prepend(lambdaDecl);
 
-        //Step Two:
         //now that we have generated a method for the lambda expression,
         //we can translate the lambda into a method reference pointing to the newly
         //created method.
@@ -178,12 +153,12 @@
         //signature of the SAM descriptor - this means that the method reference
         //should be added the following synthetic arguments:
         //
-        //1) reference to enclosing contexts captured by the lambda expression
-        //2) enclosing locals captured by the lambda expression
+        // * the "this" argument if it is an instance method
+        // * enclosing locals captured by the lambda expression
 
         ListBuffer<JCExpression> syntheticInits = ListBuffer.lb();
 
-        if (isBound) {
+        if (!isStatic) {
             syntheticInits.append(makeThis(
                     lambdaDecl.sym.owner.asType(),
                     localContext.owner));
@@ -201,9 +176,10 @@
         List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
 
         //build a sam instance using an indy call to the meta-factory
-        int refKind = Pool.MemberReference.methodRefKind(!isBound, localContext.translatedSym.enclClass().isInterface());
+        int refKind = Pool.MemberReference.methodRefKind(isStatic, sym.enclClass().isInterface());
                 
-        result = makeMetaFactoryIndyCall(tree, tree.targetType, refKind, localContext.translatedSym, indy_args);
+        //convert to an invokedynamic call 
+        result = makeMetaFactoryIndyCall(tree, tree.targetType, refKind, sym, indy_args);
     }
 
     private JCIdent makeThis(Type type, Symbol owner) {
@@ -214,6 +190,11 @@
         return make.Ident(_this);
     }
 
+    /**
+     * Translate a method reference into an invokedynamic call to the 
+     * meta-factory.
+     * @param tree 
+     */
     @Override
     public void visitReference(JCMemberReference tree) {
         ReferenceToMethodTranslationContext localContext = (ReferenceToMethodTranslationContext)context;
@@ -607,6 +588,13 @@
         }
 
         @Override
+        public void visitLambda(JCLambda tree) {
+            super.visitLambda(tree);
+            LambdaToMethodTranslationContext context = (LambdaToMethodTranslationContext)contextMap.get(tree);
+            context.complete();
+        }
+
+        @Override
         public void visitClassDef(JCClassDecl tree) {
             super.visitClassDef(tree);
             if (frameStack.nonEmpty() && enclosingLambda() != null) {
@@ -682,10 +670,12 @@
         };
 
         class LambdaToMethodTranslationContext extends LambdaTranslationContext {
+            
+            List<JCVariableDecl> syntheticParams;
 
             LambdaToMethodTranslationContext(JCLambda tree) {
                 super(tree);
-                this.translatedSym = makeSyntheticMethod(STATIC, lambdaName(), null, owner.enclClass());
+                this.translatedSym = makeSyntheticMethod(0, lambdaName(), null, owner.enclClass());
             }
 
             @Override
@@ -696,6 +686,38 @@
                     return makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym);
                 }
             }
+            
+            void complete() {
+                if (syntheticParams != null) {
+                    return;
+                }
+                boolean inInterface = translatedSym.owner.isInterface();
+                boolean thisReferenced = !getSymbolMap(CAPTURED_THIS).isEmpty();
+                boolean needInstance = thisReferenced || inInterface;
+                
+                // If instance access isn't needed, make it static
+                // Interface methods much be public default methods, otherwise make it private
+                translatedSym.flags_field = (needInstance? 0 : STATIC) | (inInterface? PUBLIC | DEFENDER : PRIVATE);
+
+                //compute synthetic params
+                ListBuffer<JCVariableDecl> params = ListBuffer.lb();
+
+                // The signature of the method is augmented with the following 
+                // synthetic parameters:
+                //
+                // 1) reference to enclosing contexts captured by the lambda expression
+                // 2) enclosing locals captured by the lambda expression
+                for (Symbol thisSym : getSymbolMap(CAPTURED_VAR, PARAM).values()) {
+                    params.append(make.VarDef((VarSymbol) thisSym, null));
+                }
+                
+                syntheticParams = params.toList();
+
+                //prepend synthetic args to translated lambda method signature
+                translatedSym.type = (MethodType) types.createMethodTypeWithParameters(
+                        (MethodType) generatedLambdaSig(), 
+                        TreeInfo.types(syntheticParams));
+            }
 
             @Override
             protected Type enclosingType() {
@@ -703,7 +725,7 @@
                 return owner.enclClass().type;
             }
 
-            protected Type generatedLambdaSig() {
+            private Type generatedLambdaSig() {
                 return types.erasure(types.findDescriptorType(tree.targetType));
             }
         }