< prev index next >

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

Print this page

 146     private final boolean forceSerializable;
 147 
 148     /** true if line or local variable debug info has been requested */
 149     private final boolean debugLinesOrVars;
 150 
 151     /** dump statistics about lambda method deduplication */
 152     private final boolean verboseDeduplication;
 153 
 154     /** deduplicate lambda implementation methods */
 155     private final boolean deduplicateLambdas;
 156 
 157     /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
 158     public static final int FLAG_SERIALIZABLE = LambdaMetafactory.FLAG_SERIALIZABLE;
 159 
 160     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
 161     public static final int FLAG_MARKERS = LambdaMetafactory.FLAG_MARKERS;
 162 
 163     /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
 164     public static final int FLAG_BRIDGES = LambdaMetafactory.FLAG_BRIDGES;
 165 



 166     // <editor-fold defaultstate="collapsed" desc="Instantiating">
 167     protected static final Context.Key<LambdaToMethod> unlambdaKey = new Context.Key<>();
 168 
 169     public static LambdaToMethod instance(Context context) {
 170         LambdaToMethod instance = context.get(unlambdaKey);
 171         if (instance == null) {
 172             instance = new LambdaToMethod(context);
 173         }
 174         return instance;
 175     }
 176     private LambdaToMethod(Context context) {
 177         context.put(unlambdaKey, this);
 178         diags = JCDiagnostic.Factory.instance(context);
 179         log = Log.instance(context);
 180         lower = Lower.instance(context);
 181         names = Names.instance(context);
 182         syms = Symtab.instance(context);
 183         rs = Resolve.instance(context);
 184         operators = Operators.instance(context);
 185         make = TreeMaker.instance(context);

 815         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.target.tsym);
 816         List<LoadableConstant> staticArgs = List.of(
 817                 typeToMethodType(samSym.type),
 818                 refSym.asHandle(),
 819                 typeToMethodType(tree.getDescriptorType(types)));
 820 
 821         //computed indy arg types
 822         ListBuffer<Type> indy_args_types = new ListBuffer<>();
 823         for (JCExpression arg : indy_args) {
 824             indy_args_types.append(arg.type);
 825         }
 826 
 827         //finally, compute the type of the indy call
 828         MethodType indyType = new MethodType(indy_args_types.toList(),
 829                 tree.type,
 830                 List.nil(),
 831                 syms.methodClass);
 832 
 833         List<Symbol> bridges = bridges(tree);
 834         boolean isSerializable = isSerializable(tree);

 835         boolean needsAltMetafactory = tree.target.isIntersection() ||
 836                 isSerializable || bridges.length() > 1;
 837 
 838         dumpStats(tree, needsAltMetafactory, nonDedupedRefSym);
 839 
 840         Name metafactoryName = needsAltMetafactory ?
 841                 names.altMetafactory : names.metafactory;
 842 
 843         if (needsAltMetafactory) {
 844             ListBuffer<Type> markers = new ListBuffer<>();
 845             List<Type> targets = tree.target.isIntersection() ?
 846                     types.directSupertypes(tree.target) :
 847                     List.nil();
 848             for (Type t : targets) {
 849                 t = types.erasure(t);
 850                 if (t.tsym != syms.serializableType.tsym &&

 851                         t.tsym != tree.type.tsym &&
 852                         t.tsym != syms.objectType.tsym) {
 853                     markers.append(t);
 854                 }
 855             }
 856             int flags = isSerializable ? FLAG_SERIALIZABLE : 0;

 857             boolean hasMarkers = markers.nonEmpty();
 858             boolean hasBridges = bridges.nonEmpty();
 859             if (hasMarkers) {
 860                 flags |= FLAG_MARKERS;
 861             }
 862             if (hasBridges) {
 863                 flags |= FLAG_BRIDGES;
 864             }
 865             staticArgs = staticArgs.append(LoadableConstant.Int(flags));
 866             if (hasMarkers) {
 867                 staticArgs = staticArgs.append(LoadableConstant.Int(markers.length()));
 868                 staticArgs = staticArgs.appendList(List.convert(LoadableConstant.class, markers.toList()));
 869             }
 870             if (hasBridges) {
 871                 staticArgs = staticArgs.append(LoadableConstant.Int(bridges.length() - 1));
 872                 for (Symbol s : bridges) {
 873                     Type s_erasure = s.erasure(types);
 874                     if (!types.isSameType(s_erasure, samSym.erasure(types))) {
 875                         staticArgs = staticArgs.append(((MethodType)s.erasure(types)));
 876                     }
 877                 }
 878             }




 879             if (isSerializable) {
 880                 int prevPos = make.pos;
 881                 try {
 882                     make.at(kInfo.clazz);
 883                     addDeserializationCase(refSym, tree.type, samSym,
 884                             tree, staticArgs, indyType);
 885                 } finally {
 886                     make.at(prevPos);
 887                 }
 888             }
 889         }
 890 
 891         return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name);
 892     }
 893 
 894     /**
 895      * Generate an indy method call with given name, type and static bootstrap
 896      * arguments types
 897      */
 898     private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,

 925             return proxyCall;
 926         } finally {
 927             make.at(prevPos);
 928         }
 929     }
 930 
 931     List<Symbol> bridges(JCFunctionalExpression tree) {
 932         ClassSymbol csym =
 933                 types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
 934         return types.functionalInterfaceBridges(csym);
 935     }
 936 
 937     /** does this functional expression require serialization support? */
 938     boolean isSerializable(JCFunctionalExpression tree) {
 939         if (forceSerializable) {
 940             return true;
 941         }
 942         return types.asSuper(tree.target, syms.serializableType.tsym) != null;
 943     }
 944 




 945     void dumpStats(JCFunctionalExpression tree, boolean needsAltMetafactory, Symbol sym) {
 946         if (dumpLambdaToMethodStats) {
 947             if (tree instanceof JCLambda lambda) {
 948                 log.note(tree, diags.noteKey(lambda.wasMethodReference ? "mref.stat.1" : "lambda.stat",
 949                         needsAltMetafactory, sym));
 950             } else if (tree instanceof JCMemberReference) {
 951                 log.note(tree, Notes.MrefStat(needsAltMetafactory, null));
 952             }
 953         }
 954     }
 955 
 956     /**
 957      * This class retains all the useful information about a lambda expression,
 958      * and acts as a translation map that is used by the main translation routines
 959      * in order to adjust references to captured locals/members, etc.
 960      */
 961     class LambdaTranslationContext {
 962 
 963         /** the underlying (untranslated) tree */
 964         final JCFunctionalExpression tree;

 146     private final boolean forceSerializable;
 147 
 148     /** true if line or local variable debug info has been requested */
 149     private final boolean debugLinesOrVars;
 150 
 151     /** dump statistics about lambda method deduplication */
 152     private final boolean verboseDeduplication;
 153 
 154     /** deduplicate lambda implementation methods */
 155     private final boolean deduplicateLambdas;
 156 
 157     /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
 158     public static final int FLAG_SERIALIZABLE = LambdaMetafactory.FLAG_SERIALIZABLE;
 159 
 160     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
 161     public static final int FLAG_MARKERS = LambdaMetafactory.FLAG_MARKERS;
 162 
 163     /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
 164     public static final int FLAG_BRIDGES = LambdaMetafactory.FLAG_BRIDGES;
 165 
 166     /** Flag for alternate metafactories indicating the lambda object is intended to be quotable */
 167     public static final int FLAG_QUOTABLE = 1 << 3;
 168 
 169     // <editor-fold defaultstate="collapsed" desc="Instantiating">
 170     protected static final Context.Key<LambdaToMethod> unlambdaKey = new Context.Key<>();
 171 
 172     public static LambdaToMethod instance(Context context) {
 173         LambdaToMethod instance = context.get(unlambdaKey);
 174         if (instance == null) {
 175             instance = new LambdaToMethod(context);
 176         }
 177         return instance;
 178     }
 179     private LambdaToMethod(Context context) {
 180         context.put(unlambdaKey, this);
 181         diags = JCDiagnostic.Factory.instance(context);
 182         log = Log.instance(context);
 183         lower = Lower.instance(context);
 184         names = Names.instance(context);
 185         syms = Symtab.instance(context);
 186         rs = Resolve.instance(context);
 187         operators = Operators.instance(context);
 188         make = TreeMaker.instance(context);

 818         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.target.tsym);
 819         List<LoadableConstant> staticArgs = List.of(
 820                 typeToMethodType(samSym.type),
 821                 refSym.asHandle(),
 822                 typeToMethodType(tree.getDescriptorType(types)));
 823 
 824         //computed indy arg types
 825         ListBuffer<Type> indy_args_types = new ListBuffer<>();
 826         for (JCExpression arg : indy_args) {
 827             indy_args_types.append(arg.type);
 828         }
 829 
 830         //finally, compute the type of the indy call
 831         MethodType indyType = new MethodType(indy_args_types.toList(),
 832                 tree.type,
 833                 List.nil(),
 834                 syms.methodClass);
 835 
 836         List<Symbol> bridges = bridges(tree);
 837         boolean isSerializable = isSerializable(tree);
 838         boolean isQuotable = isQuotable(tree);
 839         boolean needsAltMetafactory = tree.target.isIntersection() ||
 840                 isSerializable || isQuotable || bridges.length() > 1;
 841 
 842         dumpStats(tree, needsAltMetafactory, nonDedupedRefSym);
 843 
 844         Name metafactoryName = needsAltMetafactory ?
 845                 names.altMetafactory : names.metafactory;
 846 
 847         if (needsAltMetafactory) {
 848             ListBuffer<Type> markers = new ListBuffer<>();
 849             List<Type> targets = tree.target.isIntersection() ?
 850                     types.directSupertypes(tree.target) :
 851                     List.nil();
 852             for (Type t : targets) {
 853                 t = types.erasure(t);
 854                 if (t.tsym != syms.serializableType.tsym &&
 855                         !types.isQuotable(t) &&
 856                         t.tsym != tree.type.tsym &&
 857                         t.tsym != syms.objectType.tsym) {
 858                     markers.append(t);
 859                 }
 860             }
 861             int flags = isSerializable ? FLAG_SERIALIZABLE : 0;
 862             flags |= isQuotable ? FLAG_QUOTABLE : 0;
 863             boolean hasMarkers = markers.nonEmpty();
 864             boolean hasBridges = bridges.nonEmpty();
 865             if (hasMarkers) {
 866                 flags |= FLAG_MARKERS;
 867             }
 868             if (hasBridges) {
 869                 flags |= FLAG_BRIDGES;
 870             }
 871             staticArgs = staticArgs.append(LoadableConstant.Int(flags));
 872             if (hasMarkers) {
 873                 staticArgs = staticArgs.append(LoadableConstant.Int(markers.length()));
 874                 staticArgs = staticArgs.appendList(List.convert(LoadableConstant.class, markers.toList()));
 875             }
 876             if (hasBridges) {
 877                 staticArgs = staticArgs.append(LoadableConstant.Int(bridges.length() - 1));
 878                 for (Symbol s : bridges) {
 879                     Type s_erasure = s.erasure(types);
 880                     if (!types.isSameType(s_erasure, samSym.erasure(types))) {
 881                         staticArgs = staticArgs.append(((MethodType)s.erasure(types)));
 882                     }
 883                 }
 884             }
 885             if (isQuotable) {
 886                 MethodSymbol opMethodSym = tree.codeModel;
 887                 staticArgs = staticArgs.append(opMethodSym.asHandle());
 888             }
 889             if (isSerializable) {
 890                 int prevPos = make.pos;
 891                 try {
 892                     make.at(kInfo.clazz);
 893                     addDeserializationCase(refSym, tree.type, samSym,
 894                             tree, staticArgs, indyType);
 895                 } finally {
 896                     make.at(prevPos);
 897                 }
 898             }
 899         }
 900 
 901         return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name);
 902     }
 903 
 904     /**
 905      * Generate an indy method call with given name, type and static bootstrap
 906      * arguments types
 907      */
 908     private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,

 935             return proxyCall;
 936         } finally {
 937             make.at(prevPos);
 938         }
 939     }
 940 
 941     List<Symbol> bridges(JCFunctionalExpression tree) {
 942         ClassSymbol csym =
 943                 types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
 944         return types.functionalInterfaceBridges(csym);
 945     }
 946 
 947     /** does this functional expression require serialization support? */
 948     boolean isSerializable(JCFunctionalExpression tree) {
 949         if (forceSerializable) {
 950             return true;
 951         }
 952         return types.asSuper(tree.target, syms.serializableType.tsym) != null;
 953     }
 954 
 955     boolean isQuotable(JCFunctionalExpression tree) {
 956         return tree.codeModel != null;
 957     }
 958 
 959     void dumpStats(JCFunctionalExpression tree, boolean needsAltMetafactory, Symbol sym) {
 960         if (dumpLambdaToMethodStats) {
 961             if (tree instanceof JCLambda lambda) {
 962                 log.note(tree, diags.noteKey(lambda.wasMethodReference ? "mref.stat.1" : "lambda.stat",
 963                         needsAltMetafactory, sym));
 964             } else if (tree instanceof JCMemberReference) {
 965                 log.note(tree, Notes.MrefStat(needsAltMetafactory, null));
 966             }
 967         }
 968     }
 969 
 970     /**
 971      * This class retains all the useful information about a lambda expression,
 972      * and acts as a translation map that is used by the main translation routines
 973      * in order to adjust references to captured locals/members, etc.
 974      */
 975     class LambdaTranslationContext {
 976 
 977         /** the underlying (untranslated) tree */
 978         final JCFunctionalExpression tree;
< prev index next >