diff -r bdeef606be8e -r 39ec5d8a691b src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Jul 11 10:13:57 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Jul 11 14:07:39 2013 +0100 @@ -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); } /** @@ -606,8 +609,8 @@ make.Return(makeIndyCall( pos, syms.lambdaMetafactory, - names.altMetaFactory, - staticArgs, indyType, serArgs.toList())), + names.altMetafactory, + staticArgs, indyType, serArgs.toList(), samSym.name)), null); ListBuffer stmts = kInfo.deserializeCases.get(implMethodName); if (stmts == null) { @@ -905,22 +908,26 @@ kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge()); } + private MethodType typeToMethodType(Type mt) { + Type type = types.erasure(mt); + return new MethodType(type.getParameterTypes(), + type.getReturnType(), + type.getThrownTypes(), + syms.methodClass); + } + /** * Generate an indy method call to the meta factory */ - private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory, - boolean isSerializable, int refKind, Symbol refSym, List indy_args) { + private JCExpression makeMetafactoryIndyCall(TranslationContext context, + int refKind, Symbol refSym, List indy_args) { + JCFunctionalExpression tree = context.tree; //determine the static bsm args - Type mtype = types.erasure(tree.descriptorType); MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym); List staticArgs = List.of( - new Pool.MethodHandle(ClassFile.REF_invokeInterface, - types.findDescriptorSymbol(tree.type.tsym), types), + typeToMethodType(samSym.type), new Pool.MethodHandle(refKind, refSym, types), - new MethodType(mtype.getParameterTypes(), - mtype.getReturnType(), - mtype.getThrownTypes(), - syms.methodClass)); + typeToMethodType(tree.getDescriptorType(types))); //computed indy arg types ListBuffer indy_args_types = ListBuffer.lb(); @@ -934,31 +941,46 @@ List.nil(), syms.methodClass); - Name metafactoryName = needsAltMetafactory ? - names.altMetaFactory : names.metaFactory; + Name metafactoryName = context.needsAltMetafactory() ? + names.altMetafactory : names.metafactory; - if (needsAltMetafactory) { + if (context.needsAltMetafactory()) { ListBuffer 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); } } - return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args); + return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name); } /** @@ -966,7 +988,8 @@ * arguments types */ private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName, - List staticArgs, MethodType indyType, List indyArgs) { + List staticArgs, MethodType indyType, List indyArgs, + Name methName) { int prevPos = make.pos; try { make.at(pos); @@ -978,7 +1001,7 @@ bsmName, bsm_staticArgs, List.nil()); DynamicMethodSymbol dynSym = - new DynamicMethodSymbol(names.lambda, + new DynamicMethodSymbol(methName, syms.noSymbol, bsm.isStatic() ? ClassFile.REF_invokeStatic : @@ -1299,7 +1322,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 +1656,30 @@ /** the enclosing translation context (set for nested lambdas/mref) */ TranslationContext prev; + /** list of methods to be bridged by the meta-factory */ + List 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 +1862,7 @@ } Type generatedLambdaSig() { - return types.erasure(tree.descriptorType); + return types.erasure(tree.getDescriptorType(types)); } } @@ -1909,7 +1938,7 @@ } Type bridgedRefSig() { - return types.erasure(types.findDescriptorSymbol(tree.targets.head).type); + return types.erasure(types.findDescriptorSymbol(tree.targets.head.tsym).type); } } }