mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Fix NPE in dependency analyzer. Fix excessive types propagating in dependency analyzer
This commit is contained in:
parent
558c3f2f1e
commit
d6363c5fbf
|
@ -460,7 +460,9 @@ class DependencyGraphBuilder {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
valueNode.connect(receiverNode, dependencyAnalyzer.getSuperClassFilter(targetType.toString()));
|
if (valueNode != null && receiverNode != null) {
|
||||||
|
valueNode.connect(receiverNode, dependencyAnalyzer.getSuperClassFilter(targetType.toString()));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (valueNode != null && receiverNode != null) {
|
if (valueNode != null && receiverNode != null) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.teavm.model.ValueType;
|
||||||
public class DependencyNode implements ValueDependencyInfo {
|
public class DependencyNode implements ValueDependencyInfo {
|
||||||
private static final int SMALL_TYPES_THRESHOLD = 3;
|
private static final int SMALL_TYPES_THRESHOLD = 3;
|
||||||
private static final int DEGREE_THRESHOLD = 2;
|
private static final int DEGREE_THRESHOLD = 2;
|
||||||
private DependencyAnalyzer dependencyAnalyzer;
|
DependencyAnalyzer dependencyAnalyzer;
|
||||||
List<DependencyConsumer> followers;
|
List<DependencyConsumer> followers;
|
||||||
TypeSet typeSet;
|
TypeSet typeSet;
|
||||||
ObjectObjectHashMap<DependencyNode, DependencyNodeToNodeTransition> transitions;
|
ObjectObjectHashMap<DependencyNode, DependencyNodeToNodeTransition> transitions;
|
||||||
|
@ -46,11 +46,10 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
private int degree;
|
private int degree;
|
||||||
boolean locked;
|
boolean locked;
|
||||||
MethodReference method;
|
MethodReference method;
|
||||||
private ValueType typeFilter;
|
ValueType typeFilter;
|
||||||
private DependencyTypeFilter cachedTypeFilter;
|
private DependencyTypeFilter cachedTypeFilter;
|
||||||
|
|
||||||
boolean visitedFlag;
|
boolean visitedFlag;
|
||||||
int splitCount;
|
|
||||||
|
|
||||||
DependencyNode(DependencyAnalyzer dependencyAnalyzer, ValueType typeFilter) {
|
DependencyNode(DependencyAnalyzer dependencyAnalyzer, ValueType typeFilter) {
|
||||||
this(dependencyAnalyzer, typeFilter, 0);
|
this(dependencyAnalyzer, typeFilter, 0);
|
||||||
|
@ -287,7 +286,7 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
typeSet.transitions.add(transition);
|
typeSet.transitions.add(transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.propagate(getTypesInternal());
|
node.propagate(filter != null ? getTypesInternal(filter) : getTypesInternal());
|
||||||
}
|
}
|
||||||
|
|
||||||
connectArrayItemNodes(node);
|
connectArrayItemNodes(node);
|
||||||
|
@ -446,6 +445,21 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
return i == result.length ? result : Arrays.copyOf(result, i);
|
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() {
|
public String getTag() {
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
@ -483,7 +497,6 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
|
|
||||||
for (DependencyNode node : domain) {
|
for (DependencyNode node : domain) {
|
||||||
node.typeSet = typeSet;
|
node.typeSet = typeSet;
|
||||||
node.splitCount++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +515,7 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
for (ObjectCursor<DependencyNodeToNodeTransition> cursor : node.transitionList) {
|
for (ObjectCursor<DependencyNodeToNodeTransition> cursor : node.transitionList) {
|
||||||
DependencyNodeToNodeTransition transition = cursor.value;
|
DependencyNodeToNodeTransition transition = cursor.value;
|
||||||
if (transition.filter == null && transition.destination.typeSet == typeSet
|
if (transition.filter == null && transition.destination.typeSet == typeSet
|
||||||
&& !visited.contains(transition.destination)) {
|
&& !visited.contains(transition.destination) && transition.isDestSubsetOfSrc()) {
|
||||||
stack.push(transition.destination);
|
stack.push(transition.destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ import com.carrotsearch.hppc.IntSet;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
class DependencyNodeToNodeTransition {
|
class DependencyNodeToNodeTransition {
|
||||||
DependencyNode source;
|
DependencyNode source;
|
||||||
|
@ -26,6 +28,7 @@ class DependencyNodeToNodeTransition {
|
||||||
DependencyTypeFilter filter;
|
DependencyTypeFilter filter;
|
||||||
private BitSet knownFilteredOffTypes;
|
private BitSet knownFilteredOffTypes;
|
||||||
IntSet pendingTypes;
|
IntSet pendingTypes;
|
||||||
|
byte destSubsetOfSrc;
|
||||||
|
|
||||||
DependencyNodeToNodeTransition(DependencyNode source, DependencyNode destination, DependencyTypeFilter filter) {
|
DependencyNodeToNodeTransition(DependencyNode source, DependencyNode destination, DependencyTypeFilter filter) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
|
@ -69,7 +72,6 @@ class DependencyNodeToNodeTransition {
|
||||||
Collection<DependencyNode> domainToMerge = destination.typeSet.domain;
|
Collection<DependencyNode> domainToMerge = destination.typeSet.domain;
|
||||||
for (DependencyNode node : domainToMerge) {
|
for (DependencyNode node : domainToMerge) {
|
||||||
node.typeSet = source.typeSet;
|
node.typeSet = source.typeSet;
|
||||||
node.splitCount++;
|
|
||||||
source.typeSet.domain.add(node);
|
source.typeSet.domain.add(node);
|
||||||
}
|
}
|
||||||
source.typeSet.invalidate();
|
source.typeSet.invalidate();
|
||||||
|
@ -77,7 +79,7 @@ class DependencyNodeToNodeTransition {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean shouldMergeDomains() {
|
boolean shouldMergeDomains() {
|
||||||
if (filter != null || destination.splitCount > 2) {
|
if (filter != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (destination.typeSet == null) {
|
if (destination.typeSet == null) {
|
||||||
|
@ -171,4 +173,25 @@ class DependencyNodeToNodeTransition {
|
||||||
boolean pointsToDomainOrigin() {
|
boolean pointsToDomainOrigin() {
|
||||||
return destination.typeSet == null || destination.typeSet.origin == destination;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user