提交 2fa9337d 编写于 作者: M mcimadamore

8078093: Severe compiler performance regression Java 7 to 8 for nested method invocations

Summary: Add infrastructure to avoid combinatorial explosion of method argument attributions
Reviewed-by: jlahoda, vromero, dlsmith
上级 3adc82c1
......@@ -3152,10 +3152,20 @@ public class Types {
throw new IllegalArgumentException("Not a method type: " + t);
}
public Type visitMethodType(MethodType t, Type newReturn) {
return new MethodType(t.argtypes, newReturn, t.thrown, t.tsym);
return new MethodType(t.argtypes, newReturn, t.thrown, t.tsym) {
@Override
public Type baseType() {
return t;
}
};
}
public Type visitForAll(ForAll t, Type newReturn) {
return new ForAll(t.tvars, t.qtype.accept(this, newReturn));
return new ForAll(t.tvars, t.qtype.accept(this, newReturn)) {
@Override
public Type baseType() {
return t;
}
};
}
};
......
......@@ -108,6 +108,7 @@ public class Attr extends JCTree.Visitor {
final TypeEnvs typeEnvs;
final Dependencies dependencies;
final Annotate annotate;
final ArgumentAttr argumentAttr;
public static Attr instance(Context context) {
Attr instance = context.get(attrKey);
......@@ -142,6 +143,7 @@ public class Attr extends JCTree.Visitor {
deferredLintHandler = DeferredLintHandler.instance(context);
typeEnvs = TypeEnvs.instance(context);
dependencies = Dependencies.instance(context);
argumentAttr = ArgumentAttr.instance(context);
Options options = Options.instance(context);
......@@ -160,7 +162,7 @@ public class Attr extends JCTree.Visitor {
statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType);
unknownAnyPolyInfo = new ResultInfo(KindSelector.VAL, Infer.anyPoly);
methodAttrInfo = new MethodAttrInfo();
unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType);
unknownTypeExprInfo = new ResultInfo(KindSelector.VAL_TYP, Type.noType);
recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext);
......@@ -488,6 +490,10 @@ public class Attr extends JCTree.Visitor {
this.checkMode = checkMode;
}
protected void attr(JCTree tree, Env<AttrContext> env) {
tree.accept(Attr.this);
}
protected Type check(final DiagnosticPosition pos, final Type found) {
return chk.checkType(pos, found, pt, checkContext);
}
......@@ -522,6 +528,41 @@ public class Attr extends JCTree.Visitor {
}
}
class MethodAttrInfo extends ResultInfo {
public MethodAttrInfo() {
this(chk.basicHandler);
}
public MethodAttrInfo(CheckContext checkContext) {
super(KindSelector.VAL, Infer.anyPoly, checkContext);
}
@Override
protected void attr(JCTree tree, Env<AttrContext> env) {
result = argumentAttr.attribArg(tree, env);
}
protected ResultInfo dup(Type newPt) {
throw new IllegalStateException();
}
protected ResultInfo dup(CheckContext newContext) {
return new MethodAttrInfo(newContext);
}
protected ResultInfo dup(Type newPt, CheckContext newContext) {
throw new IllegalStateException();
}
protected ResultInfo dup(Type newPt, CheckContext newContext, CheckMode newMode) {
throw new IllegalStateException();
}
protected ResultInfo dup(CheckMode newMode) {
throw new IllegalStateException();
}
}
class RecoveryInfo extends ResultInfo {
public RecoveryInfo(final DeferredAttr.DeferredAttrContext deferredAttrContext) {
......@@ -545,7 +586,7 @@ public class Attr extends JCTree.Visitor {
final ResultInfo statInfo;
final ResultInfo varAssignmentInfo;
final ResultInfo unknownAnyPolyInfo;
final ResultInfo methodAttrInfo;
final ResultInfo unknownExprInfo;
final ResultInfo unknownTypeInfo;
final ResultInfo unknownTypeExprInfo;
......@@ -588,7 +629,7 @@ public class Attr extends JCTree.Visitor {
try {
this.env = env;
this.resultInfo = resultInfo;
tree.accept(this);
resultInfo.attr(tree, env);
if (tree == breakTree &&
resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
throw new BreakAttr(copyEnv(env));
......@@ -684,12 +725,9 @@ public class Attr extends JCTree.Visitor {
KindSelector attribArgs(KindSelector initialKind, List<JCExpression> trees, Env<AttrContext> env, ListBuffer<Type> argtypes) {
KindSelector kind = initialKind;
for (JCExpression arg : trees) {
Type argtype;
if (allowPoly && deferredAttr.isDeferred(env, arg)) {
argtype = deferredAttr.new DeferredType(arg, env);
Type argtype = chk.checkNonVoid(arg, attribTree(arg, env, allowPoly ? methodAttrInfo : unknownExprInfo));
if (argtype.hasTag(DEFERRED)) {
kind = KindSelector.of(KindSelector.POLY, kind);
} else {
argtype = chk.checkNonVoid(arg, attribTree(arg, env, unknownAnyPolyInfo));
}
argtypes.append(argtype);
}
......@@ -1426,12 +1464,12 @@ public class Attr extends JCTree.Visitor {
Type condtype = attribExpr(tree.cond, env, syms.booleanType);
tree.polyKind = (!allowPoly ||
pt().hasTag(NONE) && pt() != Type.recoveryType ||
pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly ||
isBooleanOrNumeric(env, tree)) ?
PolyKind.STANDALONE : PolyKind.POLY;
if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
//cannot get here (i.e. it means we are returning from void method - which is already an error)
//this means we are returning a poly conditional from void-compatible lambda expression
resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void"));
result = tree.type = types.createErrorType(resultInfo.pt);
return;
......@@ -1439,15 +1477,7 @@ public class Attr extends JCTree.Visitor {
ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
unknownExprInfo :
resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
//this will use enclosing check context to check compatibility of
//subexpression against target type; if we are in a method check context,
//depending on whether boxing is allowed, we could have incompatibilities
@Override
public void report(DiagnosticPosition pos, JCDiagnostic details) {
enclosingContext.report(pos, diags.fragment("incompatible.type.in.conditional", details));
}
});
resultInfo.dup(conditionalContext(resultInfo.checkContext));
Type truetype = attribTree(tree.truepart, env, condInfo);
Type falsetype = attribTree(tree.falsepart, env, condInfo);
......@@ -1506,6 +1536,18 @@ public class Attr extends JCTree.Visitor {
}
};
CheckContext conditionalContext(CheckContext checkContext) {
return new Check.NestedCheckContext(checkContext) {
//this will use enclosing check context to check compatibility of
//subexpression against target type; if we are in a method check context,
//depending on whether boxing is allowed, we could have incompatibilities
@Override
public void report(DiagnosticPosition pos, JCDiagnostic details) {
enclosingContext.report(pos, diags.fragment("incompatible.type.in.conditional", details));
}
};
}
/** Compute the type of a conditional expression, after
* checking that it exists. See JLS 15.25. Does not take into
* account the special case where condition and both arms
......@@ -2070,13 +2112,8 @@ public class Attr extends JCTree.Visitor {
tree.constructor = constructor.baseSymbol();
final TypeSymbol csym = clazztype.tsym;
ResultInfo diamondResult = new ResultInfo(pkind, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) {
@Override
public void report(DiagnosticPosition _unused, JCDiagnostic details) {
enclosingContext.report(tree.clazz,
diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", csym), details));
}
}, CheckMode.NO_TREE_UPDATE);
ResultInfo diamondResult = new ResultInfo(pkind, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes),
diamondContext(tree, csym, resultInfo.checkContext), CheckMode.NO_TREE_UPDATE);
Type constructorType = tree.constructorType = types.createErrorType(clazztype);
constructorType = checkId(tree, site,
constructor,
......@@ -2261,6 +2298,16 @@ public class Attr extends JCTree.Visitor {
chk.validate(tree.typeargs, localEnv);
}
CheckContext diamondContext(JCNewClass clazz, TypeSymbol tsym, CheckContext checkContext) {
return new Check.NestedCheckContext(checkContext) {
@Override
public void report(DiagnosticPosition _unused, JCDiagnostic details) {
enclosingContext.report(clazz.clazz,
diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", tsym), details));
}
};
}
/** Make an attributed null check tree.
*/
public JCExpression makeNullCheck(JCExpression arg) {
......@@ -2330,8 +2377,7 @@ public class Attr extends JCTree.Visitor {
boolean needsRecovery =
resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK;
try {
Type currentTarget = pt();
if (needsRecovery && isSerializable(currentTarget)) {
if (needsRecovery && isSerializable(pt())) {
localEnv.info.isSerializable = true;
}
List<Type> explicitParamTypes = null;
......@@ -2341,22 +2387,13 @@ public class Attr extends JCTree.Visitor {
explicitParamTypes = TreeInfo.types(that.params);
}
Type lambdaType;
if (pt() != Type.recoveryType) {
/* We need to adjust the target. If the target is an
* intersection type, for example: SAM & I1 & I2 ...
* the target will be updated to SAM
*/
currentTarget = targetChecker.visit(currentTarget, that);
if (explicitParamTypes != null) {
currentTarget = infer.instantiateFunctionalInterface(that,
currentTarget, explicitParamTypes, resultInfo.checkContext);
}
currentTarget = types.removeWildcards(currentTarget);
lambdaType = types.findDescriptorType(currentTarget);
} else {
currentTarget = Type.recoveryType;
lambdaType = fallbackDescriptorType(that);
TargetInfo targetInfo = getTargetInfo(that, resultInfo, explicitParamTypes);
Type currentTarget = targetInfo.target;
Type lambdaType = targetInfo.descriptor;
if (currentTarget.isErroneous()) {
result = that.type = currentTarget;
return;
}
setFunctionalInfo(localEnv, that, pt(), lambdaType, currentTarget, resultInfo.checkContext);
......@@ -2409,15 +2446,8 @@ public class Attr extends JCTree.Visitor {
//with the target-type, it will be recovered anyway in Attr.checkId
needsRecovery = false;
FunctionalReturnContext funcContext = that.getBodyKind() == JCLambda.BodyKind.EXPRESSION ?
new ExpressionLambdaReturnContext((JCExpression)that.getBody(), resultInfo.checkContext) :
new FunctionalReturnContext(resultInfo.checkContext);
ResultInfo bodyResultInfo = lambdaType.getReturnType() == Type.recoveryType ?
recoveryInfo :
new ResultInfo(KindSelector.VAL,
lambdaType.getReturnType(), funcContext);
localEnv.info.returnResult = bodyResultInfo;
ResultInfo bodyResultInfo = localEnv.info.returnResult =
lambdaBodyResult(that, lambdaType, resultInfo);
if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
attribTree(that.getBody(), localEnv, bodyResultInfo);
......@@ -2467,6 +2497,44 @@ public class Attr extends JCTree.Visitor {
}
}
//where
class TargetInfo {
Type target;
Type descriptor;
public TargetInfo(Type target, Type descriptor) {
this.target = target;
this.descriptor = descriptor;
}
}
TargetInfo getTargetInfo(JCPolyExpression that, ResultInfo resultInfo, List<Type> explicitParamTypes) {
Type lambdaType;
Type currentTarget = resultInfo.pt;
if (resultInfo.pt != Type.recoveryType) {
/* We need to adjust the target. If the target is an
* intersection type, for example: SAM & I1 & I2 ...
* the target will be updated to SAM
*/
currentTarget = targetChecker.visit(currentTarget, that);
if (explicitParamTypes != null) {
currentTarget = infer.instantiateFunctionalInterface(that,
currentTarget, explicitParamTypes, resultInfo.checkContext);
}
currentTarget = types.removeWildcards(currentTarget);
lambdaType = types.findDescriptorType(currentTarget);
} else {
currentTarget = Type.recoveryType;
lambdaType = fallbackDescriptorType(that);
}
if (that.hasTag(LAMBDA) && lambdaType.hasTag(FORALL)) {
//lambda expression target desc cannot be a generic method
resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target",
lambdaType, kindName(currentTarget.tsym), currentTarget.tsym));
currentTarget = types.createErrorType(pt());
}
return new TargetInfo(currentTarget, lambdaType);
}
void preFlow(JCLambda tree) {
new PostAttrAnalyzer() {
@Override
......@@ -2612,13 +2680,24 @@ public class Attr extends JCTree.Visitor {
}
}
ResultInfo lambdaBodyResult(JCLambda that, Type descriptor, ResultInfo resultInfo) {
FunctionalReturnContext funcContext = that.getBodyKind() == JCLambda.BodyKind.EXPRESSION ?
new ExpressionLambdaReturnContext((JCExpression)that.getBody(), resultInfo.checkContext) :
new FunctionalReturnContext(resultInfo.checkContext);
return descriptor.getReturnType() == Type.recoveryType ?
recoveryInfo :
new ResultInfo(KindSelector.VAL,
descriptor.getReturnType(), funcContext);
}
/**
* Lambda compatibility. Check that given return types, thrown types, parameter types
* are compatible with the expected functional interface descriptor. This means that:
* (i) parameter types must be identical to those of the target descriptor; (ii) return
* types must be compatible with the return type of the expected descriptor.
*/
private void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext) {
void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext) {
Type returnType = checkContext.inferenceContext().asUndetVar(descriptor.getReturnType());
//return values have already been checked - but if lambda has no return
......@@ -2746,18 +2825,12 @@ public class Attr extends JCTree.Visitor {
typeargtypes = attribTypes(that.typeargs, localEnv);
}
Type desc;
Type currentTarget = pt();
boolean isTargetSerializable =
resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK &&
isSerializable(currentTarget);
if (currentTarget != Type.recoveryType) {
currentTarget = types.removeWildcards(targetChecker.visit(currentTarget, that));
desc = types.findDescriptorType(currentTarget);
} else {
currentTarget = Type.recoveryType;
desc = fallbackDescriptorType(that);
}
isSerializable(pt());
TargetInfo targetInfo = getTargetInfo(that, resultInfo, null);
Type currentTarget = targetInfo.target;
Type desc = targetInfo.descriptor;
setFunctionalInfo(localEnv, that, pt(), desc, currentTarget, resultInfo.checkContext);
List<Type> argtypes = desc.getParameterTypes();
......@@ -3279,7 +3352,7 @@ public class Attr extends JCTree.Visitor {
}
// Attribute the qualifier expression, and determine its symbol (if any).
Type site = attribTree(tree.selected, env, new ResultInfo(skind, Infer.anyPoly));
Type site = attribTree(tree.selected, env, new ResultInfo(skind, Type.noType));
if (!pkind().contains(KindSelector.TYP_PCK))
site = capture(site); // Capture field access
......@@ -3884,8 +3957,15 @@ public class Attr extends JCTree.Visitor {
syms.methodClass);
}
return chk.checkMethod(owntype, sym, env, argtrees, argtypes, env.info.lastResolveVarargs(),
resultInfo.checkContext.inferenceContext());
PolyKind pkind = (sym.type.hasTag(FORALL) &&
sym.type.getReturnType().containsAny(((ForAll)sym.type).tvars)) ?
PolyKind.POLY : PolyKind.STANDALONE;
TreeInfo.setPolyKind(env.tree, pkind);
return (resultInfo.pt == Infer.anyPoly) ?
owntype :
chk.checkMethod(owntype, sym, env, argtrees, argtypes, env.info.lastResolveVarargs(),
resultInfo.checkContext.inferenceContext());
} catch (Infer.InferenceException ex) {
//invalid target type - propagate exception outwards or report error
//depending on the current check context
......
......@@ -49,7 +49,6 @@ import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
import com.sun.tools.javac.comp.Infer.FreeTypeListener;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Flags.ANNOTATION;
......@@ -976,10 +975,6 @@ public class Check {
TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype));
}
}
PolyKind pkind = (sym.type.hasTag(FORALL) &&
sym.type.getReturnType().containsAny(((ForAll)sym.type).tvars)) ?
PolyKind.POLY : PolyKind.STANDALONE;
TreeInfo.setPolyKind(env.tree, pkind);
return owntype;
}
//where
......
......@@ -37,6 +37,7 @@ import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph;
import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node;
import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
......@@ -179,7 +180,11 @@ public class Infer {
resolveContext.methodCheck.argumentsAcceptable(env, deferredAttrContext, //B2
argtypes, mt.getParameterTypes(), warn);
if (allowGraphInference &&
if (allowGraphInference && resultInfo != null && resultInfo.pt == anyPoly) {
//we are inside method attribution - just return a partially inferred type
return new PartiallyInferredMethodType(mt, inferenceContext, env, warn);
} else if (allowGraphInference &&
resultInfo != null &&
!warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
//inject return constraints earlier
......@@ -238,6 +243,73 @@ public class Infer {
}
}
/**
* A partially infered method/constructor type; such a type can be checked multiple times
* against different targets.
*/
public class PartiallyInferredMethodType extends MethodType {
public PartiallyInferredMethodType(MethodType mtype, InferenceContext inferenceContext, Env<AttrContext> env, Warner warn) {
super(mtype.getParameterTypes(), mtype.getReturnType(), mtype.getThrownTypes(), mtype.tsym);
this.inferenceContext = inferenceContext;
this.env = env;
this.warn = warn;
}
/** The inference context. */
final InferenceContext inferenceContext;
/** The attribution environment. */
Env<AttrContext> env;
/** The warner. */
final Warner warn;
@Override
public boolean isPartial() {
return true;
}
/**
* Checks this type against a target; this means generating return type constraints, solve
* and then roll back the results (to avoid poolluting the context).
*/
Type check(Attr.ResultInfo resultInfo) {
Warner noWarnings = new Warner(null);
inferenceException.clear();
List<Type> saved_undet = null;
try {
/** we need to save the inference context before generating target type constraints.
* This constraints may pollute the inference context and make it useless in case we
* need to use it several times: with several targets.
*/
saved_undet = inferenceContext.save();
if (allowGraphInference && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
//inject return constraints earlier
checkWithinBounds(inferenceContext, noWarnings); //propagation
Type res = generateReturnConstraints(env.tree, resultInfo, //B3
this, inferenceContext);
if (resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
//propagate inference context outwards and exit
inferenceContext.dupTo(resultInfo.checkContext.inferenceContext(),
resultInfo.checkContext.deferredAttrContext().insideOverloadPhase());
return res;
}
}
inferenceContext.solve(noWarnings);
return inferenceContext.asInstType(this).getReturnType();
} catch (InferenceException ex) {
resultInfo.checkContext.report(null, ex.getDiagnostic());
Assert.error(); //cannot get here (the above should throw)
return null;
} finally {
if (saved_undet != null) {
inferenceContext.rollback(saved_undet);
}
}
}
}
private void dumpGraphsIfNeeded(DiagnosticPosition pos, Symbol msym, Resolve.MethodResolutionContext rsContext) {
int round = 0;
try {
......
......@@ -315,31 +315,46 @@ class InferenceContext {
return buf.toList();
}
/**
* Restore the state of this inference context to the previous known checkpoint
*/
/** Restore the state of this inference context to the previous known checkpoint.
* Consider that the number of saved undetermined variables can be different to the current
* amount. This is because new captured variables could have been added.
*/
void rollback(List<Type> saved_undet) {
Assert.check(saved_undet != null && saved_undet.length() == undetvars.length());
Assert.check(saved_undet != null);
//restore bounds (note: we need to preserve the old instances)
for (Type t : undetvars) {
UndetVar uv = (UndetVar)t;
ListBuffer<Type> newUndetVars = new ListBuffer<>();
ListBuffer<Type> newInferenceVars = new ListBuffer<>();
while (saved_undet.nonEmpty() && undetvars.nonEmpty()) {
UndetVar uv = (UndetVar)undetvars.head;
UndetVar uv_saved = (UndetVar)saved_undet.head;
for (InferenceBound ib : InferenceBound.values()) {
uv.setBounds(ib, uv_saved.getBounds(ib));
if (uv.qtype == uv_saved.qtype) {
for (InferenceBound ib : InferenceBound.values()) {
uv.setBounds(ib, uv_saved.getBounds(ib));
}
uv.inst = uv_saved.inst;
undetvars = undetvars.tail;
saved_undet = saved_undet.tail;
newUndetVars.add(uv);
newInferenceVars.add(uv.qtype);
} else {
undetvars = undetvars.tail;
}
uv.inst = uv_saved.inst;
saved_undet = saved_undet.tail;
}
undetvars = newUndetVars.toList();
inferencevars = newInferenceVars.toList();
}
/**
* Copy variable in this inference context to the given context
*/
void dupTo(final InferenceContext that) {
that.inferencevars = that.inferencevars.appendList(
inferencevars.diff(that.inferencevars));
that.undetvars = that.undetvars.appendList(
undetvars.diff(that.undetvars));
dupTo(that, false);
}
void dupTo(final InferenceContext that, boolean clone) {
that.inferencevars = that.inferencevars.appendList(inferencevars.diff(that.inferencevars));
List<Type> undetsToPropagate = clone ? save() : undetvars;
that.undetvars = that.undetvars.appendList(undetsToPropagate.diff(that.undetvars)); //propagate cloned undet!!
//set up listeners to notify original inference contexts as
//propagated vars are inferred in new context
for (Type t : inferencevars) {
......
......@@ -588,7 +588,8 @@ public class Resolve {
MethodResolutionContext prevContext = currentResolutionContext;
try {
currentResolutionContext = new MethodResolutionContext();
currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK;
currentResolutionContext.attrMode = (resultInfo.pt == Infer.anyPoly) ?
AttrMode.SPECULATIVE : DeferredAttr.AttrMode.CHECK;
if (env.tree.hasTag(JCTree.Tag.REFERENCE)) {
//method/constructor references need special check class
//to handle inference variables in 'argtypes' (might happen
......@@ -1032,6 +1033,11 @@ public class Resolve {
protected ResultInfo dup(CheckContext newContext) {
return new MethodResultInfo(pt, newContext);
}
@Override
protected ResultInfo dup(Type newPt, CheckContext newContext) {
return new MethodResultInfo(newPt, newContext);
}
}
/**
......@@ -1092,10 +1098,9 @@ public class Resolve {
unrelatedFunctionalInterfaces(found, req) &&
(actual != null && actual.getTag() == DEFERRED)) {
DeferredType dt = (DeferredType) actual;
DeferredType.SpeculativeCache.Entry e =
dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
if (e != null && e.speculativeTree != deferredAttr.stuckTree) {
return functionalInterfaceMostSpecific(found, req, e.speculativeTree);
JCTree speculativeTree = dt.speculativeTree(deferredAttrContext);
if (speculativeTree != deferredAttr.stuckTree) {
return functionalInterfaceMostSpecific(found, req, speculativeTree);
}
}
return compatibleBySubtyping(found, req);
......@@ -1147,8 +1152,8 @@ public class Resolve {
@Override
public void visitConditional(JCConditional tree) {
scan(tree.truepart);
scan(tree.falsepart);
scan(asExpr(tree.truepart));
scan(asExpr(tree.falsepart));
}
@Override
......@@ -1179,6 +1184,11 @@ public class Resolve {
}
}
@Override
public void visitParens(JCParens tree) {
scan(asExpr(tree.expr));
}
@Override
public void visitLambda(JCLambda tree) {
Type desc_t = types.findDescriptorType(t);
......@@ -1214,7 +1224,7 @@ public class Resolve {
private List<JCExpression> lambdaResults(JCLambda lambda) {
if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
return List.of((JCExpression) lambda.body);
return List.of(asExpr((JCExpression) lambda.body));
} else {
final ListBuffer<JCExpression> buffer = new ListBuffer<>();
DeferredAttr.LambdaReturnScanner lambdaScanner =
......@@ -1222,7 +1232,7 @@ public class Resolve {
@Override
public void visitReturn(JCReturn tree) {
if (tree.expr != null) {
buffer.append(tree.expr);
buffer.append(asExpr(tree.expr));
}
}
};
......@@ -1230,6 +1240,16 @@ public class Resolve {
return buffer.toList();
}
}
private JCExpression asExpr(JCExpression expr) {
if (expr.type.hasTag(DEFERRED)) {
JCTree speculativeTree = ((DeferredType)expr.type).speculativeTree(deferredAttrContext);
if (speculativeTree != deferredAttr.stuckTree) {
expr = (JCExpression)speculativeTree;
}
}
return expr;
}
}
}
......
Readonly.java:15:10: compiler.err.cant.apply.symbol: kindname.method, put, Err<compiler.misc.type.captureof: 1, ? extends java.lang.String>, Err<compiler.misc.type.captureof: 2, ? extends java.lang.String>, kindname.class, Err<T>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: Err<compiler.misc.type.captureof: 2, ? extends java.lang.String>, Err<compiler.misc.type.captureof: 1, ? extends java.lang.String>))
Readonly.java:15:10: compiler.err.cant.apply.symbol: kindname.method, put, Err<compiler.misc.type.captureof: 1, ? extends java.lang.String>, Err<compiler.misc.type.captureof: 2, ? extends java.lang.String>, kindname.class, Err<T>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: Err<compiler.misc.type.captureof: 3, ? extends java.lang.String>, Err<compiler.misc.type.captureof: 1, ? extends java.lang.String>))
1 error
T8019480.java:21:46: compiler.err.report.access: clone(), protected, java.lang.Object
T8019480.java:21:34: compiler.err.cant.apply.symbols: kindname.method, add, java.lang.Object,{(compiler.misc.inapplicable.method: kindname.method, java.util.Collection, add(U), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, U))),(compiler.misc.inapplicable.method: kindname.method, java.util.List, add(U), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, U))),(compiler.misc.inapplicable.method: kindname.method, java.util.List, add(int,U), (compiler.misc.arg.length.mismatch))}
T8019480.java:21:46: compiler.err.report.access: clone(), protected, java.lang.Object
2 errors
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8078093
* @summary Exponential performance regression Java 8 compiler compared to Java 7 compiler
* @compile InferStrict.java
*/
import java.util.HashSet;
import java.util.Set;
class InferStrict {
public <T> Set<T> compute(Set<T> t) { return t; }
public <T> T join(Set<T> t1, Set<T> t2) { return null; }
public <T extends InferStrict> T compute() { return null; }
public void test() {
join(
compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(new HashSet<>()))))))))))))))))),
compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(compute(new HashSet<String>())))))))))))))))))
).length();
}
}
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8078093
* @summary Exponential performance regression Java 8 compiler compared to Java 7 compiler
* @compile InferWeak.java
*/
class InferWeak {
private void test() {
GroupLayout l = new GroupLayout();
l.setHorizontalGroup(
l.createParallelGroup().addGroup(l.createParallelGroup().addGroup(
l.createParallelGroup().addGroup(l.createParallelGroup().addGroup(
l.createParallelGroup().addGroup(l.createParallelGroup().addGroup(
l.createParallelGroup().addGroup(l.createParallelGroup().addGroup(
l.createParallelGroup().addGroup(l.createParallelGroup().addGroup(
l.createParallelGroup().addGroup(l.createParallelGroup().addGroup(
l.createParallelGroup().addGroup(l.createParallelGroup().addGroup(
l.createParallelGroup().addGroup(l.createParallelGroup().addGroup(
l.createParallelGroup().addGroup(l.createParallelGroup().addGroup(
l.createParallelGroup().addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object())).addGap(1).addComponent(new Object()).addGap(1)
.addComponent(new Object()));
}
static class GroupLayout {
<T extends ParallelGroup> T createParallelGroup() {return null;}
<T extends ParallelGroup> T createParallelGroup(int i) {return null;}
<T extends ParallelGroup> T createParallelGroup(int i, int j) {return null;}
void setHorizontalGroup(ParallelGroup g) { }
}
static class ParallelGroup {
<T extends ParallelGroup> T addGroup(ParallelGroup g) { return null; }
<T extends ParallelGroup> T addGroup(int i, ParallelGroup g) { return null; }
<T extends ParallelGroup> T addGap(int i) { return null; }
<T extends ParallelGroup> T addGap(int i, int j) { return null; }
<T extends ParallelGroup> T addComponent(Object c) { return null; }
<T extends ParallelGroup> T addComponent(int i, Object c) { return null; }
}
}
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8078093
* @summary Exponential performance regression Java 8 compiler compared to Java 7 compiler
* @compile NestedLambdaGenerics.java
*/
import java.util.concurrent.Callable;
class NestedLambdaGenerics {
void test() {
m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
() -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
() -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
() -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
() -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
(Callable<String>)null)))))))))))))))))))))))))))))));
}
static class A0 { }
static class A1 { }
static class A2 { }
static class A3 { }
static class A4 { }
<Z extends A0> Z m(A0 t, Callable<Z> ct) { return null; }
<Z extends A1> Z m(A1 t, Callable<Z> ct) { return null; }
<Z extends A2> Z m(A2 t, Callable<Z> ct) { return null; }
<Z extends A3> Z m(A3 t, Callable<Z> ct) { return null; }
<Z extends A4> Z m(A4 t, Callable<Z> ct) { return null; }
<Z> Z m(Object o, Callable<Z> co) { return null; }
}
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8078093
* @summary Exponential performance regression Java 8 compiler compared to Java 7 compiler
* @compile NestedLambdaNoGenerics.java
*/
import java.util.concurrent.Callable;
class NestedLambdaNoGenerics {
void test() {
m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
() -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
() -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
() -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
() -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null, () -> m(null,
(Callable<String>)null)))))))))))))))))))))))))))))));
}
static class A0 { }
static class A1 { }
static class A2 { }
static class A3 { }
static class A4 { }
String m(A0 t, Callable<A0> ct) { return ""; }
String m(A1 t, Callable<A1> ct) { return ""; }
String m(A2 t, Callable<A2> ct) { return ""; }
String m(A3 t, Callable<A3> ct) { return ""; }
String m(A4 t, Callable<A4> ct) { return ""; }
String m(Object o, Callable<String> co) { return ""; }
}
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8078093 8055894
* @summary Exponential performance regression Java 8 compiler compared to Java 7 compiler
* @compile T8055984.java
*/
class T8055984 {
static class C<U> {
U fu;
C() { }
C(C<U> other) {
this.fu = other.fu;
}
C(U fu) {
this.fu = fu;
}
}
static <U> C<U> m(C<U> src) { return new C<U>(src); }
static void test() {
C<String> c2 = m(new C<>(m(new C<>() )) );
C<String> c3 = m(new C<>(m(new C<>(m(new C<>() )) )) );
C<String> c4 = m(new C<>(m(new C<>(m(new C<>(m(new C<>() )) )) )) );
C<String> c5 = m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>() )) )) )) )) );
C<String> c6 = m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>() )) )) )) )) )) );
C<String> c7 = m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>() )) )) )) )) )) )) );
C<String> c8 = m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>() )) )) )) )) )) )) )) );
C<String> c9 = m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>() )) )) )) )) )) )) )) )) );
C<String> c10 = m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>(m(new C<>())))))))))))))))))));
}
}
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8078093 8077247
* @summary Exponential performance regression Java 8 compiler compared to Java 7 compiler
* @compile T8077247.java
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class T8077247 {
public static void test() {
int x = add(add(add(add(add(add(add(add(add(add(1, 2), 3), 4), 5), 6), 7), 8), 9), 10), 11);
}
public static int add(int x, int y) {
long rslt = (long)x + (long)y;
if (Integer.MIN_VALUE <= rslt && rslt <= Integer.MAX_VALUE) {
return (int)rslt;
}
String msg = String.format("Integer overflow: %d + %d.", x, y);
throw new IllegalArgumentException(msg);
}
public static double add(double x, double y) {
double rslt = x + y;
if (Double.isInfinite(rslt)) {
String msg = String.format("Real overflow: %s + %s.", x, y);
throw new IllegalArgumentException(msg);
}
return (rslt == -0.0) ? 0.0 : rslt;
}
public static <T> List<T> add(List<T> x, List<T> y) {
List<T> rslt = new ArrayList<>(x.size() + y.size());
rslt.addAll(x);
rslt.addAll(y);
return rslt;
}
public static String add(String x, String y) {
return x + y;
}
public static <K, V> Map<K, V> add(Map<K, V> x, Map<K, V> y) {
Map<K, V> rslt = new HashMap<>(x);
rslt.putAll(y);
return rslt;
}
}
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8078093
* @summary Exponential performance regression Java 8 compiler compared to Java 7 compiler
* @compile T8078093.java
*/
import java.util.LinkedHashMap;
import java.util.Map;
class T8078093 {
public static void test() {
Map<Integer, String> a = x(x(x(x(x(x(x(x(x(x(x(x(
new LinkedHashMap<Integer, String>(),
1, "a"), 2, "b"), 3, "c"), 4, "d"),
5, "e"), 6, "f"), 7, "g"), 8, "h"),
9, "i"), 10, "j"), 11, "k"), 12, "l");
}
@SuppressWarnings("unused")
public static <K, V> Map<K, V> x(Map<K, V> m, K k, V v) {
// Replaced actual code by dummy implementation.
return null;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册