src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java

changeset 1882
39ec5d8a691b
parent 1843
be62183f938a
child 1940
b8610a65fbf9
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Jul 11 10:13:57 2013 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Jul 11 14:07:39 2013 +0100
     1.3 @@ -100,6 +100,9 @@
     1.4      /** Flag for alternate metafactories indicating the lambda object has multiple targets */
     1.5      public static final int FLAG_MARKERS = 1 << 1;
     1.6  
     1.7 +    /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
     1.8 +    public static final int FLAG_BRIDGES = 1 << 2;
     1.9 +
    1.10      private class KlassInfo {
    1.11  
    1.12          /**
    1.13 @@ -321,7 +324,7 @@
    1.14          int refKind = referenceKind(sym);
    1.15  
    1.16          //convert to an invokedynamic call
    1.17 -        result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args);
    1.18 +        result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
    1.19      }
    1.20  
    1.21      private JCIdent makeThis(Type type, Symbol owner) {
    1.22 @@ -382,7 +385,7 @@
    1.23  
    1.24  
    1.25          //build a sam instance using an indy call to the meta-factory
    1.26 -        result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args);
    1.27 +        result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
    1.28      }
    1.29  
    1.30      /**
    1.31 @@ -606,8 +609,8 @@
    1.32                  make.Return(makeIndyCall(
    1.33                      pos,
    1.34                      syms.lambdaMetafactory,
    1.35 -                    names.altMetaFactory,
    1.36 -                    staticArgs, indyType, serArgs.toList())),
    1.37 +                    names.altMetafactory,
    1.38 +                    staticArgs, indyType, serArgs.toList(), samSym.name)),
    1.39                  null);
    1.40          ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
    1.41          if (stmts == null) {
    1.42 @@ -905,22 +908,26 @@
    1.43          kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge());
    1.44      }
    1.45  
    1.46 +    private MethodType typeToMethodType(Type mt) {
    1.47 +        Type type = types.erasure(mt);
    1.48 +        return new MethodType(type.getParameterTypes(),
    1.49 +                        type.getReturnType(),
    1.50 +                        type.getThrownTypes(),
    1.51 +                        syms.methodClass);
    1.52 +    }
    1.53 +
    1.54      /**
    1.55       * Generate an indy method call to the meta factory
    1.56       */
    1.57 -    private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory,
    1.58 -            boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) {
    1.59 +    private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context,
    1.60 +            int refKind, Symbol refSym, List<JCExpression> indy_args) {
    1.61 +        JCFunctionalExpression tree = context.tree;
    1.62          //determine the static bsm args
    1.63 -        Type mtype = types.erasure(tree.descriptorType);
    1.64          MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
    1.65          List<Object> staticArgs = List.<Object>of(
    1.66 -                new Pool.MethodHandle(ClassFile.REF_invokeInterface,
    1.67 -                    types.findDescriptorSymbol(tree.type.tsym), types),
    1.68 +                typeToMethodType(samSym.type),
    1.69                  new Pool.MethodHandle(refKind, refSym, types),
    1.70 -                new MethodType(mtype.getParameterTypes(),
    1.71 -                        mtype.getReturnType(),
    1.72 -                        mtype.getThrownTypes(),
    1.73 -                        syms.methodClass));
    1.74 +                typeToMethodType(tree.getDescriptorType(types)));
    1.75  
    1.76          //computed indy arg types
    1.77          ListBuffer<Type> indy_args_types = ListBuffer.lb();
    1.78 @@ -934,31 +941,46 @@
    1.79                  List.<Type>nil(),
    1.80                  syms.methodClass);
    1.81  
    1.82 -        Name metafactoryName = needsAltMetafactory ?
    1.83 -                names.altMetaFactory : names.metaFactory;
    1.84 +        Name metafactoryName = context.needsAltMetafactory() ?
    1.85 +                names.altMetafactory : names.metafactory;
    1.86  
    1.87 -        if (needsAltMetafactory) {
    1.88 +        if (context.needsAltMetafactory()) {
    1.89              ListBuffer<Object> markers = ListBuffer.lb();
    1.90 -            for (Symbol t : tree.targets.tail) {
    1.91 -                if (t != syms.serializableType.tsym) {
    1.92 -                    markers.append(t);
    1.93 +            for (Type t : tree.targets.tail) {
    1.94 +                if (t.tsym != syms.serializableType.tsym) {
    1.95 +                    markers.append(t.tsym);
    1.96                  }
    1.97              }
    1.98 -            int flags = isSerializable? FLAG_SERIALIZABLE : 0;
    1.99 +            int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
   1.100              boolean hasMarkers = markers.nonEmpty();
   1.101 -            flags |= hasMarkers ? FLAG_MARKERS : 0;
   1.102 +            boolean hasBridges = context.bridges.nonEmpty();
   1.103 +            if (hasMarkers) {
   1.104 +                flags |= FLAG_MARKERS;
   1.105 +            }
   1.106 +            if (hasBridges) {
   1.107 +                flags |= FLAG_BRIDGES;
   1.108 +            }
   1.109              staticArgs = staticArgs.append(flags);
   1.110              if (hasMarkers) {
   1.111                  staticArgs = staticArgs.append(markers.length());
   1.112                  staticArgs = staticArgs.appendList(markers.toList());
   1.113              }
   1.114 -            if (isSerializable) {
   1.115 +            if (hasBridges) {
   1.116 +                staticArgs = staticArgs.append(context.bridges.length() - 1);
   1.117 +                for (Symbol s : context.bridges) {
   1.118 +                    Type s_erasure = s.erasure(types);
   1.119 +                    if (!types.isSameType(s_erasure, samSym.erasure(types))) {
   1.120 +                        staticArgs = staticArgs.append(s.erasure(types));
   1.121 +                    }
   1.122 +                }
   1.123 +            }
   1.124 +            if (context.isSerializable()) {
   1.125                  addDeserializationCase(refKind, refSym, tree.type, samSym,
   1.126                          tree, staticArgs, indyType);
   1.127              }
   1.128          }
   1.129  
   1.130 -        return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args);
   1.131 +        return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name);
   1.132      }
   1.133  
   1.134      /**
   1.135 @@ -966,7 +988,8 @@
   1.136       * arguments types
   1.137       */
   1.138      private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
   1.139 -            List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs) {
   1.140 +            List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
   1.141 +            Name methName) {
   1.142          int prevPos = make.pos;
   1.143          try {
   1.144              make.at(pos);
   1.145 @@ -978,7 +1001,7 @@
   1.146                      bsmName, bsm_staticArgs, List.<Type>nil());
   1.147  
   1.148              DynamicMethodSymbol dynSym =
   1.149 -                    new DynamicMethodSymbol(names.lambda,
   1.150 +                    new DynamicMethodSymbol(methName,
   1.151                                              syms.noSymbol,
   1.152                                              bsm.isStatic() ?
   1.153                                                  ClassFile.REF_invokeStatic :
   1.154 @@ -1299,7 +1322,6 @@
   1.155  
   1.156                  // Make lambda holding the new-class call
   1.157                  JCLambda slam = make.Lambda(params, nc);
   1.158 -                slam.descriptorType = tree.descriptorType;
   1.159                  slam.targets = tree.targets;
   1.160                  slam.type = tree.type;
   1.161                  slam.pos = tree.pos;
   1.162 @@ -1634,23 +1656,30 @@
   1.163              /** the enclosing translation context (set for nested lambdas/mref) */
   1.164              TranslationContext<?> prev;
   1.165  
   1.166 +            /** list of methods to be bridged by the meta-factory */
   1.167 +            List<Symbol> bridges;
   1.168 +
   1.169              TranslationContext(T tree) {
   1.170                  this.tree = tree;
   1.171                  this.owner = owner();
   1.172                  this.depth = frameStack.size() - 1;
   1.173                  this.prev = context();
   1.174 +                ClassSymbol csym =
   1.175 +                        types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.targets, ABSTRACT | INTERFACE);
   1.176 +                this.bridges = types.functionalInterfaceBridges(csym);
   1.177              }
   1.178  
   1.179              /** does this functional expression need to be created using alternate metafactory? */
   1.180              boolean needsAltMetafactory() {
   1.181 -                return (tree.targets.length() > 1 ||
   1.182 -                        isSerializable());
   1.183 +                return tree.targets.length() > 1 ||
   1.184 +                        isSerializable() ||
   1.185 +                        bridges.length() > 1;
   1.186              }
   1.187  
   1.188              /** does this functional expression require serialization support? */
   1.189              boolean isSerializable() {
   1.190 -                for (Symbol target : tree.targets) {
   1.191 -                    if (types.asSuper(target.type, syms.serializableType.tsym) != null) {
   1.192 +                for (Type target : tree.targets) {
   1.193 +                    if (types.asSuper(target, syms.serializableType.tsym) != null) {
   1.194                          return true;
   1.195                      }
   1.196                  }
   1.197 @@ -1833,7 +1862,7 @@
   1.198              }
   1.199  
   1.200              Type generatedLambdaSig() {
   1.201 -                return types.erasure(tree.descriptorType);
   1.202 +                return types.erasure(tree.getDescriptorType(types));
   1.203              }
   1.204          }
   1.205  
   1.206 @@ -1909,7 +1938,7 @@
   1.207              }
   1.208  
   1.209              Type bridgedRefSig() {
   1.210 -                return types.erasure(types.findDescriptorSymbol(tree.targets.head).type);
   1.211 +                return types.erasure(types.findDescriptorSymbol(tree.targets.head.tsym).type);
   1.212              }
   1.213          }
   1.214      }

mercurial