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, |
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 } |