From 712fafddb61f4cf2b2ed101483f261d00cf41c0e Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 16 Nov 2012 16:21:00 +0400 Subject: [PATCH] DataFlowInfo.getPossibleTypes() now returns Set This solves some performance problems related to DataFlowInfo (lots of nested conditions etc.) --- .../resolve/calls/autocasts/DataFlowInfo.java | 4 +- .../autocasts/DelegatingDataFlowInfo.java | 75 +++++++------------ .../tests/dataFlowInfoTraversal/ManyIfs.kt | 46 +++++++----- 3 files changed, 60 insertions(+), 65 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java index 6079c1183fc..5e8d2dc33b0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java @@ -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.of(), @@ -30,7 +30,7 @@ public interface DataFlowInfo { Nullability getNullability(@NotNull DataFlowValue key); @NotNull - List getPossibleTypes(@NotNull DataFlowValue key); + Set getPossibleTypes(@NotNull DataFlowValue key); @NotNull DataFlowInfo equate(@NotNull DataFlowValue a, @NotNull DataFlowValue b); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DelegatingDataFlowInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DelegatingDataFlowInfo.java index 9081958d4c1..13513e03ef2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DelegatingDataFlowInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DelegatingDataFlowInfo.java @@ -36,16 +36,16 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL /** Also immutable */ @NotNull - private final ListMultimap typeInfo; + private final SetMultimap typeInfo; private static final ImmutableMap EMPTY_NULLABILITY_INFO = ImmutableMap.copyOf(Collections.emptyMap()); - private static final ListMultimap EMPTY_TYPE_INFO = newTypeInfo(); + private static final SetMultimap EMPTY_TYPE_INFO = newTypeInfo(); /* package */ DelegatingDataFlowInfo( @Nullable DataFlowInfo parent, @NotNull ImmutableMap nullabilityInfo, - @NotNull ListMultimap typeInfo + @NotNull SetMultimap 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 getCompleteTypeInfo() { - ListMultimap result = newTypeInfo(); + private SetMultimap getCompleteTypeInfo() { + SetMultimap 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 getPossibleTypes(@NotNull DataFlowValue key) { - List types = typeInfo.get(key); + public Set getPossibleTypes(@NotNull DataFlowValue key) { + Set 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 enrichedTypes = Lists.newArrayListWithCapacity(types.size() + 1); + Set 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 toList, @NotNull List 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 newNullabilityInfo = type.isNullable() ? EMPTY_NULLABILITY_INFO : ImmutableMap.of(value, NOT_NULL); - ListMultimap newTypeInfo = ImmutableListMultimap.of(value, type); + SetMultimap 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 newTypeInfo = other.getCompleteTypeInfo(); - if (nullabilityMapBuilder.isEmpty() && newTypeInfo.isEmpty()) { + SetMultimap myTypeInfo = getCompleteTypeInfo(); + SetMultimap 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 first, SetMultimap 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 myTypeInfo = getCompleteTypeInfo(); - ListMultimap otherTypeInfo = other.getCompleteTypeInfo(); - ListMultimap newTypeInfo = newTypeInfo(); + SetMultimap myTypeInfo = getCompleteTypeInfo(); + SetMultimap otherTypeInfo = other.getCompleteTypeInfo(); + SetMultimap newTypeInfo = newTypeInfo(); - Set keys = Sets.newHashSet(myTypeInfo.keySet()); - keys.retainAll(otherTypeInfo.keySet()); - - for (DataFlowValue key : keys) { - Collection thisTypes = myTypeInfo.get(key); - Collection otherTypes = otherTypeInfo.get(key); - - Collection newTypes = Sets.newHashSet(thisTypes); - newTypes.retainAll(otherTypes); - - newTypeInfo.putAll(key, newTypes); + for (DataFlowValue key : Sets.intersection(myTypeInfo.keySet(), otherTypeInfo.keySet())) { + Set thisTypes = myTypeInfo.get(key); + Set 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 newTypeInfo() { - return Multimaps.newListMultimap(Maps.>newHashMap(), CommonSuppliers.getArrayListSupplier()); + /* package */ static SetMultimap newTypeInfo() { + return Multimaps.newSetMultimap(Maps.>newHashMap(), + CommonSuppliers.getLinkedHashSetSupplier()); } @Override diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ManyIfs.kt b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ManyIfs.kt index a9b35e8a54c..a655e41ce4d 100644 --- a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ManyIfs.kt +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ManyIfs.kt @@ -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) { + 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) { + a[0] : Int + } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } +} + +fun dataFlowInfoOr(a: Array) { + 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) { + a[0] : Int + } }