changeset 1426:42a7a264130d lambda-b45

Handle raw type references to method references by sending the functional descriptor through the lambda meta factory protocol
author Robert Field <Robert.Field@oracle.com>
date Fri, 22 Jun 2012 00:00:59 -0700
parents 797a96145e71
children c7ad5276fd28 a37eb06c7db4
files 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
diffstat 3 files changed, 65 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Wed Jun 20 15:45:04 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Fri Jun 22 00:00:59 2012 -0700
@@ -517,38 +517,6 @@
         trans_instance = trans_instance.prepend(bridgeDecl);
         return bridgeDecl.sym;
     }
-    
-    private MethodSymbol makeFunctionalDescriptorSym(Type targetType, Symbol owner) {
-        MethodSymbol samDescriptor = types.findDescriptor(targetType.tsym);
-        MethodSymbol ms =  makeSyntheticMethod(samDescriptor.flags() & ~Flags.ABSTRACT,
-                samDescriptor.name,
-                types.memberType(targetType, samDescriptor),
-                owner);
-        ms.flags_field &= ~SYNTHETIC;
-        return ms;
-    }
-
-    private ClassSymbol makeFunctionalClassSym(long flags, Type targetType, Symbol owner) {
-        ClassSymbol functionalClassSym = new ClassSymbol(flags | Flags.SYNTHETIC, names.empty, null, owner);
-        functionalClassSym.sourcefile = owner.enclClass().sourcefile;
-
-        functionalClassSym.type = new ClassType(Type.noType,
-                List.<Type>nil(),
-                functionalClassSym);
-
-        enter.setEnclosingType(functionalClassSym, functionalClassSym.owner);
-
-        functionalClassSym.flatname = chk.localClassName(functionalClassSym);
-        chk.compiled.put(functionalClassSym.flatname, functionalClassSym);
-
-        functionalClassSym.members_field = new Scope(functionalClassSym);
-        
-        //supertype to be erased later (to allow transTypes to compute right set of bridge methods)
-        ((ClassType)functionalClassSym.type).supertype_field = syms.objectType;
-        ((ClassType)functionalClassSym.type).interfaces_field = List.of(targetType);
-
-        return functionalClassSym;
-    }
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Wed Jun 20 15:45:04 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Jun 22 00:00:59 2012 -0700
@@ -187,13 +187,9 @@
         //then, determine the arguments to the indy call
         List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
 
-        //first determine the static bsm args
-        List<Object> bsm_staticArgs = List.<Object>of(
-                new Pool.MemberReference(ClassFile.REF_invokeInterface, types.findDescriptor(tree.targetType.tsym)),
-                new Pool.MemberReference(isBound ? ClassFile.REF_invokeVirtual : ClassFile.REF_invokeStatic, localContext.translatedSym));
-
         //build a sam instance using an indy call to the meta-factory
