Speed-up dependency analysis

This commit is contained in:
Alexey Andreev 2017-02-11 12:25:57 +03:00
parent d6e3331063
commit 3402fd8ec9
2 changed files with 55 additions and 15 deletions

View File

@ -75,7 +75,6 @@ public class DependencyChecker implements DependencyInfo {
private Diagnostics diagnostics; private Diagnostics diagnostics;
DefaultCallGraph callGraph = new DefaultCallGraph(); DefaultCallGraph callGraph = new DefaultCallGraph();
private DependencyAgent agent; private DependencyAgent agent;
List<DependencyNode> nodes = new ArrayList<>();
Map<MethodReference, BootstrapMethodSubstitutor> bootstrapMethodSubstitutors = new HashMap<>(); Map<MethodReference, BootstrapMethodSubstitutor> bootstrapMethodSubstitutors = new HashMap<>();
private boolean completing; private boolean completing;
@ -134,9 +133,7 @@ public class DependencyChecker implements DependencyInfo {
} }
public DependencyNode createNode() { public DependencyNode createNode() {
DependencyNode node = new DependencyNode(this); return new DependencyNode(this);
nodes.add(node);
return node;
} }
@Override @Override
@ -235,17 +232,33 @@ public class DependencyChecker implements DependencyInfo {
} }
} }
private int propagationDepth;
void schedulePropagation(DependencyConsumer consumer, DependencyType type) { void schedulePropagation(DependencyConsumer consumer, DependencyType type) {
if (propagationDepth < 50) {
++propagationDepth;
consumer.consume(type);
--propagationDepth;
} else {
tasks.add(() -> consumer.consume(type)); tasks.add(() -> consumer.consume(type));
} }
}
void schedulePropagation(DependencyConsumer consumer, DependencyType[] types) { void schedulePropagation(DependencyConsumer consumer, DependencyType[] types) {
if (propagationDepth < 50) {
++propagationDepth;
for (DependencyType type : types) {
consumer.consume(type);
}
--propagationDepth;
} else {
tasks.add(() -> { tasks.add(() -> {
for (DependencyType type : types) { for (DependencyType type : types) {
consumer.consume(type); consumer.consume(type);
} }
}); });
} }
}
private Set<String> classesAddedByRoot = new HashSet<>(); private Set<String> classesAddedByRoot = new HashSet<>();
@ -318,7 +331,7 @@ public class DependencyChecker implements DependencyInfo {
throw new IllegalStateException("Can't submit class during completion phase"); throw new IllegalStateException("Can't submit class during completion phase");
} }
callGraph.getNode(methodRef); callGraph.getNode(methodRef);
boolean added = true; boolean added;
if (callLocation != null && callLocation.getMethod() != null) { if (callLocation != null && callLocation.getMethod() != null) {
added = callGraph.getNode(callLocation.getMethod()).addCallSite(methodRef, added = callGraph.getNode(callLocation.getMethod()).addCallSite(methodRef,
callLocation.getSourceLocation()); callLocation.getSourceLocation());
@ -408,7 +421,7 @@ public class DependencyChecker implements DependencyInfo {
if (completing) { if (completing) {
throw new IllegalStateException("Can't submit class during completion phase"); throw new IllegalStateException("Can't submit class during completion phase");
} }
boolean added = true; boolean added;
if (location != null) { if (location != null) {
added = callGraph.getNode(location.getMethod()).addFieldAccess(fieldRef, location.getSourceLocation()); added = callGraph.getNode(location.getMethod()).addFieldAccess(fieldRef, location.getSourceLocation());
} else { } else {

View File

@ -99,6 +99,11 @@ public class DependencyNode implements ValueDependencyInfo {
dependencyChecker.schedulePropagation(consumer, type); dependencyChecker.schedulePropagation(consumer, type);
} }
} }
if (transitions != null) {
for (DependencyConsumer consumer : transitions.toArray(new DependencyConsumer[transitions.size()])) {
dependencyChecker.schedulePropagation(consumer, type);
}
}
} }
} }
@ -122,22 +127,32 @@ public class DependencyNode implements ValueDependencyInfo {
System.out.println(tag + " -> " + types[i].getName()); System.out.println(tag + " -> " + types[i].getName());
} }
} }
if (followers != null) {
if (j < types.length && (followers != null || transitions != null)) {
types = Arrays.copyOf(types, j); types = Arrays.copyOf(types, j);
}
if (followers != null) {
for (DependencyConsumer consumer : followers.toArray(new DependencyConsumer[followers.size()])) { for (DependencyConsumer consumer : followers.toArray(new DependencyConsumer[followers.size()])) {
dependencyChecker.schedulePropagation(consumer, types); dependencyChecker.schedulePropagation(consumer, types);
} }
} }
if (transitions != null) {
for (DependencyNodeToNodeTransition consumer : transitions.toArray(
new DependencyNodeToNodeTransition[transitions.size()])) {
dependencyChecker.schedulePropagation(consumer, types);
}
}
} }
public void addConsumer(DependencyConsumer consumer) { public void addConsumer(DependencyConsumer consumer) {
if (followers == null) { if (followers == null) {
followers = new ArrayList<>(); followers = new ArrayList<>(1);
} }
if (followers.contains(consumer)) { if (followers.contains(consumer)) {
return; return;
} }
followers.add(consumer); followers.add(consumer);
if (this.types != null) { if (this.types != null) {
List<DependencyType> types = new ArrayList<>(); List<DependencyType> types = new ArrayList<>();
for (int index = this.types.nextSetBit(0); index >= 0; index = this.types.nextSetBit(index + 1)) { for (int index = this.types.nextSetBit(0); index >= 0; index = this.types.nextSetBit(index + 1)) {
@ -169,14 +184,27 @@ public class DependencyNode implements ValueDependencyInfo {
} }
DependencyNodeToNodeTransition transition = new DependencyNodeToNodeTransition(this, node, filter); DependencyNodeToNodeTransition transition = new DependencyNodeToNodeTransition(this, node, filter);
if (transitions == null) { if (transitions == null) {
transitions = new ArrayList<>(); transitions = new ArrayList<>(1);
} }
transitions.add(transition); transitions.add(transition);
if (DependencyChecker.shouldLog) { if (DependencyChecker.shouldLog) {
System.out.println("Connecting " + tag + " to " + node.tag); System.out.println("Connecting " + tag + " to " + node.tag);
} }
addConsumer(transition);
if (this.types != null) {
List<DependencyType> types = new ArrayList<>();
for (int index = this.types.nextSetBit(0); index >= 0; index = this.types.nextSetBit(index + 1)) {
types.add(dependencyChecker.types.get(index));
}
dependencyChecker.schedulePropagation(transition, types.toArray(new DependencyType[types.size()]));
} else if (this.smallTypes != null) {
DependencyType[] types = new DependencyType[smallTypes.length];
for (int i = 0; i < types.length; ++i) {
types[i] = dependencyChecker.types.get(smallTypes[i]);
}
dependencyChecker.schedulePropagation(transition, types);
}
} }
public void connect(DependencyNode node) { public void connect(DependencyNode node) {
@ -187,7 +215,6 @@ public class DependencyNode implements ValueDependencyInfo {
public DependencyNode getArrayItem() { public DependencyNode getArrayItem() {
if (arrayItemNode == null) { if (arrayItemNode == null) {
arrayItemNode = new DependencyNode(dependencyChecker, degree + 1); arrayItemNode = new DependencyNode(dependencyChecker, degree + 1);
dependencyChecker.nodes.add(arrayItemNode);
if (DependencyChecker.shouldLog) { if (DependencyChecker.shouldLog) {
arrayItemNode.tag = tag + "["; arrayItemNode.tag = tag + "[";
} }
@ -199,7 +226,7 @@ public class DependencyNode implements ValueDependencyInfo {
public DependencyNode getClassValueNode() { public DependencyNode getClassValueNode() {
if (classValueNode == null) { if (classValueNode == null) {
classValueNode = new DependencyNode(dependencyChecker, degree); classValueNode = new DependencyNode(dependencyChecker, degree);
dependencyChecker.nodes.add(classValueNode); classValueNode.classValueNode = classValueNode;
if (DependencyChecker.shouldLog) { if (DependencyChecker.shouldLog) {
classValueNode.tag = tag + "@"; classValueNode.tag = tag + "@";
} }