langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
changeset 42828 cce89649f958
parent 41028 5164e92730d9
child 43148 9d11c46bd7bf
equal deleted inserted replaced
42827:36468b5fa7f4 42828:cce89649f958
   177         private KlassInfo(JCClassDecl clazz) {
   177         private KlassInfo(JCClassDecl clazz) {
   178             this.clazz = clazz;
   178             this.clazz = clazz;
   179             appendedMethodList = new ListBuffer<>();
   179             appendedMethodList = new ListBuffer<>();
   180             deserializeCases = new HashMap<>();
   180             deserializeCases = new HashMap<>();
   181             MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType,
   181             MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType,
   182                     List.<Type>nil(), syms.methodClass);
   182                     List.nil(), syms.methodClass);
   183             deserMethodSym = makePrivateSyntheticMethod(STATIC, names.deserializeLambda, type, clazz.sym);
   183             deserMethodSym = makePrivateSyntheticMethod(STATIC, names.deserializeLambda, type, clazz.sym);
   184             deserParamSym = new VarSymbol(FINAL, names.fromString("lambda"),
   184             deserParamSym = new VarSymbol(FINAL, names.fromString("lambda"),
   185                     syms.serializedLambdaType, deserMethodSym);
   185                     syms.serializedLambdaType, deserMethodSym);
   186         }
   186         }
   187 
   187 
   308 
   308 
   309         //create the method declaration hoisting the lambda body
   309         //create the method declaration hoisting the lambda body
   310         JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
   310         JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field),
   311                 sym.name,
   311                 sym.name,
   312                 make.QualIdent(lambdaType.getReturnType().tsym),
   312                 make.QualIdent(lambdaType.getReturnType().tsym),
   313                 List.<JCTypeParameter>nil(),
   313                 List.nil(),
   314                 localContext.syntheticParams,
   314                 localContext.syntheticParams,
   315                 lambdaType.getThrownTypes() == null ?
   315                 lambdaType.getThrownTypes() == null ?
   316                     List.<JCExpression>nil() :
   316                     List.nil() :
   317                     make.Types(lambdaType.getThrownTypes()),
   317                     make.Types(lambdaType.getThrownTypes()),
   318                 null,
   318                 null,
   319                 null);
   319                 null);
   320         lambdaDecl.sym = sym;
   320         lambdaDecl.sym = sym;
   321         lambdaDecl.type = lambdaType;
   321         lambdaDecl.type = lambdaType;
   445 
   445 
   446             default:
   446             default:
   447                 throw new InternalError("Should not have an invalid kind");
   447                 throw new InternalError("Should not have an invalid kind");
   448         }
   448         }
   449 
   449 
   450         List<JCExpression> indy_args = init==null? List.<JCExpression>nil() : translate(List.of(init), localContext.prev);
   450         List<JCExpression> indy_args = init==null? List.nil() : translate(List.of(init), localContext.prev);
   451 
   451 
   452 
   452 
   453         //build a sam instance using an indy call to the meta-factory
   453         //build a sam instance using an indy call to the meta-factory
   454         result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
   454         result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
   455     }
   455     }
   554         try {
   554         try {
   555             if (isTarget_void) {
   555             if (isTarget_void) {
   556                 //target is void:
   556                 //target is void:
   557                 // BODY;
   557                 // BODY;
   558                 JCStatement stat = make.at(expr).Exec(expr);
   558                 JCStatement stat = make.at(expr).Exec(expr);
   559                 return make.Block(0, List.<JCStatement>of(stat));
   559                 return make.Block(0, List.of(stat));
   560             } else if (isLambda_void && isTarget_Void) {
   560             } else if (isLambda_void && isTarget_Void) {
   561                 //void to Void conversion:
   561                 //void to Void conversion:
   562                 // BODY; return null;
   562                 // BODY; return null;
   563                 ListBuffer<JCStatement> stats = new ListBuffer<>();
   563                 ListBuffer<JCStatement> stats = new ListBuffer<>();
   564                 stats.append(make.at(expr).Exec(expr));
   564                 stats.append(make.at(expr).Exec(expr));
   566                 return make.Block(0, stats.toList());
   566                 return make.Block(0, stats.toList());
   567             } else {
   567             } else {
   568                 //non-void to non-void conversion:
   568                 //non-void to non-void conversion:
   569                 // return (TYPE)BODY;
   569                 // return (TYPE)BODY;
   570                 JCExpression retExpr = transTypes.coerce(attrEnv, expr, restype);
   570                 JCExpression retExpr = transTypes.coerce(attrEnv, expr, restype);
   571                 return make.at(retExpr).Block(0, List.<JCStatement>of(make.Return(retExpr)));
   571                 return make.at(retExpr).Block(0, List.of(make.Return(retExpr)));
   572             }
   572             }
   573         } finally {
   573         } finally {
   574             make.at(prevPos);
   574             make.at(prevPos);
   575         }
   575         }
   576     }
   576     }
   600                 if (isTarget_void && !isLambda_void) {
   600                 if (isTarget_void && !isLambda_void) {
   601                     //Void to void conversion:
   601                     //Void to void conversion:
   602                     // { TYPE $loc = RET-EXPR; return; }
   602                     // { TYPE $loc = RET-EXPR; return; }
   603                     VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym);
   603                     VarSymbol loc = makeSyntheticVar(0, names.fromString("$loc"), tree.expr.type, lambdaMethodDecl.sym);
   604                     JCVariableDecl varDef = make.VarDef(loc, tree.expr);
   604                     JCVariableDecl varDef = make.VarDef(loc, tree.expr);
   605                     result = make.Block(0, List.<JCStatement>of(varDef, make.Return(null)));
   605                     result = make.Block(0, List.of(varDef, make.Return(null)));
   606                 } else if (!isTarget_void || !isLambda_void) {
   606                 } else if (!isTarget_void || !isLambda_void) {
   607                     //non-void to non-void conversion:
   607                     //non-void to non-void conversion:
   608                     // return (TYPE)RET-EXPR;
   608                     // return (TYPE)RET-EXPR;
   609                     tree.expr = transTypes.coerce(attrEnv, tree.expr, restype);
   609                     tree.expr = transTypes.coerce(attrEnv, tree.expr, restype);
   610                     result = tree;
   610                     result = tree;
   635         }
   635         }
   636         JCSwitch sw = make.Switch(deserGetter("getImplMethodName", syms.stringType), cases.toList());
   636         JCSwitch sw = make.Switch(deserGetter("getImplMethodName", syms.stringType), cases.toList());
   637         for (JCBreak br : breaks) {
   637         for (JCBreak br : breaks) {
   638             br.target = sw;
   638             br.target = sw;
   639         }
   639         }
   640         JCBlock body = make.Block(0L, List.<JCStatement>of(
   640         JCBlock body = make.Block(0L, List.of(
   641                 sw,
   641                 sw,
   642                 make.Throw(makeNewClass(
   642                 make.Throw(makeNewClass(
   643                     syms.illegalArgumentExceptionType,
   643                     syms.illegalArgumentExceptionType,
   644                     List.<JCExpression>of(make.Literal("Invalid lambda deserialization"))))));
   644                     List.of(make.Literal("Invalid lambda deserialization"))))));
   645         JCMethodDecl deser = make.MethodDef(make.Modifiers(kInfo.deserMethodSym.flags()),
   645         JCMethodDecl deser = make.MethodDef(make.Modifiers(kInfo.deserMethodSym.flags()),
   646                         names.deserializeLambda,
   646                         names.deserializeLambda,
   647                         make.QualIdent(kInfo.deserMethodSym.getReturnType().tsym),
   647                         make.QualIdent(kInfo.deserMethodSym.getReturnType().tsym),
   648                         List.<JCTypeParameter>nil(),
   648                         List.nil(),
   649                         List.of(make.VarDef(kInfo.deserParamSym, null)),
   649                         List.of(make.VarDef(kInfo.deserParamSym, null)),
   650                         List.<JCExpression>nil(),
   650                         List.nil(),
   651                         body,
   651                         body,
   652                         null);
   652                         null);
   653         deser.sym = kInfo.deserMethodSym;
   653         deser.sym = kInfo.deserMethodSym;
   654         deser.type = kInfo.deserMethodSym.type;
   654         deser.type = kInfo.deserMethodSym.type;
   655         //System.err.printf("DESER: '%s'\n", deser);
   655         //System.err.printf("DESER: '%s'\n", deser);
   673      *  @param ctype    The class type.
   673      *  @param ctype    The class type.
   674      *  @param args     The constructor arguments.
   674      *  @param args     The constructor arguments.
   675      */
   675      */
   676     JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
   676     JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
   677         return makeNewClass(ctype, args,
   677         return makeNewClass(ctype, args,
   678                 rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil()));
   678                 rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.nil()));
   679      }
   679      }
   680 
   680 
   681     private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
   681     private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
   682             DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
   682             DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
   683         String functionalInterfaceClass = classSig(targetType);
   683         String functionalInterfaceClass = classSig(targetType);
   734         testExpr.setType(syms.booleanType);
   734         testExpr.setType(syms.booleanType);
   735         return testExpr;
   735         return testExpr;
   736     }
   736     }
   737 
   737 
   738     private JCExpression deserTest(JCExpression prev, String func, String lit) {
   738     private JCExpression deserTest(JCExpression prev, String func, String lit) {
   739         MethodType eqmt = new MethodType(List.of(syms.objectType), syms.booleanType, List.<Type>nil(), syms.methodClass);
   739         MethodType eqmt = new MethodType(List.of(syms.objectType), syms.booleanType, List.nil(), syms.methodClass);
   740         Symbol eqsym = rs.resolveQualifiedMethod(null, attrEnv, syms.objectType, names.equals, List.of(syms.objectType), List.<Type>nil());
   740         Symbol eqsym = rs.resolveQualifiedMethod(null, attrEnv, syms.objectType, names.equals, List.of(syms.objectType), List.nil());
   741         JCMethodInvocation eqtest = make.Apply(
   741         JCMethodInvocation eqtest = make.Apply(
   742                 List.<JCExpression>nil(),
   742                 List.nil(),
   743                 make.Select(deserGetter(func, syms.stringType), eqsym).setType(eqmt),
   743                 make.Select(deserGetter(func, syms.stringType), eqsym).setType(eqmt),
   744                 List.<JCExpression>of(make.Literal(lit)));
   744                 List.of(make.Literal(lit)));
   745         eqtest.setType(syms.booleanType);
   745         eqtest.setType(syms.booleanType);
   746         JCBinary compound = make.Binary(JCTree.Tag.AND, prev, eqtest);
   746         JCBinary compound = make.Binary(JCTree.Tag.AND, prev, eqtest);
   747         compound.operator = operators.resolveBinary(compound, JCTree.Tag.AND, syms.booleanType, syms.booleanType);
   747         compound.operator = operators.resolveBinary(compound, JCTree.Tag.AND, syms.booleanType, syms.booleanType);
   748         compound.setType(syms.booleanType);
   748         compound.setType(syms.booleanType);
   749         return compound;
   749         return compound;
   750     }
   750     }
   751 
   751 
   752     private JCExpression deserGetter(String func, Type type) {
   752     private JCExpression deserGetter(String func, Type type) {
   753         return deserGetter(func, type, List.<Type>nil(), List.<JCExpression>nil());
   753         return deserGetter(func, type, List.nil(), List.nil());
   754     }
   754     }
   755 
   755 
   756     private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) {
   756     private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) {
   757         MethodType getmt = new MethodType(argTypes, type, List.<Type>nil(), syms.methodClass);
   757         MethodType getmt = new MethodType(argTypes, type, List.nil(), syms.methodClass);
   758         Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.<Type>nil());
   758         Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.nil());
   759         return make.Apply(
   759         return make.Apply(
   760                     List.<JCExpression>nil(),
   760                     List.nil(),
   761                     make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt),
   761                     make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt),
   762                     args).setType(type);
   762                     args).setType(type);
   763     }
   763     }
   764 
   764 
   765     /**
   765     /**
   959             JCFieldAccess select = make.Select(qualifier, tree.sym.name);
   959             JCFieldAccess select = make.Select(qualifier, tree.sym.name);
   960             select.sym = tree.sym;
   960             select.sym = tree.sym;
   961             select.type = tree.sym.erasure(types);
   961             select.type = tree.sym.erasure(types);
   962 
   962 
   963             //create the method call expression
   963             //create the method call expression
   964             JCExpression apply = make.Apply(List.<JCExpression>nil(), select,
   964             JCExpression apply = make.Apply(List.nil(), select,
   965                     convertArgs(tree.sym, args.toList(), tree.varargsElement)).
   965                     convertArgs(tree.sym, args.toList(), tree.varargsElement)).
   966                     setType(tree.sym.erasure(types).getReturnType());
   966                     setType(tree.sym.erasure(types).getReturnType());
   967 
   967 
   968             apply = transTypes.coerce(attrEnv, apply,
   968             apply = transTypes.coerce(attrEnv, apply,
   969                     types.erasure(localContext.tree.referentType.getReturnType()));
   969                     types.erasure(localContext.tree.referentType.getReturnType()));
   987             } else {
   987             } else {
   988                 //create the instance creation expression
   988                 //create the instance creation expression
   989                 //note that method reference syntax does not allow an explicit
   989                 //note that method reference syntax does not allow an explicit
   990                 //enclosing class (so the enclosing class is null)
   990                 //enclosing class (so the enclosing class is null)
   991                 JCNewClass newClass = make.NewClass(null,
   991                 JCNewClass newClass = make.NewClass(null,
   992                         List.<JCExpression>nil(),
   992                         List.nil(),
   993                         make.Type(tree.getQualifierExpression().type),
   993                         make.Type(tree.getQualifierExpression().type),
   994                         convertArgs(tree.sym, args.toList(), tree.varargsElement),
   994                         convertArgs(tree.sym, args.toList(), tree.varargsElement),
   995                         null);
   995                         null);
   996                 newClass.constructor = tree.sym;
   996                 newClass.constructor = tree.sym;
   997                 newClass.constructorType = tree.sym.erasure(types);
   997                 newClass.constructorType = tree.sym.erasure(types);
  1026     private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context,
  1026     private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context,
  1027             int refKind, Symbol refSym, List<JCExpression> indy_args) {
  1027             int refKind, Symbol refSym, List<JCExpression> indy_args) {
  1028         JCFunctionalExpression tree = context.tree;
  1028         JCFunctionalExpression tree = context.tree;
  1029         //determine the static bsm args
  1029         //determine the static bsm args
  1030         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
  1030         MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
  1031         List<Object> staticArgs = List.<Object>of(
  1031         List<Object> staticArgs = List.of(
  1032                 typeToMethodType(samSym.type),
  1032                 typeToMethodType(samSym.type),
  1033                 new Pool.MethodHandle(refKind, refSym, types),
  1033                 new Pool.MethodHandle(refKind, refSym, types),
  1034                 typeToMethodType(tree.getDescriptorType(types)));
  1034                 typeToMethodType(tree.getDescriptorType(types)));
  1035 
  1035 
  1036         //computed indy arg types
  1036         //computed indy arg types
  1040         }
  1040         }
  1041 
  1041 
  1042         //finally, compute the type of the indy call
  1042         //finally, compute the type of the indy call
  1043         MethodType indyType = new MethodType(indy_args_types.toList(),
  1043         MethodType indyType = new MethodType(indy_args_types.toList(),
  1044                 tree.type,
  1044                 tree.type,
  1045                 List.<Type>nil(),
  1045                 List.nil(),
  1046                 syms.methodClass);
  1046                 syms.methodClass);
  1047 
  1047 
  1048         Name metafactoryName = context.needsAltMetafactory() ?
  1048         Name metafactoryName = context.needsAltMetafactory() ?
  1049                 names.altMetafactory : names.metafactory;
  1049                 names.altMetafactory : names.metafactory;
  1050 
  1050 
  1106             List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
  1106             List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
  1107                     syms.stringType,
  1107                     syms.stringType,
  1108                     syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
  1108                     syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
  1109 
  1109 
  1110             Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
  1110             Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
  1111                     bsmName, bsm_staticArgs, List.<Type>nil());
  1111                     bsmName, bsm_staticArgs, List.nil());
  1112 
  1112 
  1113             DynamicMethodSymbol dynSym =
  1113             DynamicMethodSymbol dynSym =
  1114                     new DynamicMethodSymbol(methName,
  1114                     new DynamicMethodSymbol(methName,
  1115                                             syms.noSymbol,
  1115                                             syms.noSymbol,
  1116                                             bsm.isStatic() ?
  1116                                             bsm.isStatic() ?
  1122 
  1122 
  1123             JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
  1123             JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
  1124             qualifier.sym = dynSym;
  1124             qualifier.sym = dynSym;
  1125             qualifier.type = indyType.getReturnType();
  1125             qualifier.type = indyType.getReturnType();
  1126 
  1126 
  1127             JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, indyArgs);
  1127             JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, indyArgs);
  1128             proxyCall.type = indyType.getReturnType();
  1128             proxyCall.type = indyType.getReturnType();
  1129             return proxyCall;
  1129             return proxyCall;
  1130         } finally {
  1130         } finally {
  1131             make.at(prevPos);
  1131             make.at(prevPos);
  1132         }
  1132         }
  1620                 if (clinit == null) {
  1620                 if (clinit == null) {
  1621                     /* no luck, let's create a new one
  1621                     /* no luck, let's create a new one
  1622                      */
  1622                      */
  1623                     clinit = makePrivateSyntheticMethod(STATIC,
  1623                     clinit = makePrivateSyntheticMethod(STATIC,
  1624                             names.clinit,
  1624                             names.clinit,
  1625                             new MethodType(List.<Type>nil(), syms.voidType,
  1625                             new MethodType(List.nil(), syms.voidType,
  1626                                 List.<Type>nil(), syms.methodClass),
  1626                                 List.nil(), syms.methodClass),
  1627                             csym);
  1627                             csym);
  1628                     clinits.put(csym, clinit);
  1628                     clinits.put(csym, clinit);
  1629                 }
  1629                 }
  1630                 return clinit;
  1630                 return clinit;
  1631             } else {
  1631             } else {