langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
changeset 18730 95354d510139
parent 18412 d0e713f5cabd
child 19487 9097d88f5e1f
equal deleted inserted replaced
18729:89ecb9d4d654 18730:95354d510139
    98     public static final int FLAG_SERIALIZABLE = 1 << 0;
    98     public static final int FLAG_SERIALIZABLE = 1 << 0;
    99 
    99 
   100     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
   100     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
   101     public static final int FLAG_MARKERS = 1 << 1;
   101     public static final int FLAG_MARKERS = 1 << 1;
   102 
   102 
       
   103     /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
       
   104     public static final int FLAG_BRIDGES = 1 << 2;
       
   105 
   103     private class KlassInfo {
   106     private class KlassInfo {
   104 
   107 
   105         /**
   108         /**
   106          * list of methods to append
   109          * list of methods to append
   107          */
   110          */
   319 
   322 
   320         //build a sam instance using an indy call to the meta-factory
   323         //build a sam instance using an indy call to the meta-factory
   321         int refKind = referenceKind(sym);
   324         int refKind = referenceKind(sym);
   322 
   325 
   323         //convert to an invokedynamic call
   326         //convert to an invokedynamic call
   324         result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args);
   327         result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
   325     }
   328     }
   326 
   329 
   327     private JCIdent makeThis(Type type, Symbol owner) {
   330     private JCIdent makeThis(Type type, Symbol owner) {
   328         VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
   331         VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
   329                 names._this,
   332                 names._this,
   380 
   383 
   381         List<JCExpression> indy_args = init==null? List.<JCExpression>nil() : translate(List.of(init), localContext.prev);
   384         List<JCExpression> indy_args = init==null? List.<JCExpression>nil() : translate(List.of(init), localContext.prev);
   382 
   385 
   383 
   386 
   384         //build a sam instance using an indy call to the meta-factory
   387         //build a sam instance using an indy call to the meta-factory
   385         result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args);
   388         result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
   386     }
   389     }
   387 
   390 
   388     /**
   391     /**
   389      * Translate identifiers within a lambda to the mapped identifier
   392      * Translate identifiers within a lambda to the mapped identifier
   390      * @param tree
   393      * @param tree
   604                     "getImplClass", implClass),
   607                     "getImplClass", implClass),
   605                     "getImplMethodSignature", implMethodSignature),
   608                     "getImplMethodSignature", implMethodSignature),
   606                 make.Return(makeIndyCall(
   609                 make.Return(makeIndyCall(
   607                     pos,
   610                     pos,
   608                     syms.lambdaMetafactory,
   611                     syms.lambdaMetafactory,
   609                     names.altMetaFactory,
   612                     names.altMetafactory,
   610                     staticArgs, indyType, serArgs.toList())),
   613                     staticArgs, indyType, serArgs.toList(), samSym.name)),
   611                 null);
   614                 null);
   612         ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
   615         ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
   613         if (stmts == null) {
   616         if (stmts == null) {
   614             stmts = ListBuffer.lb();
   617             stmts = ListBuffer.lb();
   615             kInfo.deserializeCases.put(implMethodName, stmts);
   618             kInfo.deserializeCases.put(implMethodName, stmts);
   903      */
   906      */
   904     private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) {
   907     private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) {
   905         kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge());
   908         kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge());
   906     }
   909     }
   907 
   910 
       
   911     private MethodType typeToMethodType(Type mt) {
       
   912         Type type = types.erasure(mt);
       
   913         return new MethodType(type.getParameterTypes(),
       
   914                         type.getReturnType(),
       
   915                         type.getThrownTypes(),
       
   916                         syms.methodClass);
       
   917     }
       
   918 
   908     /**
   919     /**
   909      * Generate an indy method call to the meta factory
   920      * Generate an indy method call to the meta factory
   910      */
   921      */
   911     private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory,
   922     private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context,
   912             boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) {
   923             int refKind, Symbol refSym, List<JCExpression> indy_args) {
       
   924         JCFunctionalExpression tree = context.tree;
   913         //determine the static bsm args
   925         //determine the static bsm args
   914         Type mtype = types.erasure(tree.descriptorType);
       
   915         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
   926         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
   916         List<Object> staticArgs = List.<Object>of(
   927         List<Object> staticArgs = List.<Object>of(
   917                 new Pool.MethodHandle(ClassFile.REF_invokeInterface,
   928                 typeToMethodType(samSym.type),
   918                     types.findDescriptorSymbol(tree.type.tsym), types),
       
   919                 new Pool.MethodHandle(refKind, refSym, types),
   929                 new Pool.MethodHandle(refKind, refSym, types),
   920                 new MethodType(mtype.getParameterTypes(),
   930                 typeToMethodType(tree.getDescriptorType(types)));
   921                         mtype.getReturnType(),
       
   922                         mtype.getThrownTypes(),
       
   923                         syms.methodClass));
       
   924 
   931 
   925         //computed indy arg types
   932         //computed indy arg types
   926         ListBuffer<Type> indy_args_types = ListBuffer.lb();
   933         ListBuffer<Type> indy_args_types = ListBuffer.lb();
   927         for (JCExpression arg : indy_args) {
   934         for (JCExpression arg : indy_args) {
   928             indy_args_types.append(arg.type);
   935             indy_args_types.append(arg.type);
   932         MethodType indyType = new MethodType(indy_args_types.toList(),
   939         MethodType indyType = new MethodType(indy_args_types.toList(),
   933                 tree.type,
   940                 tree.type,
   934                 List.<Type>nil(),
   941                 List.<Type>nil(),
   935                 syms.methodClass);
   942                 syms.methodClass);
   936 
   943 
   937         Name metafactoryName = needsAltMetafactory ?
   944         Name metafactoryName = context.needsAltMetafactory() ?
   938                 names.altMetaFactory : names.metaFactory;
   945                 names.altMetafactory : names.metafactory;
   939 
   946 
   940         if (needsAltMetafactory) {
   947         if (context.needsAltMetafactory()) {
   941             ListBuffer<Object> markers = ListBuffer.lb();
   948             ListBuffer<Object> markers = ListBuffer.lb();
   942             for (Symbol t : tree.targets.tail) {
   949             for (Type t : tree.targets.tail) {
   943                 if (t != syms.serializableType.tsym) {
   950                 if (t.tsym != syms.serializableType.tsym) {
   944                     markers.append(t);
   951                     markers.append(t.tsym);
   945                 }
   952                 }
   946             }
   953             }
   947             int flags = isSerializable? FLAG_SERIALIZABLE : 0;
   954             int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
   948             boolean hasMarkers = markers.nonEmpty();
   955             boolean hasMarkers = markers.nonEmpty();
   949             flags |= hasMarkers ? FLAG_MARKERS : 0;
   956             boolean hasBridges = context.bridges.nonEmpty();
       
   957             if (hasMarkers) {
       
   958                 flags |= FLAG_MARKERS;
       
   959             }
       
   960             if (hasBridges) {
       
   961                 flags |= FLAG_BRIDGES;
       
   962             }
   950             staticArgs = staticArgs.append(flags);
   963             staticArgs = staticArgs.append(flags);
   951             if (hasMarkers) {
   964             if (hasMarkers) {
   952                 staticArgs = staticArgs.append(markers.length());
   965                 staticArgs = staticArgs.append(markers.length());
   953                 staticArgs = staticArgs.appendList(markers.toList());
   966                 staticArgs = staticArgs.appendList(markers.toList());
   954             }
   967             }
   955             if (isSerializable) {
   968             if (hasBridges) {
       
   969                 staticArgs = staticArgs.append(context.bridges.length() - 1);
       
   970                 for (Symbol s : context.bridges) {
       
   971                     Type s_erasure = s.erasure(types);
       
   972                     if (!types.isSameType(s_erasure, samSym.erasure(types))) {
       
   973                         staticArgs = staticArgs.append(s.erasure(types));
       
   974                     }
       
   975                 }
       
   976             }
       
   977             if (context.isSerializable()) {
   956                 addDeserializationCase(refKind, refSym, tree.type, samSym,
   978                 addDeserializationCase(refKind, refSym, tree.type, samSym,
   957                         tree, staticArgs, indyType);
   979                         tree, staticArgs, indyType);
   958             }
   980             }
   959         }
   981         }
   960 
   982 
   961         return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args);
   983         return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name);
   962     }
   984     }
   963 
   985 
   964     /**
   986     /**
   965      * Generate an indy method call with given name, type and static bootstrap
   987      * Generate an indy method call with given name, type and static bootstrap
   966      * arguments types
   988      * arguments types
   967      */
   989      */
   968     private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
   990     private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
   969             List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs) {
   991             List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
       
   992             Name methName) {
   970         int prevPos = make.pos;
   993         int prevPos = make.pos;
   971         try {
   994         try {
   972             make.at(pos);
   995             make.at(pos);
   973             List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
   996             List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
   974                     syms.stringType,
   997                     syms.stringType,
   976 
   999 
   977             Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
  1000             Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
   978                     bsmName, bsm_staticArgs, List.<Type>nil());
  1001                     bsmName, bsm_staticArgs, List.<Type>nil());
   979 
  1002 
   980             DynamicMethodSymbol dynSym =
  1003             DynamicMethodSymbol dynSym =
   981                     new DynamicMethodSymbol(names.lambda,
  1004                     new DynamicMethodSymbol(methName,
   982                                             syms.noSymbol,
  1005                                             syms.noSymbol,
   983                                             bsm.isStatic() ?
  1006                                             bsm.isStatic() ?
   984                                                 ClassFile.REF_invokeStatic :
  1007                                                 ClassFile.REF_invokeStatic :
   985                                                 ClassFile.REF_invokeVirtual,
  1008                                                 ClassFile.REF_invokeVirtual,
   986                                             (MethodSymbol)bsm,
  1009                                             (MethodSymbol)bsm,
  1297                 JCNewClass nc = makeNewClass(classType, make.Idents(params));
  1320                 JCNewClass nc = makeNewClass(classType, make.Idents(params));
  1298                 nc.pos = tree.pos;
  1321                 nc.pos = tree.pos;
  1299 
  1322 
  1300                 // Make lambda holding the new-class call
  1323                 // Make lambda holding the new-class call
  1301                 JCLambda slam = make.Lambda(params, nc);
  1324                 JCLambda slam = make.Lambda(params, nc);
  1302                 slam.descriptorType = tree.descriptorType;
       
  1303                 slam.targets = tree.targets;
  1325                 slam.targets = tree.targets;
  1304                 slam.type = tree.type;
  1326                 slam.type = tree.type;
  1305                 slam.pos = tree.pos;
  1327                 slam.pos = tree.pos;
  1306 
  1328 
  1307                 // Now it is a lambda, process as such
  1329                 // Now it is a lambda, process as such
  1632             int depth;
  1654             int depth;
  1633 
  1655 
  1634             /** the enclosing translation context (set for nested lambdas/mref) */
  1656             /** the enclosing translation context (set for nested lambdas/mref) */
  1635             TranslationContext<?> prev;
  1657             TranslationContext<?> prev;
  1636 
  1658 
       
  1659             /** list of methods to be bridged by the meta-factory */
       
  1660             List<Symbol> bridges;
       
  1661 
  1637             TranslationContext(T tree) {
  1662             TranslationContext(T tree) {
  1638                 this.tree = tree;
  1663                 this.tree = tree;
  1639                 this.owner = owner();
  1664                 this.owner = owner();
  1640                 this.depth = frameStack.size() - 1;
  1665                 this.depth = frameStack.size() - 1;
  1641                 this.prev = context();
  1666                 this.prev = context();
       
  1667                 ClassSymbol csym =
       
  1668                         types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.targets, ABSTRACT | INTERFACE);
       
  1669                 this.bridges = types.functionalInterfaceBridges(csym);
  1642             }
  1670             }
  1643 
  1671 
  1644             /** does this functional expression need to be created using alternate metafactory? */
  1672             /** does this functional expression need to be created using alternate metafactory? */
  1645             boolean needsAltMetafactory() {
  1673             boolean needsAltMetafactory() {
  1646                 return (tree.targets.length() > 1 ||
  1674                 return tree.targets.length() > 1 ||
  1647                         isSerializable());
  1675                         isSerializable() ||
       
  1676                         bridges.length() > 1;
  1648             }
  1677             }
  1649 
  1678 
  1650             /** does this functional expression require serialization support? */
  1679             /** does this functional expression require serialization support? */
  1651             boolean isSerializable() {
  1680             boolean isSerializable() {
  1652                 for (Symbol target : tree.targets) {
  1681                 for (Type target : tree.targets) {
  1653                     if (types.asSuper(target.type, syms.serializableType.tsym) != null) {
  1682                     if (types.asSuper(target, syms.serializableType.tsym) != null) {
  1654                         return true;
  1683                         return true;
  1655                     }
  1684                     }
  1656                 }
  1685                 }
  1657                 return false;
  1686                 return false;
  1658             }
  1687             }
  1831                         generatedLambdaSig(),
  1860                         generatedLambdaSig(),
  1832                         TreeInfo.types(syntheticParams));
  1861                         TreeInfo.types(syntheticParams));
  1833             }
  1862             }
  1834 
  1863 
  1835             Type generatedLambdaSig() {
  1864             Type generatedLambdaSig() {
  1836                 return types.erasure(tree.descriptorType);
  1865                 return types.erasure(tree.getDescriptorType(types));
  1837             }
  1866             }
  1838         }
  1867         }
  1839 
  1868 
  1840         /**
  1869         /**
  1841          * This class retains all the useful information about a method reference;
  1870          * This class retains all the useful information about a method reference;
  1907             Type generatedRefSig() {
  1936             Type generatedRefSig() {
  1908                 return types.erasure(tree.sym.type);
  1937                 return types.erasure(tree.sym.type);
  1909             }
  1938             }
  1910 
  1939 
  1911             Type bridgedRefSig() {
  1940             Type bridgedRefSig() {
  1912                 return types.erasure(types.findDescriptorSymbol(tree.targets.head).type);
  1941                 return types.erasure(types.findDescriptorSymbol(tree.targets.head.tsym).type);
  1913             }
  1942             }
  1914         }
  1943         }
  1915     }
  1944     }
  1916     // </editor-fold>
  1945     // </editor-fold>
  1917 
  1946