-        result = makeMetaFactoryIndyCall(tree, bsm_staticArgs, indy_args);
+        int refKind = isBound ? ClassFile.REF_invokeVirtual : ClassFile.REF_invokeStatic;
+        result = makeMetaFactoryIndyCall(tree, tree.targetType, refKind, localContext.translatedSym, indy_args);
     }
 
     private JCIdent makeThis(Type type, Symbol owner) {
@@ -232,13 +228,9 @@
         //determine the arguments to the indy call
         List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
 
-        //determine the static bsm args
-        List<Object> bsm_staticArgs = List.<Object>of(
-                new Pool.MemberReference(ClassFile.REF_invokeInterface, types.findDescriptor(tree.targetType.tsym)),
-                new Pool.MemberReference(localContext.referenceKind(), refSym));
 
         //build a sam instance using an indy call to the meta-factory
-        result = makeMetaFactoryIndyCall(tree, bsm_staticArgs, indy_args);
+        result = makeMetaFactoryIndyCall(tree, tree.targetType, localContext.referenceKind(), refSym, indy_args);
 
         //if we had a static reference with non-static qualifier, add a let
         //expression to force the evaluation of the qualifier expr
@@ -280,15 +272,12 @@
             if (lambdaContext.getSymbolMap(PARAM).containsKey(tree.sym)) {
                 Symbol translatedSym = lambdaContext.getSymbolMap(PARAM).get(tree.sym);
                 result = make.Ident(translatedSym).setType(tree.type);
-                //System.err.printf("PARAM: tree.sym: %s  translated: %s\n", tree.sym, translatedSym);
             } else if (lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
                 Symbol translatedSym = lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym);
                 result = make.Ident(translatedSym).setType(tree.type);
-                //System.err.printf("LOCAL_VAR: tree.sym: %s  translated: %s\n", tree.sym, translatedSym);
             } else if (lambdaContext.getSymbolMap(CAPTURED_VAR).containsKey(tree.sym)) {
                 Symbol translatedSym = lambdaContext.getSymbolMap(CAPTURED_VAR).get(tree.sym);
                 result = make.Ident(translatedSym).setType(tree.type);
-                //System.err.printf("CAPTURED_VAR: tree.sym: %s  translated: %s\n", tree.sym, translatedSym);
             } else {
                 if (tree.sym.owner.kind == Kinds.TYP) {
                     for (Map.Entry<Symbol, Symbol> encl_entry : lambdaContext.getSymbolMap(CAPTURED_THIS).entrySet()) {
@@ -498,8 +487,17 @@
     /**
      * Generate an indy method call to the meta factory
      */
-    private JCExpression makeMetaFactoryIndyCall(JCExpression tree, List<Object> staticArgs, List<JCExpression> indy_args) {
-        //System.err.printf("makeMetaFactoryIndyCall staticArgs: %s\n  indyType: %s\n  indyArgs: %s\n", staticArgs, indyType, indyArgs);
+    private JCExpression makeMetaFactoryIndyCall(JCExpression tree, Type targetType, int refKind, Symbol refSym, List<JCExpression> indy_args) {
+        //determine the static bsm args
+        Type mtype = makeFunctionalDescriptorType(targetType);
+        List<Object> staticArgs = List.<Object>of(
+                new Pool.MemberReference(ClassFile.REF_invokeInterface, types.findDescriptor(targetType.tsym)),
+                new Pool.MemberReference(refKind, refSym),
+                new MethodType(mtype.getParameterTypes(),
+                        mtype.getReturnType(),
+                        mtype.getThrownTypes(),
+                        syms.methodClass));
+
         //computed enclosing "this" arg types
         ListBuffer<Type> indy_args_types = ListBuffer.lb();
         for (JCExpression arg : indy_args) {
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Wed Jun 20 15:45:04 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Fri Jun 22 00:00:59 2012 -0700
@@ -60,7 +60,9 @@
     protected Types types;
     protected TransTypes transTypes;
     protected Env<AttrContext> attrEnv;
-    
+    private Check chk;
+    private Enter enter;
+        
     /** the analyzer scanner */
     protected LambdaAnalyzer analyzer;
     
@@ -79,6 +81,8 @@
         types = Types.instance(context);
         transTypes = TransTypes.instance(context);
         this.analyzer = makeAnalyzer();
+        chk = Check.instance(context);
+        enter = Enter.instance(context);
     }
     
     protected abstract LambdaAnalyzer makeAnalyzer();
@@ -179,7 +183,6 @@
                     VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym);
                     JCVariableDecl varDef = make.VarDef(loc, tree.expr);
                     result = make.Block(0, List.<JCStatement>of(varDef, make.Return(null)));
-                    return;
                 } else if (!isTarget_void || !isLambda_void) {
                     //non-void to non-void conversion:
                     // return (TYPE)RET-EXPR;
@@ -298,6 +301,51 @@
         return transTypes.bridges(cdef, attrEnv);
     }
     // </editor-fold>
+
+    private MethodSymbol makeSamDescriptor(Type targetType) {
+        return types.findDescriptor(targetType.tsym);
+    }
+
+    private Type makeFunctionalDescriptorType(Type targetType, MethodSymbol samDescriptor) {
+        return types.erasure(types.memberType(targetType, samDescriptor));
+    }
+
+    protected Type makeFunctionalDescriptorType(Type targetType) {
+        return makeFunctionalDescriptorType(targetType, makeSamDescriptor(targetType));
+    }
+
+    protected MethodSymbol makeFunctionalDescriptorSym(Type targetType, Symbol owner) {
+        MethodSymbol samDescriptor = makeSamDescriptor(targetType);
+        MethodSymbol ms =  makeSyntheticMethod(samDescriptor.flags() & ~Flags.ABSTRACT,
+                samDescriptor.name,
+                makeFunctionalDescriptorType(targetType, samDescriptor),
+                owner);
+        ms.flags_field &= ~SYNTHETIC;
+        return ms;
+    }
+
+    protected ClassSymbol makeFunctionalClassSym(long flags, Type targetType, Symbol owner) {
+        ClassSymbol functionalClassSym = new ClassSymbol(flags | Flags.SYNTHETIC, names.empty, null, owner);
+        functionalClassSym.sourcefile = owner.enclClass().sourcefile;
+
+        functionalClassSym.type = new ClassType(Type.noType,
+                List.<Type>nil(),
+                functionalClassSym);
+
+        enter.setEnclosingType(functionalClassSym, functionalClassSym.owner);
+
+        functionalClassSym.flatname = chk.localClassName(functionalClassSym);
+        chk.compiled.put(functionalClassSym.flatname, functionalClassSym);
+
+        functionalClassSym.members_field = new Scope(functionalClassSym);
+        
+        //supertype to be erased later (to allow transTypes to compute right set of bridge methods)
+        ((ClassType)functionalClassSym.type).supertype_field = syms.objectType;
+        ((ClassType)functionalClassSym.type).interfaces_field = List.of(targetType);
+
+        return functionalClassSym;
+    }
+
     
     // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
     /*
@@ -508,7 +556,7 @@
                         if (localContext.tree.hasTag(LAMBDA)) {
                             JCTree block = capturedDecl(localContext.depth, tree.sym);
                             if (block == null) break;
-                            switch (block.getTag()) {                                
+                            switch (block.getTag()) {
                                 case CLASSDEF:
                                     JCClassDecl cdecl = (JCClassDecl)block;
                                     ((LambdaTranslationContext)localContext).addSymbol(cdecl.sym, CAPTURED_THIS);