< prev index next >

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

Print this page

 350             boolean init;
 351             if ((init = (owner.name == names.init)) || owner.name == names.clinit) {
 352                 owner = owner.owner;
 353                 apportionTypeAnnotations(tree,
 354                         init ? owner::getInitTypeAttributes : owner::getClassInitTypeAttributes,
 355                         init ? owner::setInitTypeAttributes : owner::setClassInitTypeAttributes,
 356                         sym::appendUniqueTypeAttributes);
 357             }
 358             if (localContext.self != null && localContext.self.getKind() == ElementKind.FIELD) {
 359                 owner = localContext.self;
 360                 apportionTypeAnnotations(tree,
 361                         owner::getRawTypeAttributes,
 362                         owner::setTypeAttributes,
 363                         sym::appendUniqueTypeAttributes);
 364             }
 365         }
 366 
 367         //create the method declaration hoisting the lambda body
 368         JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
 369                 sym.name,
 370                 make.QualIdent(lambdaType.getReturnType().tsym),
 371                 List.nil(),
 372                 localContext.syntheticParams,
 373                 lambdaType.getThrownTypes() == null ?
 374                     List.nil() :
 375                     make.Types(lambdaType.getThrownTypes()),
 376                 null,
 377                 null);
 378         lambdaDecl.sym = sym;
 379         lambdaDecl.type = lambdaType;
 380 
 381         //translate lambda body
 382         //As the lambda body is translated, all references to lambda locals,
 383         //captured variables, enclosing members are adjusted accordingly
 384         //to refer to the static method parameters (rather than i.e. accessing
 385         //captured members directly).
 386         lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
 387 
 388         boolean dedupe = false;
 389         if (deduplicateLambdas && !debugLinesOrVars && !localContext.isSerializable()) {
 390             DedupedLambda dedupedLambda = new DedupedLambda(lambdaDecl.sym, lambdaDecl.body);

1833                 this.owner = owner(true);
1834                 this.depth = frameStack.size() - 1;
1835                 this.prev = context();
1836                 ClassSymbol csym =
1837                         types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
1838                 this.bridges = types.functionalInterfaceBridges(csym);
1839             }
1840 
1841             /** does this functional expression need to be created using alternate metafactory? */
1842             boolean needsAltMetafactory() {
1843                 return tree.target.isIntersection() ||
1844                         isSerializable() ||
1845                         bridges.length() > 1;
1846             }
1847 
1848             /** does this functional expression require serialization support? */
1849             boolean isSerializable() {
1850                 if (forceSerializable) {
1851                     return true;
1852                 }
1853                 return types.asSuper(tree.target, syms.serializableType.tsym) != null;
1854             }
1855 
1856             /**
1857              * @return Name of the enclosing method to be folded into synthetic
1858              * method name
1859              */
1860             String enclosingMethodName() {
1861                 return syntheticMethodNameComponent(owner.name);
1862             }
1863 
1864             /**
1865              * @return Method name in a form that can be folded into a
1866              * component of a synthetic method name
1867              */
1868             String syntheticMethodNameComponent(Name name) {
1869                 if (name == null) {
1870                     return "null";
1871                 }
1872                 String methodName = name.toString();
1873                 if (methodName.equals("<clinit>")) {

2256             }
2257 
2258             boolean needsVarArgsConversion() {
2259                 return tree.varargsElement != null;
2260             }
2261 
2262             /**
2263              * @return Is this an array operation like clone()
2264              */
2265             boolean isArrayOp() {
2266                 return tree.sym.owner == syms.arrayClass;
2267             }
2268 
2269             boolean receiverAccessible() {
2270                 //hack needed to workaround 292 bug (7087658)
2271                 //when 292 issue is fixed we should remove this and change the backend
2272                 //code to always generate a method handle to an accessible method
2273                 return tree.ownerAccessible;
2274             }
2275 








2276             /**
2277              * This method should be called only when target release <= 14
2278              * where LambdaMetaFactory does not spin nestmate classes.
2279              *
2280              * This method should be removed when --release 14 is not supported.
2281              */
2282             boolean isPrivateInOtherClass() {
2283                 assert !nestmateLambdas;
2284                 return  (tree.sym.flags() & PRIVATE) != 0 &&
2285                         !types.isSameType(
2286                               types.erasure(tree.sym.enclClass().asType()),
2287                               types.erasure(owner.enclClass().asType()));
2288             }
2289 
2290             /**
2291              * Erasure destroys the implementation parameter subtype
2292              * relationship for intersection types.
2293              * Have similar problems for union types too.
2294              */
2295             boolean interfaceParameterIsIntersectionOrUnionType() {

2308                         return true;
2309                     case TYPEVAR:
2310                         TypeVar tv = (TypeVar) t;
2311                         return isIntersectionOrUnionType(tv.getUpperBound());
2312                 }
2313                 return false;
2314             }
2315 
2316             /**
2317              * Does this reference need to be converted to a lambda
2318              * (i.e. var args need to be expanded or "super" is used)
2319              */
2320             final boolean needsConversionToLambda() {
2321                 return interfaceParameterIsIntersectionOrUnionType() ||
2322                         isSuper ||
2323                         needsVarArgsConversion() ||
2324                         isArrayOp() ||
2325                         (!nestmateLambdas && isPrivateInOtherClass()) ||
2326                         isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, owner) ||
2327                         !receiverAccessible() ||

