DataFlowInfo.getPossibleTypes() now returns Set
This solves some performance problems related to DataFlowInfo (lots of nested conditions etc.)
This commit is contained in:
+2
-2
@@ -20,7 +20,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface DataFlowInfo {
|
||||
DataFlowInfo EMPTY = new DelegatingDataFlowInfo(null, ImmutableMap.<DataFlowValue, Nullability>of(),
|
||||
@@ -30,7 +30,7 @@ public interface DataFlowInfo {
|
||||
Nullability getNullability(@NotNull DataFlowValue key);
|
||||
|
||||
@NotNull
|
||||
List<JetType> getPossibleTypes(@NotNull DataFlowValue key);
|
||||
Set<JetType> getPossibleTypes(@NotNull DataFlowValue key);
|
||||
|
||||
@NotNull
|
||||
DataFlowInfo equate(@NotNull DataFlowValue a, @NotNull DataFlowValue b);
|
||||
|
||||
+29
-46
@@ -36,16 +36,16 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
|
||||
|
||||
/** Also immutable */
|
||||
@NotNull
|
||||
private final ListMultimap<DataFlowValue, JetType> typeInfo;
|
||||
private final SetMultimap<DataFlowValue, JetType> typeInfo;
|
||||
|
||||
private static final ImmutableMap<DataFlowValue,Nullability> EMPTY_NULLABILITY_INFO =
|
||||
ImmutableMap.copyOf(Collections.<DataFlowValue, Nullability>emptyMap());
|
||||
private static final ListMultimap<DataFlowValue, JetType> EMPTY_TYPE_INFO = newTypeInfo();
|
||||
private static final SetMultimap<DataFlowValue, JetType> EMPTY_TYPE_INFO = newTypeInfo();
|
||||
|
||||
/* package */ DelegatingDataFlowInfo(
|
||||
@Nullable DataFlowInfo parent,
|
||||
@NotNull ImmutableMap<DataFlowValue, Nullability> nullabilityInfo,
|
||||
@NotNull ListMultimap<DataFlowValue, JetType> typeInfo
|
||||
@NotNull SetMultimap<DataFlowValue, JetType> typeInfo
|
||||
) {
|
||||
this.parent = parent;
|
||||
this.nullabilityInfo = nullabilityInfo;
|
||||
@@ -70,8 +70,8 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ListMultimap<DataFlowValue, JetType> getCompleteTypeInfo() {
|
||||
ListMultimap<DataFlowValue, JetType> result = newTypeInfo();
|
||||
private SetMultimap<DataFlowValue, JetType> getCompleteTypeInfo() {
|
||||
SetMultimap<DataFlowValue, JetType> result = newTypeInfo();
|
||||
DelegatingDataFlowInfo info = this;
|
||||
while (info != null) {
|
||||
for (DataFlowValue key : info.typeInfo.keySet()) {
|
||||
@@ -100,17 +100,13 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetType> getPossibleTypes(@NotNull DataFlowValue key) {
|
||||
List<JetType> types = typeInfo.get(key);
|
||||
public Set<JetType> getPossibleTypes(@NotNull DataFlowValue key) {
|
||||
Set<JetType> types = typeInfo.get(key);
|
||||
if (getNullability(key).canBeNull()) {
|
||||
if (parent != null) {
|
||||
types = Lists.newArrayList(types);
|
||||
addAllUnique(types, parent.getPossibleTypes(key));
|
||||
}
|
||||
return types;
|
||||
return parent == null ? types : Sets.union(types, parent.getPossibleTypes(key));
|
||||
}
|
||||
|
||||
List<JetType> enrichedTypes = Lists.newArrayListWithCapacity(types.size() + 1);
|
||||
Set<JetType> enrichedTypes = Sets.newHashSetWithExpectedSize(types.size() + 1);
|
||||
JetType originalType = key.getType();
|
||||
if (originalType.isNullable()) {
|
||||
enrichedTypes.add(TypeUtils.makeNotNullable(originalType));
|
||||
@@ -119,19 +115,7 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
|
||||
enrichedTypes.add(TypeUtils.makeNotNullable(type));
|
||||
}
|
||||
|
||||
if (parent != null) {
|
||||
addAllUnique(enrichedTypes, parent.getPossibleTypes(key));
|
||||
}
|
||||
|
||||
return enrichedTypes;
|
||||
}
|
||||
|
||||
private static void addAllUnique(@NotNull List<JetType> toList, @NotNull List<JetType> fromList) {
|
||||
for (JetType type : fromList) {
|
||||
if (!toList.contains(type)) {
|
||||
toList.add(type);
|
||||
}
|
||||
}
|
||||
return parent == null ? enrichedTypes : Sets.union(enrichedTypes, parent.getPossibleTypes(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,7 +151,7 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
|
||||
if (getPossibleTypes(value).contains(type)) return this;
|
||||
ImmutableMap<DataFlowValue, Nullability> newNullabilityInfo =
|
||||
type.isNullable() ? EMPTY_NULLABILITY_INFO : ImmutableMap.of(value, NOT_NULL);
|
||||
ListMultimap<DataFlowValue, JetType> newTypeInfo = ImmutableListMultimap.of(value, type);
|
||||
SetMultimap<DataFlowValue, JetType> newTypeInfo = ImmutableSetMultimap.of(value, type);
|
||||
return new DelegatingDataFlowInfo(this, newNullabilityInfo, newTypeInfo);
|
||||
}
|
||||
|
||||
@@ -192,12 +176,17 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
|
||||
}
|
||||
}
|
||||
|
||||
ListMultimap<DataFlowValue, JetType> newTypeInfo = other.getCompleteTypeInfo();
|
||||
if (nullabilityMapBuilder.isEmpty() && newTypeInfo.isEmpty()) {
|
||||
SetMultimap<DataFlowValue, JetType> myTypeInfo = getCompleteTypeInfo();
|
||||
SetMultimap<DataFlowValue, JetType> otherTypeInfo = other.getCompleteTypeInfo();
|
||||
if (nullabilityMapBuilder.isEmpty() && containsAll(myTypeInfo, otherTypeInfo)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return new DelegatingDataFlowInfo(this, ImmutableMap.copyOf(nullabilityMapBuilder), newTypeInfo);
|
||||
return new DelegatingDataFlowInfo(this, ImmutableMap.copyOf(nullabilityMapBuilder), otherTypeInfo);
|
||||
}
|
||||
|
||||
private static boolean containsAll(SetMultimap<DataFlowValue, JetType> first, SetMultimap<DataFlowValue, JetType> second) {
|
||||
return first.entries().containsAll(second.entries());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -218,21 +207,14 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
|
||||
nullabilityMapBuilder.put(key, thisFlags.or(otherFlags));
|
||||
}
|
||||
|
||||
ListMultimap<DataFlowValue, JetType> myTypeInfo = getCompleteTypeInfo();
|
||||
ListMultimap<DataFlowValue, JetType> otherTypeInfo = other.getCompleteTypeInfo();
|
||||
ListMultimap<DataFlowValue, JetType> newTypeInfo = newTypeInfo();
|
||||
SetMultimap<DataFlowValue, JetType> myTypeInfo = getCompleteTypeInfo();
|
||||
SetMultimap<DataFlowValue, JetType> otherTypeInfo = other.getCompleteTypeInfo();
|
||||
SetMultimap<DataFlowValue, JetType> newTypeInfo = newTypeInfo();
|
||||
|
||||
Set<DataFlowValue> keys = Sets.newHashSet(myTypeInfo.keySet());
|
||||
keys.retainAll(otherTypeInfo.keySet());
|
||||
|
||||
for (DataFlowValue key : keys) {
|
||||
Collection<JetType> thisTypes = myTypeInfo.get(key);
|
||||
Collection<JetType> otherTypes = otherTypeInfo.get(key);
|
||||
|
||||
Collection<JetType> newTypes = Sets.newHashSet(thisTypes);
|
||||
newTypes.retainAll(otherTypes);
|
||||
|
||||
newTypeInfo.putAll(key, newTypes);
|
||||
for (DataFlowValue key : Sets.intersection(myTypeInfo.keySet(), otherTypeInfo.keySet())) {
|
||||
Set<JetType> thisTypes = myTypeInfo.get(key);
|
||||
Set<JetType> otherTypes = otherTypeInfo.get(key);
|
||||
newTypeInfo.putAll(key, Sets.intersection(thisTypes, otherTypes));
|
||||
}
|
||||
|
||||
if (nullabilityMapBuilder.isEmpty() && newTypeInfo.isEmpty()) {
|
||||
@@ -243,8 +225,9 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/* package */ static ListMultimap<DataFlowValue, JetType> newTypeInfo() {
|
||||
return Multimaps.newListMultimap(Maps.<DataFlowValue, Collection<JetType>>newHashMap(), CommonSuppliers.<JetType>getArrayListSupplier());
|
||||
/* package */ static SetMultimap<DataFlowValue, JetType> newTypeInfo() {
|
||||
return Multimaps.newSetMultimap(Maps.<DataFlowValue, Collection<JetType>>newHashMap(),
|
||||
CommonSuppliers.<JetType>getLinkedHashSetSupplier());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,18 +1,30 @@
|
||||
fun foo(x: Number) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
if (x is Int) {
|
||||
} } } } } } } } } } } } } } }
|
||||
fun noUselessDataFlowInfoCreation(x: Number) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) { if (x is Int) {
|
||||
} } } } } } } } } } } } } } } } } } } } } } } } }
|
||||
}
|
||||
|
||||
fun dataFlowInfoAnd(a: Array<Number>) {
|
||||
if (a[0] is Int) { if (a[1] is Int) { if (a[2] is Int) { if (a[3] is Int) { if (a[4] is Int) {
|
||||
if (a[5] is Int) { if (a[6] is Int) { if (a[7] is Int) { if (a[8] is Int) { if (a[9] is Int) {
|
||||
if (a[10] is Int) { if (a[11] is Int) { if (a[12] is Int) { if (a[13] is Int) { if (a[14] is Int) {
|
||||
if (a[15] is Int) { if (a[16] is Int) { if (a[17] is Int) { if (a[18] is Int) { if (a[19] is Int) {
|
||||
if (a[20] is Int) { if (a[21] is Int) { if (a[22] is Int) { if (a[23] is Int) { if (a[24] is Int) {
|
||||
if (a[25] is Int) { if (a[26] is Int) { if (a[27] is Int) { if (a[28] is Int) { if (a[29] is Int) {
|
||||
<!TYPE_MISMATCH!>a[0]<!> : Int
|
||||
} } } } } } } } } } } } } } } } } } } } } } } } } } } } } }
|
||||
}
|
||||
|
||||
fun dataFlowInfoOr(a: Array<Number>) {
|
||||
if (a[0] is Int || a[1] is Int || a[2] is Int || a[3] is Int || a[4] is Int || a[5] is Int || a[6] is Int || a[7] is Int || a[8] is Int || a[9] is Int ||
|
||||
a[10] is Int || a[11] is Int || a[12] is Int || a[13] is Int || a[14] is Int || a[15] is Int || a[16] is Int || a[17] is Int || a[18] is Int || a[19] is Int ||
|
||||
a[20] is Int || a[21] is Int || a[22] is Int || a[23] is Int || a[24] is Int || a[25] is Int || a[26] is Int || a[27] is Int || a[28] is Int || a[29] is Int ||
|
||||
a[30] is Int || a[31] is Int || a[32] is Int || a[33] is Int || a[34] is Int || a[35] is Int || a[36] is Int || a[37] is Int || a[38] is Int || a[39] is Int ||
|
||||
a[40] is Int || a[41] is Int || a[42] is Int || a[43] is Int || a[44] is Int || a[45] is Int || a[46] is Int || a[47] is Int || a[48] is Int || a[49] is Int ||
|
||||
a[50] is Int || a[51] is Int || a[52] is Int || a[53] is Int || a[54] is Int || a[55] is Int || a[56] is Int || a[57] is Int || a[58] is Int || a[59] is Int) {
|
||||
<!TYPE_MISMATCH!>a[0]<!> : Int
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user