< prev index next >

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

Print this page




  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
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
  29 import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
  30 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
  31 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  32 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  33 import com.sun.tools.javac.tree.*;
  34 import com.sun.tools.javac.tree.JCTree.*;
  35 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
  36 import com.sun.tools.javac.tree.TreeMaker;
  37 import com.sun.tools.javac.tree.TreeTranslator;
  38 import com.sun.tools.javac.code.Attribute;
  39 import com.sun.tools.javac.code.Scope.WriteableScope;
  40 import com.sun.tools.javac.code.Symbol;
  41 import com.sun.tools.javac.code.Symbol.ClassSymbol;
  42 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
  43 import com.sun.tools.javac.code.Symbol.MethodSymbol;
  44 import com.sun.tools.javac.code.Symbol.TypeSymbol;
  45 import com.sun.tools.javac.code.Symbol.VarSymbol;
  46 import com.sun.tools.javac.code.Symtab;
  47 import com.sun.tools.javac.code.Type;
  48 import com.sun.tools.javac.code.Type.MethodType;
  49 import com.sun.tools.javac.code.Type.TypeVar;
  50 import com.sun.tools.javac.code.Types;
  51 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
  52 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
  53 import com.sun.tools.javac.resources.CompilerProperties.Notes;
  54 import com.sun.tools.javac.jvm.*;
  55 import com.sun.tools.javac.util.*;
  56 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  57 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  58 
  59 import java.util.EnumMap;


 110     private TranslationContext<?> context;
 111 
 112     /** info about the current class being processed */
 113     private KlassInfo kInfo;
 114 
 115     /** dump statistics about lambda code generation */
 116     private final boolean dumpLambdaToMethodStats;
 117 
 118     /** force serializable representation, for stress testing **/
 119     private final boolean forceSerializable;
 120 
 121     /** true if line or local variable debug info has been requested */
 122     private final boolean debugLinesOrVars;
 123 
 124     /** dump statistics about lambda method deduplication */
 125     private final boolean verboseDeduplication;
 126 
 127     /** deduplicate lambda implementation methods */
 128     private final boolean deduplicateLambdas;
 129 



 130     /** Flag for alternate metafactories indicating the lambda object is intended to be serializable */
 131     public static final int FLAG_SERIALIZABLE = 1 << 0;
 132 
 133     /** Flag for alternate metafactories indicating the lambda object has multiple targets */
 134     public static final int FLAG_MARKERS = 1 << 1;
 135 
 136     /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */
 137     public static final int FLAG_BRIDGES = 1 << 2;
 138 
 139     // <editor-fold defaultstate="collapsed" desc="Instantiating">
 140     protected static final Context.Key<LambdaToMethod> unlambdaKey = new Context.Key<>();
 141 
 142     public static LambdaToMethod instance(Context context) {
 143         LambdaToMethod instance = context.get(unlambdaKey);
 144         if (instance == null) {
 145             instance = new LambdaToMethod(context);
 146         }
 147         return instance;
 148     }
 149     private LambdaToMethod(Context context) {


 151         diags = JCDiagnostic.Factory.instance(context);
 152         log = Log.instance(context);
 153         lower = Lower.instance(context);
 154         names = Names.instance(context);
 155         syms = Symtab.instance(context);
 156         rs = Resolve.instance(context);
 157         operators = Operators.instance(context);
 158         make = TreeMaker.instance(context);
 159         types = Types.instance(context);
 160         transTypes = TransTypes.instance(context);
 161         analyzer = new LambdaAnalyzerPreprocessor();
 162         Options options = Options.instance(context);
 163         dumpLambdaToMethodStats = options.isSet("debug.dumpLambdaToMethodStats");
 164         attr = Attr.instance(context);
 165         forceSerializable = options.isSet("forceSerializable");
 166         debugLinesOrVars = options.isSet(Option.G)
 167                 || options.isSet(Option.G_CUSTOM, "lines")
 168                 || options.isSet(Option.G_CUSTOM, "vars");
 169         verboseDeduplication = options.isSet("debug.dumpLambdaToMethodDeduplication");
 170         deduplicateLambdas = options.getBoolean("deduplicateLambdas", true);

 171     }
 172     // </editor-fold>
 173 
 174     class DedupedLambda {
 175         private final MethodSymbol symbol;
 176         private final JCTree tree;
 177 
 178         private int hashCode;
 179 
 180         DedupedLambda(MethodSymbol symbol, JCTree tree) {
 181             this.symbol = symbol;
 182             this.tree = tree;
 183         }
 184 
 185 
 186         @Override
 187         public int hashCode() {
 188             int hashCode = this.hashCode;
 189             if (hashCode == 0) {
 190                 this.hashCode = hashCode = TreeHasher.hash(tree, symbol.params());


2236             }
2237 
2238             boolean needsVarArgsConversion() {
2239                 return tree.varargsElement != null;
2240             }
2241 
2242             /**
2243              * @return Is this an array operation like clone()
2244              */
2245             boolean isArrayOp() {
2246                 return tree.sym.owner == syms.arrayClass;
2247             }
2248 
2249             boolean receiverAccessible() {
2250                 //hack needed to workaround 292 bug (7087658)
2251                 //when 292 issue is fixed we should remove this and change the backend
2252                 //code to always generate a method handle to an accessible method
2253                 return tree.ownerAccessible;
2254             }
2255 














2256             boolean isProtectedInSuperClassOfEnclosingClassInOtherPackage() {
2257                 return ((tree.sym.flags() & PROTECTED) != 0 &&
2258                         tree.sym.packge() != owner.packge());
2259             }
2260 
2261             /**
2262              * Erasure destroys the implementation parameter subtype
2263              * relationship for intersection types.
2264              * Have similar problems for union types too.
2265              */
2266             boolean interfaceParameterIsIntersectionOrUnionType() {
2267                 List<Type> tl = tree.getDescriptorType(types).getParameterTypes();
2268                 for (; tl.nonEmpty(); tl = tl.tail) {
2269                     Type pt = tl.head;
2270                     return isIntersectionOrUnionType(pt);
2271                 }
2272                 return false;
2273             }
2274 
2275             boolean isIntersectionOrUnionType(Type t) {
2276                 switch (t.getKind()) {
2277                     case INTERSECTION:
2278                     case UNION:
2279                         return true;
2280                     case TYPEVAR:
2281                         TypeVar tv = (TypeVar) t;
2282                         return isIntersectionOrUnionType(tv.getUpperBound());
2283                 }
2284                 return false;
2285             }
2286 
2287             /**
2288              * Does this reference need to be converted to a lambda
2289              * (i.e. var args need to be expanded or "super" is used)
2290              */
2291             final boolean needsConversionToLambda() {
2292                 return interfaceParameterIsIntersectionOrUnionType() ||
2293                         isSuper ||
2294                         needsVarArgsConversion() ||
2295                         isArrayOp() ||

2296                         isProtectedInSuperClassOfEnclosingClassInOtherPackage() ||
2297                         !receiverAccessible() ||
2298                         (tree.getMode() == ReferenceMode.NEW &&
2299                           tree.kind != ReferenceKind.ARRAY_CTOR &&
2300                           (tree.sym.owner.isLocal() || tree.sym.owner.isInner()));
2301             }
2302 
2303             Type generatedRefSig() {
2304                 return types.erasure(tree.sym.type);
2305             }
2306 
2307             Type bridgedRefSig() {
2308                 return types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
2309             }
2310         }
2311     }
2312     // </editor-fold>
2313 
2314     /*
2315      * These keys provide mappings for various translated lambda symbols




  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
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
  29 import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
  30 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
  31 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  32 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  33 import com.sun.tools.javac.tree.*;
  34 import com.sun.tools.javac.tree.JCTree.*;
  35 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
  36 import com.sun.tools.javac.tree.TreeMaker;
  37 import com.sun.tools.javac.tree.TreeTranslator;
  38 import com.sun.tools.javac.code.Attribute;

  39 import com.sun.tools.javac.code.Symbol;
  40 import com.sun.tools.javac.code.Symbol.ClassSymbol;
  41 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
  42 import com.sun.tools.javac.code.Symbol.MethodSymbol;
  43 import com.sun.tools.javac.code.Symbol.TypeSymbol;
  44 import com.sun.tools.javac.code.Symbol.VarSymbol;
  45 import com.sun.tools.javac.code.Symtab;
  46 import com.sun.tools.javac.code.Type;
  47 import com.sun.tools.javac.code.Type.MethodType;
  48 import com.sun.tools.javac.code.Type.TypeVar;
  49 import com.sun.tools.javac.code.Types;
  50 import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
  51 import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
  52 import com.sun.tools.javac.resources.CompilerProperties.Notes;
  53 import com.sun.tools.javac.jvm.*;
  54 import com.sun.tools.javac.util.*;
  55 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  56 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
  57 
  58 import java.util.EnumMap;


 109     private TranslationContext<?> context;
 110 
 111     /** info about the current class being processed */
 112     private KlassInfo kInfo;
 113 
 114     /** dump statistics about lambda code generation */
 115     private final boolean dumpLambdaToMethodStats;
 116 
 117     /** force serializable representation, for stress testing **/
 118     private final boolean forceSerializable;
 119 
 120     /** true if line or local variable debug info has been requested */
 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) {


 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);
 161         types = Types.instance(context);
 162         transTypes = TransTypes.instance(context);
 163         analyzer = new LambdaAnalyzerPreprocessor();
 164         Options options = Options.instance(context);
 165         dumpLambdaToMethodStats = options.isSet("debug.dumpLambdaToMethodStats");
 166         attr = Attr.instance(context);
 167         forceSerializable = options.isSet("forceSerializable");
 168         debugLinesOrVars = options.isSet(Option.G)
 169                 || options.isSet(Option.G_CUSTOM, "lines")
 170                 || options.isSet(Option.G_CUSTOM, "vars");
 171         verboseDeduplication = options.isSet("debug.dumpLambdaToMethodDeduplication");
 172         deduplicateLambdas = options.getBoolean("deduplicateLambdas", true);
 173         nestmateLambdas = Target.instance(context).runtimeUseNestAccess();
 174     }
 175     // </editor-fold>
 176 
 177     class DedupedLambda {
 178         private final MethodSymbol symbol;
 179         private final JCTree tree;
 180 
 181         private int hashCode;
 182 
 183         DedupedLambda(MethodSymbol symbol, JCTree tree) {
 184             this.symbol = symbol;
 185             this.tree = tree;
 186         }
 187 
 188 
 189         @Override
 190         public int hashCode() {
 191             int hashCode = this.hashCode;
 192             if (hashCode == 0) {
 193                 this.hashCode = hashCode = TreeHasher.hash(tree, symbol.params());


2239             }
2240 
2241             boolean needsVarArgsConversion() {
2242                 return tree.varargsElement != null;
2243             }
2244 
2245             /**
2246              * @return Is this an array operation like clone()
2247              */
2248             boolean isArrayOp() {
2249                 return tree.sym.owner == syms.arrayClass;
2250             }
2251 
2252             boolean receiverAccessible() {
2253                 //hack needed to workaround 292 bug (7087658)
2254                 //when 292 issue is fixed we should remove this and change the backend
2255                 //code to always generate a method handle to an accessible method
2256                 return tree.ownerAccessible;
2257             }
2258 
2259             /**
2260              * This method should be called only when target release <= 14
2261              * where LambdaMetaFactory does not spin nestmate classes.
2262              *
2263              * This method should be removed when --release 14 is not supported.
2264              */
2265             boolean isPrivateInOtherClass() {
2266                 assert !nestmateLambdas;
2267                 return  (tree.sym.flags() & PRIVATE) != 0 &&
2268                         !types.isSameType(
2269                               types.erasure(tree.sym.enclClass().asType()),
2270                               types.erasure(owner.enclClass().asType()));
2271             }
2272 
2273             boolean isProtectedInSuperClassOfEnclosingClassInOtherPackage() {
2274                 return ((tree.sym.flags() & PROTECTED) != 0 &&
2275                         tree.sym.packge() != owner.packge());
2276             }
2277 
2278             /**
2279              * Erasure destroys the implementation parameter subtype
2280              * relationship for intersection types.
2281              * Have similar problems for union types too.
2282              */
2283             boolean interfaceParameterIsIntersectionOrUnionType() {
2284                 List<Type> tl = tree.getDescriptorType(types).getParameterTypes();
2285                 for (; tl.nonEmpty(); tl = tl.tail) {
2286                     Type pt = tl.head;
2287                     return isIntersectionOrUnionType(pt);
2288                 }
2289                 return false;
2290             }
2291 
2292             boolean isIntersectionOrUnionType(Type t) {
2293                 switch (t.getKind()) {
2294                     case INTERSECTION:
2295                     case UNION:
2296                         return true;
2297                     case TYPEVAR:
2298                         TypeVar tv = (TypeVar) t;
2299                         return isIntersectionOrUnionType(tv.getUpperBound());
2300                 }
2301                 return false;
2302             }
2303 
2304             /**
2305              * Does this reference need to be converted to a lambda
2306              * (i.e. var args need to be expanded or "super" is used)
2307              */
2308             final boolean needsConversionToLambda() {
2309                 return interfaceParameterIsIntersectionOrUnionType() ||
2310                         isSuper ||
2311                         needsVarArgsConversion() ||
2312                         isArrayOp() ||
2313                         (!nestmateLambdas && isPrivateInOtherClass()) ||
2314                         isProtectedInSuperClassOfEnclosingClassInOtherPackage() ||
2315                         !receiverAccessible() ||
2316                         (tree.getMode() == ReferenceMode.NEW &&
2317                           tree.kind != ReferenceKind.ARRAY_CTOR &&
2318                           (tree.sym.owner.isLocal() || tree.sym.owner.isInner()));
2319             }
2320 
2321             Type generatedRefSig() {
2322                 return types.erasure(tree.sym.type);
2323             }
2324 
2325             Type bridgedRefSig() {
2326                 return types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
2327             }
2328         }
2329     }
2330     // </editor-fold>
2331 
2332     /*
2333      * These keys provide mappings for various translated lambda symbols


< prev index next >