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
|