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 }