Remove unnecessary debugging code

This commit is contained in:
konsoletyper 2015-03-14 15:34:13 +03:00
parent 3449257db7
commit 004cb79b17
5 changed files with 172 additions and 141 deletions

View File

@ -31,7 +31,7 @@ public class IntegerStack {
public void push(int value) {
if (head == buffer.length) {
buffer = Arrays.copyOf(buffer, buffer.length * 2);
buffer = Arrays.copyOf(buffer, Math.max(buffer.length * 2, 1));
}
buffer[head++] = value;
}

View File

@ -19,6 +19,7 @@ import com.carrotsearch.hppc.IntOpenHashSet;
import com.carrotsearch.hppc.IntSet;
import com.carrotsearch.hppc.ObjectIntMap;
import com.carrotsearch.hppc.ObjectIntOpenHashMap;
import com.carrotsearch.hppc.cursors.IntCursor;
import java.util.Arrays;
import java.util.List;
import org.teavm.common.*;
@ -32,95 +33,62 @@ import org.teavm.model.instructions.*;
public class DataFlowGraphBuilder implements InstructionReader {
private int lastIndex;
private GraphBuilder builder = new GraphBuilder();
private IntSet importantNodes = new IntOpenHashSet();
private ObjectIntMap<MethodReference> methodNodes = new ObjectIntOpenHashMap<>();
private ObjectIntMap<FieldReference> fieldNodes = new ObjectIntOpenHashMap<>();
private int[] arrayNodes;
private int returnIndex = -1;
private int exceptionIndex;
private DisjointSet classes = new DisjointSet();
private int paramCount;
private IntSet escaping = new IntOpenHashSet();
public void important(int node) {
importantNodes.add(node);
private void join(int a, int b) {
if (a < paramCount || b < paramCount) {
return;
}
classes.union(a, b);
}
public int[] buildMapping(ProgramReader program, int paramCount, boolean needsReturn) {
public int[] buildMapping(ProgramReader program, boolean[] significantParams, boolean needsReturn) {
lastIndex = program.variableCount();
arrayNodes = new int[lastIndex];
this.paramCount = significantParams.length;
if (needsReturn) {
returnIndex = lastIndex++;
escaping.add(returnIndex);
}
exceptionIndex = lastIndex++;
Arrays.fill(arrayNodes, -1);
for (int i = 0; i < lastIndex; ++i) {
classes.create();
}
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlockReader block = program.basicBlockAt(i);
for (PhiReader phi : block.readPhis()) {
for (IncomingReader incoming : phi.readIncomings()) {
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
}
}
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
if (tryCatch.getExceptionVariable() != null) {
important(tryCatch.getExceptionVariable().getIndex());
int from = incoming.getValue().getIndex();
int to = phi.getReceiver().getIndex();
builder.addEdge(from, to);
join(from, to);
}
}
block.readAllInstructions(this);
}
Graph graph = builder.build();
DisjointSet classes = new DisjointSet();
for (int i = 0; i < lastIndex; ++i) {
classes.create();
}
IntegerArray startNodes = new IntegerArray(graph.size());
for (int i = paramCount; i < graph.size(); ++i) {
if (graph.incomingEdgesCount(i) == 0) {
startNodes.add(i);
}
for (int pred : graph.incomingEdges(i)) {
boolean predImportant = importantNodes.contains(classes.find(pred));
boolean nodeImportant = importantNodes.contains(classes.find(i));
if (predImportant && nodeImportant) {
continue;
}
int newCls = classes.union(pred, i);
if (nodeImportant || predImportant) {
importantNodes.add(newCls);
}
}
for (int succ : graph.outgoingEdges(i)) {
boolean succImportant = importantNodes.contains(classes.find(succ));
boolean nodeImportant = importantNodes.contains(classes.find(i));
if (succImportant && nodeImportant) {
continue;
}
int newCls = classes.union(succ, i);
if (nodeImportant || succImportant) {
importantNodes.add(newCls);
}
}
}
int[][] sccs = GraphUtils.findStronglyConnectedComponents(graph, startNodes.getAll());
for (int[] scc : sccs) {
int last = -1;
for (int node : scc) {
if (!importantNodes.contains(classes.find(node))) {
continue;
}
last = last < 0 ? node : classes.union(node, last);
for (int i = 0; i < paramCount; ++i) {
if (significantParams[i]) {
escaping.add(i);
}
}
propagateEscaping(graph);
int[] classMap = new int[classes.size()];
Arrays.fill(classMap, -1);
int[] result = new int[program.variableCount()];
int classCount = 0;
for (int i = 0; i < program.variableCount(); ++i) {
int cls = classes.find(i);
if (!importantNodes.contains(cls)) {
if (!escaping.contains(i) && i >= significantParams.length) {
result[i] = -1;
continue;
}
int cls = classes.find(i);
int packedCls = classMap[cls];
if (packedCls < 0) {
packedCls = classCount++;
@ -131,6 +99,32 @@ public class DataFlowGraphBuilder implements InstructionReader {
return result;
}
private void propagateEscaping(Graph graph) {
IntegerStack stack = new IntegerStack(graph.size());
for (IntCursor node : escaping) {
stack.push(node.value);
}
escaping.clear();
while (!stack.isEmpty()) {
int node = stack.pop();
if (!escaping.add(node)) {
continue;
}
if (node < graph.size()) {
for (int pred : graph.incomingEdges(node)) {
if (!escaping.contains(pred)) {
stack.push(pred);
}
}
for (int succ : graph.outgoingEdges(node)) {
if (!escaping.contains(succ)) {
stack.push(succ);
}
}
}
}
}
@Override
public void location(InstructionLocation location) {
}
@ -176,15 +170,19 @@ public class DataFlowGraphBuilder implements InstructionReader {
public void negate(VariableReader receiver, VariableReader operand, NumericOperandType type) {
}
private void connect(int a, int b) {
builder.addEdge(a, b);
join(a, b);
}
@Override
public void assign(VariableReader receiver, VariableReader assignee) {
builder.addEdge(assignee.getIndex(), receiver.getIndex());
connect(assignee.getIndex(), receiver.getIndex());
}
@Override
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
builder.addEdge(value.getIndex(), receiver.getIndex());
important(receiver.getIndex());
}
@Override
@ -219,15 +217,14 @@ public class DataFlowGraphBuilder implements InstructionReader {
@Override
public void exit(VariableReader valueToReturn) {
if (valueToReturn != null && returnIndex >= 0) {
important(returnIndex);
builder.addEdge(valueToReturn.getIndex(), returnIndex);
connect(valueToReturn.getIndex(), returnIndex);
}
}
@Override
public void raise(VariableReader exception) {
builder.addEdge(exception.getIndex(), exceptionIndex);
important(exceptionIndex);
escaping.add(exceptionIndex);
}
@Override
@ -245,10 +242,10 @@ public class DataFlowGraphBuilder implements InstructionReader {
private int getFieldNode(FieldReference field) {
int fieldNode = fieldNodes.getOrDefault(field, -1);
if (fieldNode < 0) {
fieldNode = lastIndex++;
fieldNode = classes.create();
fieldNodes.put(field, fieldNode);
}
important(fieldNode);
escaping.add(fieldNode);
return fieldNode;
}
@ -257,8 +254,7 @@ public class DataFlowGraphBuilder implements InstructionReader {
if (fieldType instanceof ValueType.Primitive) {
return;
}
int fieldNode = getFieldNode(field);
builder.addEdge(fieldNode, receiver.getIndex());
connect(getFieldNode(field), receiver.getIndex());
}
@Override
@ -266,8 +262,7 @@ public class DataFlowGraphBuilder implements InstructionReader {
if (fieldType instanceof ValueType.Primitive) {
return;
}
int fieldNode = getFieldNode(field);
builder.addEdge(value.getIndex(), fieldNode);
connect(value.getIndex(), getFieldNode(field));
}
@Override
@ -276,65 +271,40 @@ public class DataFlowGraphBuilder implements InstructionReader {
@Override
public void cloneArray(VariableReader receiver, VariableReader array) {
important(receiver.getIndex());
builder.addEdge(array.getIndex(), receiver.getIndex());
}
@Override
public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) {
if (elementType == ArrayElementType.OBJECT) {
builder.addEdge(array.getIndex(), receiver.getIndex());
connect(array.getIndex(), receiver.getIndex());
}
}
private int getArrayElementNode(int array) {
int node = arrayNodes[array];
if (node < 0) {
node = lastIndex++;
arrayNodes[array] = node;
}
important(node);
return node;
}
@Override
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) {
important(array.getIndex());
builder.addEdge(getArrayElementNode(array.getIndex()), receiver.getIndex());
builder.addEdge(array.getIndex(), receiver.getIndex());
}
@Override
public void putElement(VariableReader array, VariableReader index, VariableReader value) {
important(array.getIndex());
builder.addEdge(value.getIndex(), getArrayElementNode(array.getIndex()));
}
private int getMethodNode(MethodReference method) {
int methodNode = methodNodes.getOrDefault(method, -1);
if (methodNode < 0) {
methodNode = lastIndex++;
methodNodes.put(method, methodNode);
}
important(methodNode);
return methodNode;
builder.addEdge(value.getIndex(), array.getIndex());
}
@Override
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
List<? extends VariableReader> arguments, InvocationType type) {
if (receiver != null) {
if (!(method.getReturnType() instanceof ValueType.Primitive)) {
builder.addEdge(getMethodNode(method), receiver.getIndex());
}
}
ValueType[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; ++i) {
if (!(paramTypes[i] instanceof ValueType.Primitive)) {
important(arguments.get(i).getIndex());
escaping.add(arguments.get(i).getIndex());
}
}
if (instance != null) {
important(instance.getIndex());
escaping.add(instance.getIndex());
}
if (receiver != null && !(method.getReturnType() instanceof ValueType.Primitive)) {
escaping.add(receiver.getIndex());
}
}
@ -348,16 +318,16 @@ public class DataFlowGraphBuilder implements InstructionReader {
@Override
public void nullCheck(VariableReader receiver, VariableReader value) {
builder.addEdge(value.getIndex(), receiver.getIndex());
connect(value.getIndex(), receiver.getIndex());
}
@Override
public void monitorEnter(VariableReader objectRef) {
important(objectRef.getIndex());
escaping.add(objectRef.getIndex());
}
@Override
public void monitorExit(VariableReader objectRef) {
important(objectRef.getIndex());
escaping.add(exceptionIndex);
}
}

View File

@ -504,7 +504,6 @@ public class DependencyChecker implements DependencyInfo {
index = 0;
}
}
return;
}
public <T> T getService(Class<T> type) {

View File

@ -51,10 +51,15 @@ class DependencyGraphBuilder {
resultNode = dep.getResult();
DataFlowGraphBuilder dfgBuilder = new DataFlowGraphBuilder();
for (int i = 0; i < dep.getParameterCount(); ++i) {
dfgBuilder.important(i);
boolean[] significantParams = new boolean[dep.getParameterCount()];
significantParams[0] = true;
for (int i = 1; i < dep.getParameterCount(); ++i) {
ValueType arg = method.parameterType(i - 1);
if (!(arg instanceof ValueType.Primitive)) {
significantParams[i] = true;
}
}
int[] nodeMapping = dfgBuilder.buildMapping(program, dep.getParameterCount(),
int[] nodeMapping = dfgBuilder.buildMapping(program, significantParams,
!(method.getResultType() instanceof ValueType.Primitive) && method.getResultType() != ValueType.VOID);
if (DependencyChecker.shouldLog) {
@ -93,8 +98,8 @@ class DependencyGraphBuilder {
for (IncomingReader incoming : phi.readIncomings()) {
DependencyNode incomingNode = nodes[incoming.getValue().getIndex()];
DependencyNode receiverNode = nodes[phi.getReceiver().getIndex()];
if (incomingNode != null || receiverNode != null) {
nodes[incoming.getValue().getIndex()].connect(nodes[phi.getReceiver().getIndex()]);
if (incomingNode != null && receiverNode != null) {
incomingNode.connect(receiverNode);
}
}
}
@ -139,7 +144,9 @@ class DependencyGraphBuilder {
for (int i = 0; i < exceptions.length; ++i) {
if (exceptions[i] == null || isAssignableFrom(checker.getClassSource(), exceptions[i],
type.getName())) {
vars[i].propagate(type);
if (vars[i] != null) {
vars[i].propagate(type);
}
return;
}
}
@ -193,7 +200,7 @@ class DependencyGraphBuilder {
methodDep.use();
DependencyNode[] targetParams = methodDep.getVariables();
for (int i = 0; i < parameters.length; ++i) {
if (parameters[i] != null) {
if (parameters[i] != null && targetParams[i] != null) {
parameters[i].connect(targetParams[i]);
}
}
@ -307,18 +314,23 @@ class DependencyGraphBuilder {
String targetClsName = ((ValueType.Object)targetType).getClassName();
final ClassReader targetClass = dependencyChecker.getClassSource().get(targetClsName);
if (targetClass != null) {
valueNode.connect(receiverNode, new DependencyTypeFilter() {
@Override public boolean match(DependencyType type) {
if (targetClass.getName().equals("java.lang.Object")) {
return true;
if (valueNode != null && receiverNode != null) {
valueNode.connect(receiverNode, new DependencyTypeFilter() {
@Override public boolean match(DependencyType type) {
if (targetClass.getName().equals("java.lang.Object")) {
return true;
}
return isAssignableFrom(dependencyChecker.getClassSource(), targetClass,
type.getName());
}
return isAssignableFrom(dependencyChecker.getClassSource(), targetClass, type.getName());
}
});
});
}
return;
}
}
valueNode.connect(receiverNode);
if (valueNode != null && receiverNode != null) {
valueNode.connect(receiverNode);
}
}
@Override
@ -481,7 +493,7 @@ class DependencyGraphBuilder {
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) {
DependencyNode arrayNode = nodes[array.getIndex()];
DependencyNode receiverNode = nodes[receiver.getIndex()];
if (arrayNode != null && receiverNode != null) {
if (arrayNode != null && receiverNode != null && receiverNode != arrayNode.getArrayItem()) {
arrayNode.getArrayItem().connect(receiverNode);
}
}
@ -490,7 +502,7 @@ class DependencyGraphBuilder {
public void putElement(VariableReader array, VariableReader index, VariableReader value) {
DependencyNode valueNode = nodes[value.getIndex()];
DependencyNode arrayNode = nodes[array.getIndex()];
if (valueNode != null && arrayNode != null) {
if (valueNode != null && arrayNode != null && valueNode != arrayNode.getArrayItem()) {
valueNode.connect(arrayNode.getArrayItem());
}
}

View File

@ -24,6 +24,7 @@ import java.util.*;
public class DependencyNode implements ValueDependencyInfo {
private DependencyChecker dependencyChecker;
private List<DependencyConsumer> followers;
private int[] smallTypes;
private BitSet types;
private List<DependencyNodeToNodeTransition> transitions;
private volatile String tag;
@ -41,6 +42,38 @@ public class DependencyNode implements ValueDependencyInfo {
this.degree = degree;
}
private boolean addType(DependencyType type) {
if (types == null) {
if (smallTypes == null) {
smallTypes = new int[] { type.index };
return true;
}
}
if (smallTypes != null) {
for (int i = 0; i < smallTypes.length; ++i) {
if (smallTypes[i] == type.index) {
return false;
}
}
if (smallTypes.length == 5) {
types = new BitSet();
for (int existingType : smallTypes) {
types.set(existingType);
}
smallTypes = null;
} else {
smallTypes = Arrays.copyOf(smallTypes, smallTypes.length + 1);
smallTypes[smallTypes.length - 1] = type.index;
return true;
}
}
if (!types.get(type.index)) {
types.set(type.index);
return true;
}
return false;
}
public void propagate(DependencyType type) {
if (type.getDependencyChecker() != dependencyChecker) {
throw new IllegalArgumentException("The given type does not belong to the same dependency checker");
@ -48,11 +81,7 @@ public class DependencyNode implements ValueDependencyInfo {
if (degree > 2) {
return;
}
if (types == null) {
types = new BitSet();
}
if (!types.get(type.index)) {
types.set(type.index);
if (addType(type)) {
if (DependencyChecker.shouldLog) {
System.out.println(tag + " -> " + type.getName());
}
@ -64,30 +93,30 @@ public class DependencyNode implements ValueDependencyInfo {
}
}
public void propagate(DependencyType[] agentTypes) {
DependencyType[] types = new DependencyType[agentTypes.length];
public void propagate(DependencyType[] newTypes) {
DependencyType[] types = new DependencyType[newTypes.length];
int j = 0;
for (int i = 0; i < agentTypes.length; ++i) {
DependencyType type = agentTypes[i];
for (int i = 0; i < newTypes.length; ++i) {
DependencyType type = newTypes[i];
if (type.getDependencyChecker() != dependencyChecker) {
throw new IllegalArgumentException("The given type does not belong to the same dependency checker");
}
if (this.types == null || !this.types.get(type.index)) {
if (addType(type)) {
types[j++] = type;
}
}
if (this.types == null) {
this.types = new BitSet();
if (j == 0) {
return;
}
for (int i = 0; i < j; ++i) {
this.types.set(types[i].index);
if (DependencyChecker.shouldLog) {
if (DependencyChecker.shouldLog) {
for (int i = 0; i < j; ++i) {
System.out.println(tag + " -> " + types[i].getName());
}
}
if (followers != null) {
types = Arrays.copyOf(types, j);
for (DependencyConsumer consumer : followers.toArray(new DependencyConsumer[followers.size()])) {
dependencyChecker.schedulePropagation(consumer, Arrays.copyOf(types, j));
dependencyChecker.schedulePropagation(consumer, types);
}
}
}
@ -106,6 +135,12 @@ public class DependencyNode implements ValueDependencyInfo {
types.add(dependencyChecker.types.get(index));
}
dependencyChecker.schedulePropagation(consumer, 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(consumer, types);
}
}
@ -158,10 +193,18 @@ public class DependencyNode implements ValueDependencyInfo {
@Override
public boolean hasArrayType() {
return arrayItemNode != null && arrayItemNode.types != null && !arrayItemNode.types.isEmpty();
return arrayItemNode != null && (arrayItemNode.types != null || arrayItemNode.smallTypes != null);
}
public boolean hasType(DependencyType type) {
if (smallTypes != null) {
for (int i = 0; i < smallTypes.length; ++i) {
if (smallTypes[i] == type.index) {
return true;
}
}
return false;
}
return types != null && type.getDependencyChecker() == dependencyChecker && types.get(type.index);
}
@ -172,6 +215,13 @@ public class DependencyNode implements ValueDependencyInfo {
@Override
public String[] getTypes() {
if (smallTypes != null) {
String[] result = new String[smallTypes.length];
for (int i = 0; i < result.length; ++i) {
result[i] = dependencyChecker.types.get(smallTypes[i]).getName();
}
return result;
}
if (types == null) {
return new String[0];
}