langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
changeset 18393 3672b286337e
parent 18386 174879d5b5d0
child 18412 d0e713f5cabd
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Mon Jun 17 14:46:01 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Mon Jun 17 20:29:31 2013 -0700
@@ -100,6 +100,9 @@
     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
     public static final int FLAG_MARKERS = 1 << 1;
 
+    /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
+    public static final int FLAG_BRIDGES = 1 << 2;
+
     private class KlassInfo {
 
         /**
@@ -321,7 +324,7 @@
         int refKind = referenceKind(sym);
 
         //convert to an invokedynamic call
-        result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args);
+        result = makeMetaFactoryIndyCall(context, refKind, sym, indy_args);
     }
 
     private JCIdent makeThis(Type type, Symbol owner) {
@@ -382,7 +385,7 @@
 
 
         //build a sam instance using an indy call to the meta-factory
-        result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args);
+        result = makeMetaFactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
     }
 
     /**
@@ -908,10 +911,11 @@
     /**
      * Generate an indy method call to the meta factory
      */
-    private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory,
-            boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) {
+    private JCExpression makeMetaFactoryIndyCall(TranslationContext<?> context,
+            int refKind, Symbol refSym, List<JCExpression> indy_args) {
+        JCFunctionalExpression tree = context.tree;
         //determine the static bsm args
-        Type mtype = types.erasure(tree.descriptorType);
+        Type mtype = types.erasure(tree.getDescriptorType(types));
         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
         List<Object> staticArgs = List.<Object>of(
                 new Pool.MethodHandle(ClassFile.REF_invokeInterface,
@@ -934,25 +938,40 @@
                 List.<Type>nil(),
                 syms.methodClass);
 
-        Name metafactoryName = needsAltMetafactory ?
+        Name metafactoryName = context.needsAltMetafactory() ?
                 names.altMetaFactory : names.metaFactory;
 
-        if (needsAltMetafactory) {
+        if (context.needsAltMetafactory()) {
             ListBuffer<Object> markers = ListBuffer.lb();
-            for (Symbol t : tree.targets.tail) {
-                if (t != syms.serializableType.tsym) {
-                    markers.append(t);
+            for (Type t : tree.targets.tail) {
+                if (t.tsym != syms.serializableType.tsym) {
+                    markers.append(t.tsym);
                 }
             }
-            int flags = isSerializable? FLAG_SERIALIZABLE : 0;
+            int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
             boolean hasMarkers = markers.nonEmpty();
-            flags |= hasMarkers ? FLAG_MARKERS : 0;
+            boolean hasBridges = context.bridges.nonEmpty();
+            if (hasMarkers) {
+                flags |= FLAG_MARKERS;
+            }
+            if (hasBridges) {
+                flags |= FLAG_BRIDGES;
+            }
             staticArgs = staticArgs.append(flags);
             if (hasMarkers) {
                 staticArgs = staticArgs.append(markers.length());
                 staticArgs = staticArgs.appendList(markers.toList());
             }
-            if (isSerializable) {
+            if (hasBridges) {
+                staticArgs = staticArgs.append(context.bridges.length() - 1);
+                for (Symbol s : context.bridges) {
+                    Type s_erasure = s.erasure(types);
+                    if (!types.isSameType(s_erasure, samSym.erasure(types))) {
+                        staticArgs = staticArgs.append(s.erasure(types));
+                    }
+                }
+            }
+            if (context.isSerializable()) {
                 addDeserializationCase(refKind, refSym, tree.type, samSym,
                         tree, staticArgs, indyType);
             }
@@ -1299,7 +1318,6 @@
 
                 // Make lambda holding the new-class call
                 JCLambda slam = make.Lambda(params, nc);
-                slam.descriptorType = tree.descriptorType;
                 slam.targets = tree.targets;
                 slam.type = tree.type;
                 slam.pos = tree.pos;
@@ -1634,23 +1652,30 @@
             /** the enclosing translation context (set for nested lambdas/mref) */
             TranslationContext<?> prev;
 
+            /** list of methods to be bridged by the meta-factory */
+            List<Symbol> bridges;
+
             TranslationContext(T tree) {
                 this.tree = tree;
                 this.owner = owner();
                 this.depth = frameStack.size() - 1;
                 this.prev = context();
+                ClassSymbol csym =
+                        types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.targets, ABSTRACT | INTERFACE);
+                this.bridges = types.functionalInterfaceBridges(csym);
             }
 
             /** does this functional expression need to be created using alternate metafactory? */
             boolean needsAltMetafactory() {
-                return (tree.targets.length() > 1 ||
-                        isSerializable());
+                return tree.targets.length() > 1 ||
+                        isSerializable() ||
+                        bridges.length() > 1;
             }
 
             /** does this functional expression require serialization support? */
             boolean isSerializable() {
-                for (Symbol target : tree.targets) {
-                    if (types.asSuper(target.type, syms.serializableType.tsym) != null) {
+                for (Type target : tree.targets) {
+                    if (types.asSuper(target, syms.serializableType.tsym) != null) {
                         return true;
                     }
                 }
@@ -1833,7 +1858,7 @@
             }
 
             Type generatedLambdaSig() {
-                return types.erasure(tree.descriptorType);
+                return types.erasure(tree.getDescriptorType(types));
             }
         }
 
@@ -1909,7 +1934,7 @@
             }
 
             Type bridgedRefSig() {
-                return types.erasure(types.findDescriptorSymbol(tree.targets.head).type);
+                return types.erasure(types.findDescriptorSymbol(tree.targets.head.tsym).type);
             }
         }
     }