< prev index next >

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

Print this page

   1 /*
   2  * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any

 121     private final boolean debugLinesOrVars;
 122 
 123     /** dump statistics about lambda method deduplication */
 124     private final boolean verboseDeduplication;
 125 
 126     /** deduplicate lambda implementation methods */
 127     private final boolean deduplicateLambdas;
 128 
 129     /** lambda proxy is a dynamic nestmate */
 130     private final boolean nestmateLambdas;
 131 
 132     /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
 133     public static final int FLAG_SERIALIZABLE = 1 << 0;
 134 
 135     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
 136     public static final int FLAG_MARKERS = 1 << 1;
 137 
 138     /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
 139     public static final int FLAG_BRIDGES = 1 << 2;
 140 



 141     // <editor-fold defaultstate="collapsed" desc="Instantiating">
 142     protected static final Context.Key<LambdaToMethod> unlambdaKey = new Context.Key<>();
 143 
 144     public static LambdaToMethod instance(Context context) {
 145         LambdaToMethod instance = context.get(unlambdaKey);
 146         if (instance == null) {
 147             instance = new LambdaToMethod(context);
 148         }
 149         return instance;
 150     }
 151     private LambdaToMethod(Context context) {
 152         context.put(unlambdaKey, this);
 153         diags = JCDiagnostic.Factory.instance(context);
 154         log = Log.instance(context);
 155         lower = Lower.instance(context);
 156         names = Names.instance(context);
 157         syms = Symtab.instance(context);
 158         rs = Resolve.instance(context);
 159         operators = Operators.instance(context);
 160         make = TreeMaker.instance(context);

 422             syntheticInits.append(localContext.methodReferenceReceiver);
 423         } else if (!sym.isStatic()) {
 424             syntheticInits.append(makeThis(
 425                     sym.owner.enclClass().asType(),
 426                     localContext.owner.enclClass()));
 427         }
 428 
 429         //add captured locals
 430         for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
 431             if (fv != localContext.self) {
 432                 JCExpression captured_local = make.Ident(fv).setType(fv.type);
 433                 syntheticInits.append(captured_local);
 434             }
 435         }
 436         // add captured outer this instances (used only when `this' capture itself is illegal)
 437         for (Symbol fv : localContext.getSymbolMap(CAPTURED_OUTER_THIS).keySet()) {
 438             JCExpression captured_local = make.QualThis(fv.type);
 439             syntheticInits.append(captured_local);
 440         }
 441 






 442         //then, determine the arguments to the indy call
 443         List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
 444 
 445         //convert to an invokedynamic call
 446         result = makeMetafactoryIndyCall(context, sym.asHandle(), indy_args);
 447     }
 448 
 449     // where
 450         // Reassign type annotations from the source that should really belong to the lambda
 451         private void apportionTypeAnnotations(JCLambda tree,
 452                                               Supplier<List<Attribute.TypeCompound>> source,
 453                                               Consumer<List<Attribute.TypeCompound>> owner,
 454                                               Consumer<List<Attribute.TypeCompound>> lambda) {
 455 
 456             ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>();
 457             ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>();
 458 
 459             for (Attribute.TypeCompound tc : source.get()) {
 460                 if (tc.position.onLambda == tree) {
 461                     lambdaTypeAnnos.append(tc);

 503 
 504             case BOUND:             /** Expr :: instMethod */
 505                 init = transTypes.coerce(attrEnv, tree.getQualifierExpression(),
 506                     types.erasure(tree.sym.owner.type));
 507                 init = attr.makeNullCheck(init);
 508                 break;
 509 
 510             case UNBOUND:           /** Type :: instMethod */
 511             case STATIC:            /** Type :: staticMethod */
 512             case TOPLEVEL:          /** Top level :: new */
 513             case ARRAY_CTOR:        /** ArrayType :: new */
 514                 init = null;
 515                 break;
 516 
 517             default:
 518                 throw new InternalError("Should not have an invalid kind");
 519         }
 520 
 521         List<JCExpression> indy_args = init==null? List.nil() : translate(List.of(init), localContext.prev);
 522 






 523 
 524         //build a sam instance using an indy call to the meta-factory
 525         result = makeMetafactoryIndyCall(localContext, refSym.asHandle(), indy_args);
 526     }
 527 
 528     /**
 529      * Translate identifiers within a lambda to the mapped identifier
 530      * @param tree
 531      */
 532     @Override
 533     public void visitIdent(JCIdent tree) {
 534         if (context == null || !analyzer.lambdaIdentSymbolFilter(tree.sym)) {
 535             super.visitIdent(tree);
 536         } else {
 537             int prevPos = make.pos;
 538             try {
 539                 make.at(tree);
 540 
 541                 LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
 542                 JCTree ltree = lambdaContext.translate(tree);

 904 
 905         MemberReferenceToLambda(JCMemberReference tree, ReferenceTranslationContext localContext, Symbol owner) {
 906             this.tree = tree;
 907             this.localContext = localContext;
 908             this.owner = owner;
 909         }
 910 
 911         JCLambda lambda() {
 912             int prevPos = make.pos;
 913             try {
 914                 make.at(tree);
 915 
 916                 //body generation - this can be either a method call or a
 917                 //new instance creation expression, depending on the member reference kind
 918                 VarSymbol rcvr = addParametersReturnReceiver();
 919                 JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
 920                         ? expressionInvoke(rcvr)
 921                         : expressionNew();
 922 
 923                 JCLambda slam = make.Lambda(params.toList(), expr);

 924                 slam.target = tree.target;
 925                 slam.type = tree.type;
 926                 slam.pos = tree.pos;
 927                 return slam;
 928             } finally {
 929                 make.at(prevPos);
 930             }
 931         }
 932 
 933         /**
 934          * Generate the parameter list for the converted member reference.
 935          *
 936          * @return The receiver variable symbol, if any
 937          */
 938         VarSymbol addParametersReturnReceiver() {
 939             Type samDesc = localContext.bridgedRefSig();
 940             List<Type> samPTypes = samDesc.getParameterTypes();
 941             List<Type> descPTypes = tree.getDescriptorType(types).getParameterTypes();
 942 
 943             // Determine the receiver, if any

1123             indy_args_types.append(arg.type);
1124         }
1125 
1126         //finally, compute the type of the indy call
1127         MethodType indyType = new MethodType(indy_args_types.toList(),
1128                 tree.type,
1129                 List.nil(),
1130                 syms.methodClass);
1131 
1132         Name metafactoryName = context.needsAltMetafactory() ?
1133                 names.altMetafactory : names.metafactory;
1134 
1135         if (context.needsAltMetafactory()) {
1136             ListBuffer<Type> markers = new ListBuffer<>();
1137             List<Type> targets = tree.target.isIntersection() ?
1138                     types.directSupertypes(tree.target) :
1139                     List.nil();
1140             for (Type t : targets) {
1141                 t = types.erasure(t);
1142                 if (t.tsym != syms.serializableType.tsym &&

1143                     t.tsym != tree.type.tsym &&
1144                     t.tsym != syms.objectType.tsym) {
1145                     markers.append(t);
1146                 }
1147             }
1148             int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;

1149             boolean hasMarkers = markers.nonEmpty();
1150             boolean hasBridges = context.bridges.nonEmpty();
1151             if (hasMarkers) {
1152                 flags |= FLAG_MARKERS;
1153             }
1154             if (hasBridges) {
1155                 flags |= FLAG_BRIDGES;
1156             }
1157             staticArgs = staticArgs.append(LoadableConstant.Int(flags));
1158             if (hasMarkers) {
1159                 staticArgs = staticArgs.append(LoadableConstant.Int(markers.length()));
1160                 staticArgs = staticArgs.appendList(List.convert(LoadableConstant.class, markers.toList()));
1161             }
1162             if (hasBridges) {
1163                 staticArgs = staticArgs.append(LoadableConstant.Int(context.bridges.length() - 1));
1164                 for (Symbol s : context.bridges) {
1165                     Type s_erasure = s.erasure(types);
1166                     if (!types.isSameType(s_erasure, samSym.erasure(types))) {
1167                         staticArgs = staticArgs.append(((MethodType)s.erasure(types)));
1168                     }
1169                 }
1170             }




1171             if (context.isSerializable()) {
1172                 int prevPos = make.pos;
1173                 try {
1174                     make.at(kInfo.clazz);
1175                     addDeserializationCase(refSym, tree.type, samSym,
1176                             tree, staticArgs, indyType);
1177                 } finally {
1178                     make.at(prevPos);
1179                 }
1180             }
1181         }
1182 
1183         return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name);
1184     }
1185 
1186     /**
1187      * Generate an indy method call with given name, type and static bootstrap
1188      * arguments types
1189      */
1190     private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,

1845             /** the enclosing translation context (set for nested lambdas/mref) */
1846             final TranslationContext<?> prev;
1847 
1848             /** list of methods to be bridged by the meta-factory */
1849             final List<Symbol> bridges;
1850 
1851             TranslationContext(T tree) {
1852                 this.tree = tree;
1853                 this.owner = owner(true);
1854                 this.depth = frameStack.size() - 1;
1855                 this.prev = context();
1856                 ClassSymbol csym =
1857                         types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
1858                 this.bridges = types.functionalInterfaceBridges(csym);
1859             }
1860 
1861             /** does this functional expression need to be created using alternate metafactory? */
1862             boolean needsAltMetafactory() {
1863                 return tree.target.isIntersection() ||
1864                         isSerializable() ||

1865                         bridges.length() > 1;
1866             }
1867 
1868             /** does this functional expression require serialization support? */
1869             boolean isSerializable() {
1870                 if (forceSerializable) {
1871                     return true;
1872                 }
1873                 return types.asSuper(tree.target, syms.serializableType.tsym) != null;
1874             }




1875 
1876             /**
1877              * @return Name of the enclosing method to be folded into synthetic
1878              * method name
1879              */
1880             String enclosingMethodName() {
1881                 return syntheticMethodNameComponent(owner.name);
1882             }
1883 
1884             /**
1885              * @return Method name in a form that can be folded into a
1886              * component of a synthetic method name
1887              */
1888             String syntheticMethodNameComponent(Name name) {
1889                 if (name == null) {
1890                     return "null";
1891                 }
1892                 String methodName = name.toString();
1893                 if (methodName.equals("<clinit>")) {
1894                     methodName = "static";

   1 /*
   2  * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any

 121     private final boolean debugLinesOrVars;
 122 
 123     /** dump statistics about lambda method deduplication */
 124     private final boolean verboseDeduplication;
 125 
 126     /** deduplicate lambda implementation methods */
 127     private final boolean deduplicateLambdas;
 128 
 129     /** lambda proxy is a dynamic nestmate */
 130     private final boolean nestmateLambdas;
 131 
 132     /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
 133     public static final int FLAG_SERIALIZABLE = 1 << 0;
 134 
 135     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
 136     public static final int FLAG_MARKERS = 1 << 1;
 137 
 138     /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
 139     public static final int FLAG_BRIDGES = 1 << 2;
 140 
 141     /** Flag for alternate metafactories indicating the lambda object is intended to be quotable */
 142     public static final int FLAG_QUOTABLE = 1 << 3;
 143 
 144     // <editor-fold defaultstate="collapsed" desc="Instantiating">
 145     protected static final Context.Key<LambdaToMethod> unlambdaKey = new Context.Key<>();
 146 
 147     public static LambdaToMethod instance(Context context) {
 148         LambdaToMethod instance = context.get(unlambdaKey);
 149         if (instance == null) {
 150             instance = new LambdaToMethod(context);
 151         }
 152         return instance;
 153     }
 154     private LambdaToMethod(Context context) {
 155         context.put(unlambdaKey, this);
 156         diags = JCDiagnostic.Factory.instance(context);
 157         log = Log.instance(context);
 158         lower = Lower.instance(context);
 159         names = Names.instance(context);
 160         syms = Symtab.instance(context);
 161         rs = Resolve.instance(context);
 162         operators = Operators.instance(context);
 163         make = TreeMaker.instance(context);

 425             syntheticInits.append(localContext.methodReferenceReceiver);
 426         } else if (!sym.isStatic()) {
 427             syntheticInits.append(makeThis(
 428                     sym.owner.enclClass().asType(),
 429                     localContext.owner.enclClass()));
 430         }
 431 
 432         //add captured locals
 433         for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
 434             if (fv != localContext.self) {
 435                 JCExpression captured_local = make.Ident(fv).setType(fv.type);
 436                 syntheticInits.append(captured_local);
 437             }
 438         }
 439         // add captured outer this instances (used only when `this' capture itself is illegal)
 440         for (Symbol fv : localContext.getSymbolMap(CAPTURED_OUTER_THIS).keySet()) {
 441             JCExpression captured_local = make.QualThis(fv.type);
 442             syntheticInits.append(captured_local);
 443         }
 444 
 445         if (context.isQuotable()) {
 446             for (JCExpression capturedArg : tree.codeReflectionInfo.capturedArgs()) {
 447                 syntheticInits.append(capturedArg);
 448             }
 449         }
 450 
 451         //then, determine the arguments to the indy call
 452         List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
 453 
 454         //convert to an invokedynamic call
 455         result = makeMetafactoryIndyCall(context, sym.asHandle(), indy_args);
 456     }
 457 
 458     // where
 459         // Reassign type annotations from the source that should really belong to the lambda
 460         private void apportionTypeAnnotations(JCLambda tree,
 461                                               Supplier<List<Attribute.TypeCompound>> source,
 462                                               Consumer<List<Attribute.TypeCompound>> owner,
 463                                               Consumer<List<Attribute.TypeCompound>> lambda) {
 464 
 465             ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>();
 466             ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>();
 467 
 468             for (Attribute.TypeCompound tc : source.get()) {
 469                 if (tc.position.onLambda == tree) {
 470                     lambdaTypeAnnos.append(tc);

 512 
 513             case BOUND:             /** Expr :: instMethod */
 514                 init = transTypes.coerce(attrEnv, tree.getQualifierExpression(),
 515                     types.erasure(tree.sym.owner.type));
 516                 init = attr.makeNullCheck(init);
 517                 break;
 518 
 519             case UNBOUND:           /** Type :: instMethod */
 520             case STATIC:            /** Type :: staticMethod */
 521             case TOPLEVEL:          /** Top level :: new */
 522             case ARRAY_CTOR:        /** ArrayType :: new */
 523                 init = null;
 524                 break;
 525 
 526             default:
 527                 throw new InternalError("Should not have an invalid kind");
 528         }
 529 
 530         List<JCExpression> indy_args = init==null? List.nil() : translate(List.of(init), localContext.prev);
 531 
 532         if (context.isQuotable()) {
 533             for (JCExpression capturedArg : tree.codeReflectionInfo.capturedArgs()) {
 534                 indy_args = indy_args.append(capturedArg);
 535             }
 536         }
 537 
 538 
 539         //build a sam instance using an indy call to the meta-factory
 540         result = makeMetafactoryIndyCall(localContext, refSym.asHandle(), indy_args);
 541     }
 542 
 543     /**
 544      * Translate identifiers within a lambda to the mapped identifier
 545      * @param tree
 546      */
 547     @Override
 548     public void visitIdent(JCIdent tree) {
 549         if (context == null || !analyzer.lambdaIdentSymbolFilter(tree.sym)) {
 550             super.visitIdent(tree);
 551         } else {
 552             int prevPos = make.pos;
 553             try {
 554                 make.at(tree);
 555 
 556                 LambdaTranslationContext lambdaContext = (LambdaTranslationContext) context;
 557                 JCTree ltree = lambdaContext.translate(tree);

 919 
 920         MemberReferenceToLambda(JCMemberReference tree, ReferenceTranslationContext localContext, Symbol owner) {
 921             this.tree = tree;
 922             this.localContext = localContext;
 923             this.owner = owner;
 924         }
 925 
 926         JCLambda lambda() {
 927             int prevPos = make.pos;
 928             try {
 929                 make.at(tree);
 930 
 931                 //body generation - this can be either a method call or a
 932                 //new instance creation expression, depending on the member reference kind
 933                 VarSymbol rcvr = addParametersReturnReceiver();
 934                 JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
 935                         ? expressionInvoke(rcvr)
 936                         : expressionNew();
 937 
 938                 JCLambda slam = make.Lambda(params.toList(), expr);
 939                 slam.codeReflectionInfo = tree.codeReflectionInfo;
 940                 slam.target = tree.target;
 941                 slam.type = tree.type;
 942                 slam.pos = tree.pos;
 943                 return slam;
 944             } finally {
 945                 make.at(prevPos);
 946             }
 947         }
 948 
 949         /**
 950          * Generate the parameter list for the converted member reference.
 951          *
 952          * @return The receiver variable symbol, if any
 953          */
 954         VarSymbol addParametersReturnReceiver() {
 955             Type samDesc = localContext.bridgedRefSig();
 956             List<Type> samPTypes = samDesc.getParameterTypes();
 957             List<Type> descPTypes = tree.getDescriptorType(types).getParameterTypes();
 958 
 959             // Determine the receiver, if any

1139             indy_args_types.append(arg.type);
1140         }
1141 
1142         //finally, compute the type of the indy call
1143         MethodType indyType = new MethodType(indy_args_types.toList(),
1144                 tree.type,
1145                 List.nil(),
1146                 syms.methodClass);
1147 
1148         Name metafactoryName = context.needsAltMetafactory() ?
1149                 names.altMetafactory : names.metafactory;
1150 
1151         if (context.needsAltMetafactory()) {
1152             ListBuffer<Type> markers = new ListBuffer<>();
1153             List<Type> targets = tree.target.isIntersection() ?
1154                     types.directSupertypes(tree.target) :
1155                     List.nil();
1156             for (Type t : targets) {
1157                 t = types.erasure(t);
1158                 if (t.tsym != syms.serializableType.tsym &&
1159                     t.tsym != syms.quotableType.tsym &&
1160                     t.tsym != tree.type.tsym &&
1161                     t.tsym != syms.objectType.tsym) {
1162                     markers.append(t);
1163                 }
1164             }
1165             int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
1166             flags |= context.isQuotable() ? FLAG_QUOTABLE : 0;
1167             boolean hasMarkers = markers.nonEmpty();
1168             boolean hasBridges = context.bridges.nonEmpty();
1169             if (hasMarkers) {
1170                 flags |= FLAG_MARKERS;
1171             }
1172             if (hasBridges) {
1173                 flags |= FLAG_BRIDGES;
1174             }
1175             staticArgs = staticArgs.append(LoadableConstant.Int(flags));
1176             if (hasMarkers) {
1177                 staticArgs = staticArgs.append(LoadableConstant.Int(markers.length()));
1178                 staticArgs = staticArgs.appendList(List.convert(LoadableConstant.class, markers.toList()));
1179             }
1180             if (hasBridges) {
1181                 staticArgs = staticArgs.append(LoadableConstant.Int(context.bridges.length() - 1));
1182                 for (Symbol s : context.bridges) {
1183                     Type s_erasure = s.erasure(types);
1184                     if (!types.isSameType(s_erasure, samSym.erasure(types))) {
1185                         staticArgs = staticArgs.append(((MethodType)s.erasure(types)));
1186                     }
1187                 }
1188             }
1189             if (context.isQuotable()) {
1190                 VarSymbol reflectField = (VarSymbol)tree.codeReflectionInfo.quotedField();
1191                 staticArgs = staticArgs.append(reflectField.asMethodHandle(true));
1192             }
1193             if (context.isSerializable()) {
1194                 int prevPos = make.pos;
1195                 try {
1196                     make.at(kInfo.clazz);
1197                     addDeserializationCase(refSym, tree.type, samSym,
1198                             tree, staticArgs, indyType);
1199                 } finally {
1200                     make.at(prevPos);
1201                 }
1202             }
1203         }
1204 
1205         return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name);
1206     }
1207 
1208     /**
1209      * Generate an indy method call with given name, type and static bootstrap
1210      * arguments types
1211      */
1212     private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,

1867             /** the enclosing translation context (set for nested lambdas/mref) */
1868             final TranslationContext<?> prev;
1869 
1870             /** list of methods to be bridged by the meta-factory */
1871             final List<Symbol> bridges;
1872 
1873             TranslationContext(T tree) {
1874                 this.tree = tree;
1875                 this.owner = owner(true);
1876                 this.depth = frameStack.size() - 1;
1877                 this.prev = context();
1878                 ClassSymbol csym =
1879                         types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
1880                 this.bridges = types.functionalInterfaceBridges(csym);
1881             }
1882 
1883             /** does this functional expression need to be created using alternate metafactory? */
1884             boolean needsAltMetafactory() {
1885                 return tree.target.isIntersection() ||
1886                         isSerializable() ||
1887                         isQuotable() ||
1888                         bridges.length() > 1;
1889             }
1890 
1891             /** does this functional expression require serialization support? */
1892             boolean isSerializable() {
1893                 if (forceSerializable) {
1894                     return true;
1895                 }
1896                 return types.asSuper(tree.target, syms.serializableType.tsym) != null;
1897             }
1898 
1899             boolean isQuotable() {
1900                 return tree.codeReflectionInfo != null;
1901             }
1902 
1903             /**
1904              * @return Name of the enclosing method to be folded into synthetic
1905              * method name
1906              */
1907             String enclosingMethodName() {
1908                 return syntheticMethodNameComponent(owner.name);
1909             }
1910 
1911             /**
1912              * @return Method name in a form that can be folded into a
1913              * component of a synthetic method name
1914              */
1915             String syntheticMethodNameComponent(Name name) {
1916                 if (name == null) {
1917                     return "null";
1918                 }
1919                 String methodName = name.toString();
1920                 if (methodName.equals("<clinit>")) {
1921                     methodName = "static";
< prev index next >