8067767: type inference performance regression

Overhaul implememntation of inference incorporation

Reviewed-by: vromero
This commit is contained in:
Maurizio Cimadamore 2015-11-19 16:43:11 +00:00
parent 54029caa26
commit 875bccb11e
11 changed files with 641 additions and 762 deletions

View file

@ -175,8 +175,8 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
@Override @Override
public String visitUndetVar(UndetVar t, Locale locale) { public String visitUndetVar(UndetVar t, Locale locale) {
if (t.inst != null) { if (t.getInst() != null) {
return printAnnotations(t) + visit(t.inst, locale); return printAnnotations(t) + visit(t.getInst(), locale);
} else { } else {
return printAnnotations(t) + visit(t.qtype, locale) + "?"; return printAnnotations(t) + visit(t.qtype, locale) + "?";
} }

View file

@ -26,19 +26,20 @@
package com.sun.tools.javac.code; package com.sun.tools.javac.code;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.util.ArrayDeque;
import java.util.Collections; import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import javax.lang.model.type.*; import javax.lang.model.type.*;
import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.TypeMetadata.Entry; import com.sun.tools.javac.code.TypeMetadata.Entry;
import com.sun.tools.javac.comp.Infer.IncorporationAction;
import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.DefinedBy.Api;
import static com.sun.tools.javac.code.BoundKind.*; import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.Kinds.Kind.*;
@ -1826,17 +1827,15 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
*/ */
public interface UndetVarListener { public interface UndetVarListener {
/** called when some inference variable bounds (of given kinds ibs) change */ /** called when some inference variable bounds (of given kinds ibs) change */
void varChanged(UndetVar uv, Set<InferenceBound> ibs); void varBoundChanged(UndetVar uv, InferenceBound ib, Type bound, boolean update);
/** called when the inferred type is set on some inference variable */
default void varInstantiated(UndetVar uv) { Assert.error(); }
} }
/** /**
* Inference variable bound kinds * Inference variable bound kinds
*/ */
public enum InferenceBound { public enum InferenceBound {
/** upper bounds */
UPPER {
public InferenceBound complement() { return LOWER; }
},
/** lower bounds */ /** lower bounds */
LOWER { LOWER {
public InferenceBound complement() { return UPPER; } public InferenceBound complement() { return UPPER; }
@ -1844,16 +1843,38 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
/** equality constraints */ /** equality constraints */
EQ { EQ {
public InferenceBound complement() { return EQ; } public InferenceBound complement() { return EQ; }
},
/** upper bounds */
UPPER {
public InferenceBound complement() { return LOWER; }
}; };
public abstract InferenceBound complement(); public abstract InferenceBound complement();
public boolean lessThan(InferenceBound that) {
if (that == this) {
return false;
} else {
switch (that) {
case UPPER: return true;
case LOWER: return false;
case EQ: return (this != UPPER);
default:
Assert.error("Cannot get here!");
return false;
}
}
}
} }
/** list of incorporation actions (used by the incorporation engine). */
public ArrayDeque<IncorporationAction> incorporationActions = new ArrayDeque<>();
/** inference variable bounds */ /** inference variable bounds */
protected Map<InferenceBound, List<Type>> bounds; protected Map<InferenceBound, List<Type>> bounds;
/** inference variable's inferred type (set from Infer.java) */ /** inference variable's inferred type (set from Infer.java) */
public Type inst = null; private Type inst = null;
/** number of declared (upper) bounds */ /** number of declared (upper) bounds */
public int declaredCount; public int declaredCount;
@ -1866,15 +1887,20 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
return v.visitUndetVar(this, s); return v.visitUndetVar(this, s);
} }
public UndetVar(TypeVar origin, Types types) { public UndetVar(TypeVar origin, UndetVarListener listener, Types types) {
// This is a synthesized internal type, so we cannot annotate it. // This is a synthesized internal type, so we cannot annotate it.
super(UNDETVAR, origin); super(UNDETVAR, origin);
this.listener = listener;
bounds = new EnumMap<>(InferenceBound.class); bounds = new EnumMap<>(InferenceBound.class);
List<Type> declaredBounds = types.getBounds(origin); List<Type> declaredBounds = types.getBounds(origin);
declaredCount = declaredBounds.length(); declaredCount = declaredBounds.length();
bounds.put(InferenceBound.UPPER, declaredBounds); bounds.put(InferenceBound.UPPER, List.nil());
bounds.put(InferenceBound.LOWER, List.<Type>nil()); bounds.put(InferenceBound.LOWER, List.nil());
bounds.put(InferenceBound.EQ, List.<Type>nil()); bounds.put(InferenceBound.EQ, List.nil());
for (Type t : declaredBounds.reverse()) {
//add bound works in reverse order
addBound(InferenceBound.UPPER, t, types, true);
}
} }
@DefinedBy(Api.LANGUAGE_MODEL) @DefinedBy(Api.LANGUAGE_MODEL)
@ -1904,6 +1930,32 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
return result; return result;
} }
/**
* Returns a new copy of this undet var.
*/
public UndetVar dup(Types types) {
UndetVar uv2 = new UndetVar((TypeVar)qtype, listener, types);
dupTo(uv2, types);
return uv2;
}
/**
* Dumps the contents of this undet var on another undet var.
*/
public void dupTo(UndetVar uv2, Types types) {
uv2.listener = null;
uv2.bounds.clear();
for (InferenceBound ib : InferenceBound.values()) {
uv2.bounds.put(ib, List.nil());
for (Type t : getBounds(ib)) {
uv2.addBound(ib, t, types, true);
}
}
uv2.inst = inst;
uv2.listener = listener;
uv2.incorporationActions = new ArrayDeque<>(incorporationActions);
}
@Override @Override
public UndetVar cloneWithMetadata(TypeMetadata md) { public UndetVar cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to an UndetVar type"); throw new AssertionError("Cannot add metadata to an UndetVar type");
@ -1919,6 +1971,17 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
return (inst == null) ? this : inst.baseType(); return (inst == null) ? this : inst.baseType();
} }
public Type getInst() {
return inst;
}
public void setInst(Type inst) {
this.inst = inst;
if (listener != null) {
listener.varInstantiated(this);
}
}
/** get all bounds of a given kind */ /** get all bounds of a given kind */
public List<Type> getBounds(InferenceBound... ibs) { public List<Type> getBounds(InferenceBound... ibs) {
ListBuffer<Type> buf = new ListBuffer<>(); ListBuffer<Type> buf = new ListBuffer<>();
@ -1952,13 +2015,14 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) { protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
Type bound2 = bound.map(toTypeVarMap).baseType(); Type bound2 = bound.map(toTypeVarMap).baseType();
List<Type> prevBounds = bounds.get(ib); List<Type> prevBounds = bounds.get(ib);
if (bound == qtype) return;
for (Type b : prevBounds) { for (Type b : prevBounds) {
//check for redundancy - use strict version of isSameType on tvars //check for redundancy - use strict version of isSameType on tvars
//(as the standard version will lead to false positives w.r.t. clones ivars) //(as the standard version will lead to false positives w.r.t. clones ivars)
if (types.isSameType(b, bound2, true) || bound == qtype) return; if (types.isSameType(b, bound2, true)) return;
} }
bounds.put(ib, prevBounds.prepend(bound2)); bounds.put(ib, prevBounds.prepend(bound2));
notifyChange(EnumSet.of(ib)); notifyBoundChange(ib, bound2, false);
} }
//where //where
TypeMapping<Void> toTypeVarMap = new TypeMapping<Void>() { TypeMapping<Void> toTypeVarMap = new TypeMapping<Void>() {
@ -1970,16 +2034,14 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
/** replace types in all bounds - this might trigger listener notification */ /** replace types in all bounds - this might trigger listener notification */
public void substBounds(List<Type> from, List<Type> to, Types types) { public void substBounds(List<Type> from, List<Type> to, Types types) {
List<Type> instVars = from.diff(to); final ListBuffer<Pair<InferenceBound, Type>> boundsChanged = new ListBuffer<>();
//if set of instantiated ivars is empty, there's nothing to do!
if (instVars.isEmpty()) return;
final EnumSet<InferenceBound> boundsChanged = EnumSet.noneOf(InferenceBound.class);
UndetVarListener prevListener = listener; UndetVarListener prevListener = listener;
try { try {
//setup new listener for keeping track of changed bounds //setup new listener for keeping track of changed bounds
listener = new UndetVarListener() { listener = new UndetVarListener() {
public void varChanged(UndetVar uv, Set<InferenceBound> ibs) { public void varBoundChanged(UndetVar uv, InferenceBound ib, Type t, boolean _ignored) {
boundsChanged.addAll(ibs); Assert.check(uv == UndetVar.this);
boundsChanged.add(new Pair<>(ib, t));
} }
}; };
for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) { for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
@ -1989,7 +2051,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
ListBuffer<Type> deps = new ListBuffer<>(); ListBuffer<Type> deps = new ListBuffer<>();
//step 1 - re-add bounds that are not dependent on ivars //step 1 - re-add bounds that are not dependent on ivars
for (Type t : prevBounds) { for (Type t : prevBounds) {
if (!t.containsAny(instVars)) { if (!t.containsAny(from)) {
newBounds.append(t); newBounds.append(t);
} else { } else {
deps.append(t); deps.append(t);
@ -2004,15 +2066,15 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
} }
} finally { } finally {
listener = prevListener; listener = prevListener;
if (!boundsChanged.isEmpty()) { for (Pair<InferenceBound, Type> boundUpdate : boundsChanged) {
notifyChange(boundsChanged); notifyBoundChange(boundUpdate.fst, boundUpdate.snd, true);
} }
} }
} }
private void notifyChange(EnumSet<InferenceBound> ibs) { private void notifyBoundChange(InferenceBound ib, Type bound, boolean update) {
if (listener != null) { if (listener != null) {
listener.varChanged(this, ibs); listener.varBoundChanged(this, ib, bound, update);
} }
} }
@ -2029,10 +2091,10 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
*/ */
public static class CapturedUndetVar extends UndetVar { public static class CapturedUndetVar extends UndetVar {
public CapturedUndetVar(CapturedType origin, Types types) { public CapturedUndetVar(CapturedType origin, UndetVarListener listener, Types types) {
super(origin, types); super(origin, listener, types);
if (!origin.lower.hasTag(BOT)) { if (!origin.lower.hasTag(BOT)) {
bounds.put(InferenceBound.LOWER, List.of(origin.lower)); addBound(InferenceBound.LOWER, origin.lower, types, true);
} }
} }
@ -2051,6 +2113,12 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
public boolean isCaptured() { public boolean isCaptured() {
return true; return true;
} }
public UndetVar dup(Types types) {
UndetVar uv2 = new CapturedUndetVar((CapturedType)qtype, listener, types);
dupTo(uv2, types);
return uv2;
}
} }
/** Represents NONE. /** Represents NONE.

View file

@ -3843,7 +3843,7 @@ public class Types {
@Override @Override
public Integer visitTypeVar(TypeVar t, Void ignored) { public Integer visitTypeVar(TypeVar t, Void ignored) {
return System.identityHashCode(t.tsym); return System.identityHashCode(t);
} }
@Override @Override

View file

@ -39,6 +39,7 @@ import com.sun.tools.javac.code.Type.TypeVar;
import com.sun.tools.javac.code.Type.UndetVar; import com.sun.tools.javac.code.Type.UndetVar;
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
import com.sun.tools.javac.code.Type.WildcardType; import com.sun.tools.javac.code.Type.WildcardType;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.code.Types; import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.comp.Infer.FreeTypeListener; import com.sun.tools.javac.comp.Infer.FreeTypeListener;
import com.sun.tools.javac.comp.Infer.GraphSolver; import com.sun.tools.javac.comp.Infer.GraphSolver;
@ -52,8 +53,6 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Warner; import com.sun.tools.javac.util.Warner;
import static com.sun.tools.javac.code.TypeTag.UNDETVAR;
/** /**
* An inference context keeps track of the set of variables that are free * An inference context keeps track of the set of variables that are free
* in the current context. It provides utility methods for opening/closing * in the current context. It provides utility methods for opening/closing
@ -118,7 +117,7 @@ class InferenceContext {
List<Type> restvars() { List<Type> restvars() {
return filterVars(new Filter<UndetVar>() { return filterVars(new Filter<UndetVar>() {
public boolean accepts(UndetVar uv) { public boolean accepts(UndetVar uv) {
return uv.inst == null; return uv.getInst() == null;
} }
}); });
} }
@ -130,7 +129,7 @@ class InferenceContext {
List<Type> instvars() { List<Type> instvars() {
return filterVars(new Filter<UndetVar>() { return filterVars(new Filter<UndetVar>() {
public boolean accepts(UndetVar uv) { public boolean accepts(UndetVar uv) {
return uv.inst != null; return uv.getInst() != null;
} }
}); });
} }
@ -224,7 +223,7 @@ class InferenceContext {
ListBuffer<Type> buf = new ListBuffer<>(); ListBuffer<Type> buf = new ListBuffer<>();
for (Type t : undetvars) { for (Type t : undetvars) {
UndetVar uv = (UndetVar)t; UndetVar uv = (UndetVar)t;
buf.append(uv.inst != null ? uv.inst : uv.qtype); buf.append(uv.getInst() != null ? uv.getInst() : uv.qtype);
} }
return buf.toList(); return buf.toList();
} }
@ -289,15 +288,7 @@ class InferenceContext {
List<Type> save() { List<Type> save() {
ListBuffer<Type> buf = new ListBuffer<>(); ListBuffer<Type> buf = new ListBuffer<>();
for (Type t : undetvars) { for (Type t : undetvars) {
UndetVar uv = (UndetVar)t; buf.add(((UndetVar)t).dup(infer.types));
UndetVar uv2 = new UndetVar((TypeVar)uv.qtype, types);
for (InferenceBound ib : InferenceBound.values()) {
for (Type b : uv.getBounds(ib)) {
uv2.addBound(ib, b, types);
}
}
uv2.inst = uv.inst;
buf.add(uv2);
} }
return buf.toList(); return buf.toList();
} }
@ -315,10 +306,7 @@ class InferenceContext {
UndetVar uv = (UndetVar)undetvars.head; UndetVar uv = (UndetVar)undetvars.head;
UndetVar uv_saved = (UndetVar)saved_undet.head; UndetVar uv_saved = (UndetVar)saved_undet.head;
if (uv.qtype == uv_saved.qtype) { if (uv.qtype == uv_saved.qtype) {
for (InferenceBound ib : InferenceBound.values()) { uv_saved.dupTo(uv, types);
uv.setBounds(ib, uv_saved.getBounds(ib));
}
uv.inst = uv_saved.inst;
undetvars = undetvars.tail; undetvars = undetvars.tail;
saved_undet = saved_undet.tail; saved_undet = saved_undet.tail;
newUndetVars.add(uv); newUndetVars.add(uv);
@ -367,7 +355,7 @@ class InferenceContext {
ListBuffer<Type> minUndetVars = new ListBuffer<>(); ListBuffer<Type> minUndetVars = new ListBuffer<>();
for (Type minVar : minVars) { for (Type minVar : minVars) {
UndetVar uv = (UndetVar)asUndetVar(minVar); UndetVar uv = (UndetVar)asUndetVar(minVar);
UndetVar uv2 = new UndetVar((TypeVar)minVar, types); UndetVar uv2 = new UndetVar((TypeVar)minVar, infer.incorporationEngine(), types);
for (InferenceBound ib : InferenceBound.values()) { for (InferenceBound ib : InferenceBound.values()) {
List<Type> newBounds = uv.getBounds(ib).stream() List<Type> newBounds = uv.getBounds(ib).stream()
.filter(b -> !redundantVars.contains(b)) .filter(b -> !redundantVars.contains(b))
@ -416,7 +404,7 @@ class InferenceContext {
Set<Type> deps = minMap.getOrDefault(t.qtype, new HashSet<>(Collections.singleton(t.qtype))); Set<Type> deps = minMap.getOrDefault(t.qtype, new HashSet<>(Collections.singleton(t.qtype)));
for (Type b : t.getBounds(InferenceBound.values())) { for (Type b : t.getBounds(InferenceBound.values())) {
Type undet = asUndetVar(b); Type undet = asUndetVar(b);
if (!undet.hasTag(UNDETVAR)) { if (!undet.hasTag(TypeTag.UNDETVAR)) {
visit(undet); visit(undet);
} else if (isEquiv((UndetVar)undet, b)){ } else if (isEquiv((UndetVar)undet, b)){
deps.add(b); deps.add(b);
@ -438,7 +426,7 @@ class InferenceContext {
@Override @Override
public Void visitTypeVar(TypeVar t, Void aVoid) { public Void visitTypeVar(TypeVar t, Void aVoid) {
Type undet = asUndetVar(t); Type undet = asUndetVar(t);
if (undet.hasTag(UNDETVAR)) { if (undet.hasTag(TypeTag.UNDETVAR)) {
visitUndetVar((UndetVar)undet, null); visitUndetVar((UndetVar)undet, null);
} }
return null; return null;
@ -519,23 +507,23 @@ class InferenceContext {
/** /**
* Apply a set of inference steps * Apply a set of inference steps
*/ */
private boolean solveBasic(EnumSet<InferenceStep> steps) { private List<Type> solveBasic(EnumSet<InferenceStep> steps) {
return solveBasic(inferencevars, steps); return solveBasic(inferencevars, steps);
} }
boolean solveBasic(List<Type> varsToSolve, EnumSet<InferenceStep> steps) { List<Type> solveBasic(List<Type> varsToSolve, EnumSet<InferenceStep> steps) {
boolean changed = false; ListBuffer<Type> solvedVars = new ListBuffer<>();
for (Type t : varsToSolve.intersect(restvars())) { for (Type t : varsToSolve.intersect(restvars())) {
UndetVar uv = (UndetVar)asUndetVar(t); UndetVar uv = (UndetVar)asUndetVar(t);
for (InferenceStep step : steps) { for (InferenceStep step : steps) {
if (step.accepts(uv, this)) { if (step.accepts(uv, this)) {
uv.inst = step.solve(uv, this); uv.setInst(step.solve(uv, this));
changed = true; solvedVars.add(uv.qtype);
break; break;
} }
} }
} }
return changed; return solvedVars.toList();
} }
/** /**
@ -547,11 +535,11 @@ class InferenceContext {
*/ */
public void solveLegacy(boolean partial, Warner warn, EnumSet<InferenceStep> steps) { public void solveLegacy(boolean partial, Warner warn, EnumSet<InferenceStep> steps) {
while (true) { while (true) {
boolean stuck = !solveBasic(steps); List<Type> solvedVars = solveBasic(steps);
if (restvars().isEmpty() || partial) { if (restvars().isEmpty() || partial) {
//all variables have been instantiated - exit //all variables have been instantiated - exit
break; break;
} else if (stuck) { } else if (solvedVars.isEmpty()) {
//some variables could not be instantiated because of cycles in //some variables could not be instantiated because of cycles in
//upper bounds - provide a (possibly recursive) default instantiation //upper bounds - provide a (possibly recursive) default instantiation
infer.instantiateAsUninferredVars(restvars(), this); infer.instantiateAsUninferredVars(restvars(), this);
@ -561,11 +549,11 @@ class InferenceContext {
//variables in remaining upper bounds and continue //variables in remaining upper bounds and continue
for (Type t : undetvars) { for (Type t : undetvars) {
UndetVar uv = (UndetVar)t; UndetVar uv = (UndetVar)t;
uv.substBounds(inferenceVars(), instTypes(), types); uv.substBounds(solvedVars, asInstTypes(solvedVars), types);
} }
} }
} }
infer.checkWithinBounds(this, warn); infer.doIncorporation(this, warn);
} }
@Override @Override

View file

@ -1981,18 +1981,6 @@ compiler.misc.incompatible.upper.lower.bounds=\
upper bounds: {1}\n\ upper bounds: {1}\n\
lower bounds: {2} lower bounds: {2}
# 0: type, 1: list of type, 2: list of type
compiler.misc.incompatible.upper.eq.bounds=\
inference variable {0} has incompatible bounds\n\
upper bounds: {1}\n\
equality constraints: {2}
# 0: type, 1: list of type, 2: list of type
compiler.misc.incompatible.eq.lower.bounds=\
inference variable {0} has incompatible bounds\n\
equality constraints: {1}\n\
lower bounds: {2}
# 0: type, 1: list of type, 2: list of type # 0: type, 1: list of type, 2: list of type
compiler.misc.incompatible.eq.lower.bounds=\ compiler.misc.incompatible.eq.lower.bounds=\
inference variable {0} has incompatible bounds\n\ inference variable {0} has incompatible bounds\n\

View file

@ -114,4 +114,3 @@ compiler.warn.file.from.future # warning for future mod
compiler.err.cant.inherit.from.anon # error for subclass of anonymous class compiler.err.cant.inherit.from.anon # error for subclass of anonymous class
compiler.misc.bad.class.file # class file is malformed compiler.misc.bad.class.file # class file is malformed
compiler.misc.bad.const.pool.entry # constant pool entry has wrong type compiler.misc.bad.const.pool.entry # constant pool entry has wrong type
compiler.misc.incompatible.upper.eq.bounds

View file

@ -1,2 +1,2 @@
T7154127.java:20:49: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: Y, T7154127.B<U>,T7154127.D) T7154127.java:20:49: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: U, T7154127.B<Y>,T7154127.E)
1 error 1 error

View file

@ -0,0 +1,67 @@
/*
* 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 8067767
* @summary type inference performance regression
* @compile T8067767.java
*/
class T8067767 {
static class Pair<A, B> {
static <A, B> Pair<A, B> of(A a, B b) {
throw new RuntimeException();
}
}
static class List<T> {
static <T> List<T> of(T... tx) {
throw new RuntimeException();
}
}
static final List<Pair<String, String>> PAIRS = List.of(
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"),
Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"), Pair.of("a", "b"));
}

View file

@ -1,2 +1,2 @@
TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, R,java.lang.String, java.lang.Object,java.lang.Number) TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Object,java.lang.Number)
1 error 1 error

View file

@ -1304,7 +1304,7 @@ public class DPrinter {
for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values())
printList("bounds." + ib, type.getBounds(ib)); printList("bounds." + ib, type.getBounds(ib));
printInt("declaredCount", type.declaredCount); printInt("declaredCount", type.declaredCount);
printType("inst", type.inst, Details.SUMMARY); printType("inst", type.getInst(), Details.SUMMARY);
return visitDelegatedType(type); return visitDelegatedType(type);
} }