Fix NPE in dependency analyzer. Fix excessive types propagating in dependency analyzer

This commit is contained in:
Alexey Andreev 2018-08-27 16:17:23 +03:00
parent 558c3f2f1e
commit d6363c5fbf
3 changed files with 47 additions and 9 deletions

View File

@ -460,7 +460,9 @@ class DependencyGraphBuilder {
return;
}
}
valueNode.connect(receiverNode, dependencyAnalyzer.getSuperClassFilter(targetType.toString()));
if (valueNode != null && receiverNode != null) {
valueNode.connect(receiverNode, dependencyAnalyzer.getSuperClassFilter(targetType.toString()));
}
return;
}
if (valueNode != null && receiverNode != null) {

View File

@ -33,7 +33,7 @@ import org.teavm.model.ValueType;
public class DependencyNode implements ValueDependencyInfo {
private static final int SMALL_TYPES_THRESHOLD = 3;
private static final int DEGREE_THRESHOLD = 2;
private DependencyAnalyzer dependencyAnalyzer;
DependencyAnalyzer dependencyAnalyzer;
List<DependencyConsumer> followers;
TypeSet typeSet;
ObjectObjectHashMap<DependencyNode, DependencyNodeToNodeTransition> transitions;
@ -46,11 +46,10 @@ public class DependencyNode implements ValueDependencyInfo {
private int degree;
boolean locked;
MethodReference method;
private ValueType typeFilter;
ValueType typeFilter;
private DependencyTypeFilter cachedTypeFilter;
boolean visitedFlag;
int splitCount;
DependencyNode(DependencyAnalyzer dependencyAnalyzer, ValueType typeFilter) {
this(dependencyAnalyzer, typeFilter, 0);
@ -287,7 +286,7 @@ public class DependencyNode implements ValueDependencyInfo {
typeSet.transitions.add(transition);
}
node.propagate(getTypesInternal());
node.propagate(filter != null ? getTypesInternal(filter) : getTypesInternal());
}
connectArrayItemNodes(node);
@ -446,6 +445,21 @@ public class DependencyNode implements ValueDependencyInfo {
return i == result.length ? result : Arrays.copyOf(result, i);
}
DependencyType[] getTypesInternal(DependencyTypeFilter filter) {
if (typeSet == null) {
return new DependencyType[0];
}
DependencyType[] types = typeSet.getTypes();
DependencyType[] result = new DependencyType[types.length];
int i = 0;
for (DependencyType type : types) {
if (filter(type) && filter.match(type)) {
result[i++] = type;
}
}
return i == result.length ? result : Arrays.copyOf(result, i);
}
public String getTag() {
return tag;
}
@ -483,7 +497,6 @@ public class DependencyNode implements ValueDependencyInfo {
for (DependencyNode node : domain) {
node.typeSet = typeSet;
node.splitCount++;
}
}
@ -502,7 +515,7 @@ public class DependencyNode implements ValueDependencyInfo {
for (ObjectCursor<DependencyNodeToNodeTransition> cursor : node.transitionList) {
DependencyNodeToNodeTransition transition = cursor.value;
if (transition.filter == null && transition.destination.typeSet == typeSet
&& !visited.contains(transition.destination)) {
&& !visited.contains(transition.destination) && transition.isDestSubsetOfSrc()) {
stack.push(transition.destination);
}
}

View File

@ -19,6 +19,8 @@ import com.carrotsearch.hppc.IntSet;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.ValueType;
class DependencyNodeToNodeTransition {
DependencyNode source;
@ -26,6 +28,7 @@ class DependencyNodeToNodeTransition {
DependencyTypeFilter filter;
private BitSet knownFilteredOffTypes;
IntSet pendingTypes;
byte destSubsetOfSrc;
DependencyNodeToNodeTransition(DependencyNode source, DependencyNode destination, DependencyTypeFilter filter) {
this.source = source;
@ -69,7 +72,6 @@ class DependencyNodeToNodeTransition {
Collection<DependencyNode> domainToMerge = destination.typeSet.domain;
for (DependencyNode node : domainToMerge) {
node.typeSet = source.typeSet;
node.splitCount++;
source.typeSet.domain.add(node);
}
source.typeSet.invalidate();
@ -77,7 +79,7 @@ class DependencyNodeToNodeTransition {
}
boolean shouldMergeDomains() {
if (filter != null || destination.splitCount > 2) {
if (filter != null) {
return false;
}
if (destination.typeSet == null) {
@ -171,4 +173,25 @@ class DependencyNodeToNodeTransition {
boolean pointsToDomainOrigin() {
return destination.typeSet == null || destination.typeSet.origin == destination;
}
boolean isDestSubsetOfSrc() {
if (destSubsetOfSrc == 0) {
destSubsetOfSrc = calculateDestSubsetOfSrc() ? (byte) 2 : 1;
}
return destSubsetOfSrc == 2;
}
private boolean calculateDestSubsetOfSrc() {
if (source.typeFilter == null) {
return true;
}
if (destination.typeFilter == null) {
return false;
}
ValueType sourceType = source.typeFilter;
ValueType destType = destination.typeFilter;
ClassReaderSource classSource = source.dependencyAnalyzer.getClassSource();
return classSource.isSuperType(sourceType, destType).orElse(false);
}
}