2328                         (tree.getMode() == ReferenceMode.NEW &&
2329                           tree.kind != ReferenceKind.ARRAY_CTOR &&
2330                           (tree.sym.owner.isDirectlyOrIndirectlyLocal() || tree.sym.owner.isInner()));
2331             }
2332 
2333             Type generatedRefSig() {
2334                 return types.erasure(tree.sym.type);
2335             }
2336 
2337             Type bridgedRefSig() {
2338                 return types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
2339             }
2340         }
2341     }
2342     // </editor-fold>
2343 
2344     /*
2345      * These keys provide mappings for various translated lambda symbols
2346      * and the prevailing order must be maintained.
2347      */
2348     enum LambdaSymbolKind {
2349         PARAM,          // original to translated lambda parameters
2350         LOCAL_VAR,      // original to translated lambda locals

 350             boolean init;
 351             if ((init = (owner.name == names.init)) || owner.name == names.clinit) {
 352                 owner = owner.owner;
 353                 apportionTypeAnnotations(tree,
 354                         init ? owner::getInitTypeAttributes : owner::getClassInitTypeAttributes,
 355                         init ? owner::setInitTypeAttributes : owner::setClassInitTypeAttributes,
 356                         sym::appendUniqueTypeAttributes);
 357             }
 358             if (localContext.self != null && localContext.self.getKind() == ElementKind.FIELD) {
 359                 owner = localContext.self;
 360                 apportionTypeAnnotations(tree,
 361                         owner::getRawTypeAttributes,
 362                         owner::setTypeAttributes,
 363                         sym::appendUniqueTypeAttributes);
 364             }
 365         }
 366 
 367         //create the method declaration hoisting the lambda body
 368         JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
 369                 sym.name,
 370                 make.QualIdent(lambdaType.getReturnType().tsym).setType(lambdaType.getReturnType()),
 371                 List.nil(),
 372                 localContext.syntheticParams,
 373                 lambdaType.getThrownTypes() == null ?
 374                     List.nil() :
 375                     make.Types(lambdaType.getThrownTypes()),
 376                 null,
 377                 null);
 378         lambdaDecl.sym = sym;
 379         lambdaDecl.type = lambdaType;
 380 
 381         //translate lambda body
 382         //As the lambda body is translated, all references to lambda locals,
 383         //captured variables, enclosing members are adjusted accordingly
 384         //to refer to the static method parameters (rather than i.e. accessing
 385         //captured members directly).
 386         lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
 387 
 388         boolean dedupe = false;
 389         if (deduplicateLambdas && !debugLinesOrVars && !localContext.isSerializable()) {
 390             DedupedLambda dedupedLambda = new DedupedLambda(lambdaDecl.sym, lambdaDecl.body);

1833                 this.owner = owner(true);
1834                 this.depth = frameStack.size() - 1;
1835                 this.prev = context();
1836                 ClassSymbol csym =
1837                         types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.target, ABSTRACT | INTERFACE);
1838                 this.bridges = types.functionalInterfaceBridges(csym);
1839             }
1840 
1841             /** does this functional expression need to be created using alternate metafactory? */
1842             boolean needsAltMetafactory() {
1843                 return tree.target.isIntersection() ||
1844                         isSerializable() ||
1845                         bridges.length() > 1;
1846             }
1847 
1848             /** does this functional expression require serialization support? */
1849             boolean isSerializable() {
1850                 if (forceSerializable) {
1851                     return true;
1852                 }
1853                 return types.asSuper(tree.target.referenceProjectionOrSelf(), syms.serializableType.tsym) != null;
1854             }
1855 
1856             /**
1857              * @return Name of the enclosing method to be folded into synthetic
1858              * method name
1859              */
1860             String enclosingMethodName() {
1861                 return syntheticMethodNameComponent(owner.name);
1862             }
1863 
1864             /**
1865              * @return Method name in a form that can be folded into a
1866              * component of a synthetic method name
1867              */
1868             String syntheticMethodNameComponent(Name name) {
1869                 if (name == null) {
1870                     return "null";
1871                 }
1872                 String methodName = name.toString();
1873                 if (methodName.equals("<clinit>")) {

2256             }
2257 
2258             boolean needsVarArgsConversion() {
2259                 return tree.varargsElement != null;
2260             }
2261 
2262             /**
2263              * @return Is this an array operation like clone()
2264              */
2265             boolean isArrayOp() {
2266                 return tree.sym.owner == syms.arrayClass;
2267             }
2268 
2269             boolean receiverAccessible() {
2270                 //hack needed to workaround 292 bug (7087658)
2271                 //when 292 issue is fixed we should remove this and change the backend
2272                 //code to always generate a method handle to an accessible method
2273                 return tree.ownerAccessible;
2274             }
2275 
2276             /* Workaround to BootstrapMethodError. This workaround should not be required in the unified
2277                class generation model, but seems to be required ...
2278                Todo: Investigate to see if a defect should be reported against runtime lambda machinery
2279             */
2280             boolean receiverIsReferenceProjection() {
2281                 return tree.getQualifierExpression().type.isPrimitiveReferenceType();
2282             }
2283 
2284             /**
2285              * This method should be called only when target release <= 14
2286              * where LambdaMetaFactory does not spin nestmate classes.
2287              *
2288              * This method should be removed when --release 14 is not supported.
2289              */
2290             boolean isPrivateInOtherClass() {
2291                 assert !nestmateLambdas;
2292                 return  (tree.sym.flags() & PRIVATE) != 0 &&
2293                         !types.isSameType(
2294                               types.erasure(tree.sym.enclClass().asType()),
2295                               types.erasure(owner.enclClass().asType()));
2296             }
2297 
2298             /**
2299              * Erasure destroys the implementation parameter subtype
2300              * relationship for intersection types.
2301              * Have similar problems for union types too.
2302              */
2303             boolean interfaceParameterIsIntersectionOrUnionType() {

2316                         return true;
2317                     case TYPEVAR:
2318                         TypeVar tv = (TypeVar) t;
2319                         return isIntersectionOrUnionType(tv.getUpperBound());
2320                 }
2321                 return false;
2322             }
2323 
2324             /**
2325              * Does this reference need to be converted to a lambda
2326              * (i.e. var args need to be expanded or "super" is used)
2327              */
2328             final boolean needsConversionToLambda() {
2329                 return interfaceParameterIsIntersectionOrUnionType() ||
2330                         isSuper ||
2331                         needsVarArgsConversion() ||
2332                         isArrayOp() ||
2333                         (!nestmateLambdas && isPrivateInOtherClass()) ||
2334                         isProtectedInSuperClassOfEnclosingClassInOtherPackage(tree.sym, owner) ||
2335                         !receiverAccessible() ||
2336                         receiverIsReferenceProjection() ||
2337                         (tree.getMode() == ReferenceMode.NEW &&
2338                           tree.kind != ReferenceKind.ARRAY_CTOR &&
2339                           (tree.sym.owner.isDirectlyOrIndirectlyLocal() || tree.sym.owner.isInner() || tree.sym.owner.isPrimitiveClass()));
2340             }
2341 
2342             Type generatedRefSig() {
2343                 return types.erasure(tree.sym.type);
2344             }
2345 
2346             Type bridgedRefSig() {
2347                 return types.erasure(types.findDescriptorSymbol(tree.target.tsym).type);
2348             }
2349         }
2350     }
2351     // </editor-fold>
2352 
2353     /*
2354      * These keys provide mappings for various translated lambda symbols
2355      * and the prevailing order must be maintained.
2356      */
2357     enum LambdaSymbolKind {
2358         PARAM,          // original to translated lambda parameters
2359         LOCAL_VAR,      // original to translated lambda locals
< prev index next >