mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Remove unnecessary debugging code
This commit is contained in:
parent
3449257db7
commit
004cb79b17
|
@ -31,7 +31,7 @@ public class IntegerStack {
|
||||||
|
|
||||||
public void push(int value) {
|
public void push(int value) {
|
||||||
if (head == buffer.length) {
|
if (head == buffer.length) {
|
||||||
buffer = Arrays.copyOf(buffer, buffer.length * 2);
|
buffer = Arrays.copyOf(buffer, Math.max(buffer.length * 2, 1));
|
||||||
}
|
}
|
||||||
buffer[head++] = value;
|
buffer[head++] = value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.carrotsearch.hppc.IntOpenHashSet;
|
||||||
import com.carrotsearch.hppc.IntSet;
|
import com.carrotsearch.hppc.IntSet;
|
||||||
import com.carrotsearch.hppc.ObjectIntMap;
|
import com.carrotsearch.hppc.ObjectIntMap;
|
||||||
import com.carrotsearch.hppc.ObjectIntOpenHashMap;
|
import com.carrotsearch.hppc.ObjectIntOpenHashMap;
|
||||||
|
import com.carrotsearch.hppc.cursors.IntCursor;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.teavm.common.*;
|
import org.teavm.common.*;
|
||||||
|
@ -32,95 +33,62 @@ import org.teavm.model.instructions.*;
|
||||||
public class DataFlowGraphBuilder implements InstructionReader {
|
public class DataFlowGraphBuilder implements InstructionReader {
|
||||||
private int lastIndex;
|
private int lastIndex;
|
||||||
private GraphBuilder builder = new GraphBuilder();
|
private GraphBuilder builder = new GraphBuilder();
|
||||||
private IntSet importantNodes = new IntOpenHashSet();
|
|
||||||
private ObjectIntMap<MethodReference> methodNodes = new ObjectIntOpenHashMap<>();
|
|
||||||
private ObjectIntMap<FieldReference> fieldNodes = new ObjectIntOpenHashMap<>();
|
private ObjectIntMap<FieldReference> fieldNodes = new ObjectIntOpenHashMap<>();
|
||||||
private int[] arrayNodes;
|
|
||||||
private int returnIndex = -1;
|
private int returnIndex = -1;
|
||||||
private int exceptionIndex;
|
private int exceptionIndex;
|
||||||
|
private DisjointSet classes = new DisjointSet();
|
||||||
|
private int paramCount;
|
||||||
|
private IntSet escaping = new IntOpenHashSet();
|
||||||
|
|
||||||
public void important(int node) {
|
private void join(int a, int b) {
|
||||||
importantNodes.add(node);
|
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();
|
lastIndex = program.variableCount();
|
||||||
arrayNodes = new int[lastIndex];
|
this.paramCount = significantParams.length;
|
||||||
if (needsReturn) {
|
if (needsReturn) {
|
||||||
returnIndex = lastIndex++;
|
returnIndex = lastIndex++;
|
||||||
|
escaping.add(returnIndex);
|
||||||
}
|
}
|
||||||
exceptionIndex = lastIndex++;
|
exceptionIndex = lastIndex++;
|
||||||
Arrays.fill(arrayNodes, -1);
|
for (int i = 0; i < lastIndex; ++i) {
|
||||||
|
classes.create();
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlockReader block = program.basicBlockAt(i);
|
BasicBlockReader block = program.basicBlockAt(i);
|
||||||
for (PhiReader phi : block.readPhis()) {
|
for (PhiReader phi : block.readPhis()) {
|
||||||
for (IncomingReader incoming : phi.readIncomings()) {
|
for (IncomingReader incoming : phi.readIncomings()) {
|
||||||
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
|
int from = incoming.getValue().getIndex();
|
||||||
}
|
int to = phi.getReceiver().getIndex();
|
||||||
}
|
builder.addEdge(from, to);
|
||||||
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
|
join(from, to);
|
||||||
if (tryCatch.getExceptionVariable() != null) {
|
|
||||||
important(tryCatch.getExceptionVariable().getIndex());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
block.readAllInstructions(this);
|
block.readAllInstructions(this);
|
||||||
}
|
}
|
||||||
Graph graph = builder.build();
|
Graph graph = builder.build();
|
||||||
|
for (int i = 0; i < paramCount; ++i) {
|
||||||
DisjointSet classes = new DisjointSet();
|
if (significantParams[i]) {
|
||||||
for (int i = 0; i < lastIndex; ++i) {
|
escaping.add(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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
propagateEscaping(graph);
|
||||||
|
|
||||||
int[] classMap = new int[classes.size()];
|
int[] classMap = new int[classes.size()];
|
||||||
Arrays.fill(classMap, -1);
|
Arrays.fill(classMap, -1);
|
||||||
int[] result = new int[program.variableCount()];
|
int[] result = new int[program.variableCount()];
|
||||||
int classCount = 0;
|
int classCount = 0;
|
||||||
for (int i = 0; i < program.variableCount(); ++i) {
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
int cls = classes.find(i);
|
if (!escaping.contains(i) && i >= significantParams.length) {
|
||||||
if (!importantNodes.contains(cls)) {
|
|
||||||
result[i] = -1;
|
result[i] = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
int cls = classes.find(i);
|
||||||
int packedCls = classMap[cls];
|
int packedCls = classMap[cls];
|
||||||
if (packedCls < 0) {
|
if (packedCls < 0) {
|
||||||
packedCls = classCount++;
|
packedCls = classCount++;
|
||||||
|
@ -131,6 +99,32 @@ public class DataFlowGraphBuilder implements InstructionReader {
|
||||||
return result;
|
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
|
@Override
|
||||||
public void location(InstructionLocation location) {
|
public void location(InstructionLocation location) {
|
||||||
}
|
}
|
||||||
|
@ -176,15 +170,19 @@ public class DataFlowGraphBuilder implements InstructionReader {
|
||||||
public void negate(VariableReader receiver, VariableReader operand, NumericOperandType type) {
|
public void negate(VariableReader receiver, VariableReader operand, NumericOperandType type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void connect(int a, int b) {
|
||||||
|
builder.addEdge(a, b);
|
||||||
|
join(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void assign(VariableReader receiver, VariableReader assignee) {
|
public void assign(VariableReader receiver, VariableReader assignee) {
|
||||||
builder.addEdge(assignee.getIndex(), receiver.getIndex());
|
connect(assignee.getIndex(), receiver.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
||||||
builder.addEdge(value.getIndex(), receiver.getIndex());
|
builder.addEdge(value.getIndex(), receiver.getIndex());
|
||||||
important(receiver.getIndex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -219,15 +217,14 @@ public class DataFlowGraphBuilder implements InstructionReader {
|
||||||
@Override
|
@Override
|
||||||
public void exit(VariableReader valueToReturn) {
|
public void exit(VariableReader valueToReturn) {
|
||||||
if (valueToReturn != null && returnIndex >= 0) {
|
if (valueToReturn != null && returnIndex >= 0) {
|
||||||
important(returnIndex);
|
connect(valueToReturn.getIndex(), returnIndex);
|
||||||
builder.addEdge(valueToReturn.getIndex(), returnIndex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void raise(VariableReader exception) {
|
public void raise(VariableReader exception) {
|
||||||
builder.addEdge(exception.getIndex(), exceptionIndex);
|
builder.addEdge(exception.getIndex(), exceptionIndex);
|
||||||
important(exceptionIndex);
|
escaping.add(exceptionIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -245,10 +242,10 @@ public class DataFlowGraphBuilder implements InstructionReader {
|
||||||
private int getFieldNode(FieldReference field) {
|
private int getFieldNode(FieldReference field) {
|
||||||
int fieldNode = fieldNodes.getOrDefault(field, -1);
|
int fieldNode = fieldNodes.getOrDefault(field, -1);
|
||||||
if (fieldNode < 0) {
|
if (fieldNode < 0) {
|
||||||
fieldNode = lastIndex++;
|
fieldNode = classes.create();
|
||||||
fieldNodes.put(field, fieldNode);
|
fieldNodes.put(field, fieldNode);
|
||||||
}
|
}
|
||||||
important(fieldNode);
|
escaping.add(fieldNode);
|
||||||
return fieldNode;
|
return fieldNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,8 +254,7 @@ public class DataFlowGraphBuilder implements InstructionReader {
|
||||||
if (fieldType instanceof ValueType.Primitive) {
|
if (fieldType instanceof ValueType.Primitive) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int fieldNode = getFieldNode(field);
|
connect(getFieldNode(field), receiver.getIndex());
|
||||||
builder.addEdge(fieldNode, receiver.getIndex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -266,8 +262,7 @@ public class DataFlowGraphBuilder implements InstructionReader {
|
||||||
if (fieldType instanceof ValueType.Primitive) {
|
if (fieldType instanceof ValueType.Primitive) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int fieldNode = getFieldNode(field);
|
connect(value.getIndex(), getFieldNode(field));
|
||||||
builder.addEdge(value.getIndex(), fieldNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -276,65 +271,40 @@ public class DataFlowGraphBuilder implements InstructionReader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cloneArray(VariableReader receiver, VariableReader array) {
|
public void cloneArray(VariableReader receiver, VariableReader array) {
|
||||||
important(receiver.getIndex());
|
|
||||||
builder.addEdge(array.getIndex(), receiver.getIndex());
|
builder.addEdge(array.getIndex(), receiver.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) {
|
public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) {
|
||||||
if (elementType == ArrayElementType.OBJECT) {
|
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
|
@Override
|
||||||
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) {
|
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) {
|
||||||
important(array.getIndex());
|
builder.addEdge(array.getIndex(), receiver.getIndex());
|
||||||
builder.addEdge(getArrayElementNode(array.getIndex()), receiver.getIndex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putElement(VariableReader array, VariableReader index, VariableReader value) {
|
public void putElement(VariableReader array, VariableReader index, VariableReader value) {
|
||||||
important(array.getIndex());
|
builder.addEdge(value.getIndex(), 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||||
List<? extends VariableReader> arguments, InvocationType type) {
|
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();
|
ValueType[] paramTypes = method.getParameterTypes();
|
||||||
for (int i = 0; i < paramTypes.length; ++i) {
|
for (int i = 0; i < paramTypes.length; ++i) {
|
||||||
if (!(paramTypes[i] instanceof ValueType.Primitive)) {
|
if (!(paramTypes[i] instanceof ValueType.Primitive)) {
|
||||||
important(arguments.get(i).getIndex());
|
escaping.add(arguments.get(i).getIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (instance != null) {
|
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
|
@Override
|
||||||
public void nullCheck(VariableReader receiver, VariableReader value) {
|
public void nullCheck(VariableReader receiver, VariableReader value) {
|
||||||
builder.addEdge(value.getIndex(), receiver.getIndex());
|
connect(value.getIndex(), receiver.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void monitorEnter(VariableReader objectRef) {
|
public void monitorEnter(VariableReader objectRef) {
|
||||||
important(objectRef.getIndex());
|
escaping.add(objectRef.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void monitorExit(VariableReader objectRef) {
|
public void monitorExit(VariableReader objectRef) {
|
||||||
important(objectRef.getIndex());
|
escaping.add(exceptionIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -504,7 +504,6 @@ public class DependencyChecker implements DependencyInfo {
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getService(Class<T> type) {
|
public <T> T getService(Class<T> type) {
|
||||||
|
|
|
@ -51,10 +51,15 @@ class DependencyGraphBuilder {
|
||||||
resultNode = dep.getResult();
|
resultNode = dep.getResult();
|
||||||
|
|
||||||
DataFlowGraphBuilder dfgBuilder = new DataFlowGraphBuilder();
|
DataFlowGraphBuilder dfgBuilder = new DataFlowGraphBuilder();
|
||||||
for (int i = 0; i < dep.getParameterCount(); ++i) {
|
boolean[] significantParams = new boolean[dep.getParameterCount()];
|
||||||
dfgBuilder.important(i);
|
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);
|
!(method.getResultType() instanceof ValueType.Primitive) && method.getResultType() != ValueType.VOID);
|
||||||
|
|
||||||
if (DependencyChecker.shouldLog) {
|
if (DependencyChecker.shouldLog) {
|
||||||
|
@ -93,8 +98,8 @@ class DependencyGraphBuilder {
|
||||||
for (IncomingReader incoming : phi.readIncomings()) {
|
for (IncomingReader incoming : phi.readIncomings()) {
|
||||||
DependencyNode incomingNode = nodes[incoming.getValue().getIndex()];
|
DependencyNode incomingNode = nodes[incoming.getValue().getIndex()];
|
||||||
DependencyNode receiverNode = nodes[phi.getReceiver().getIndex()];
|
DependencyNode receiverNode = nodes[phi.getReceiver().getIndex()];
|
||||||
if (incomingNode != null || receiverNode != null) {
|
if (incomingNode != null && receiverNode != null) {
|
||||||
nodes[incoming.getValue().getIndex()].connect(nodes[phi.getReceiver().getIndex()]);
|
incomingNode.connect(receiverNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +144,9 @@ class DependencyGraphBuilder {
|
||||||
for (int i = 0; i < exceptions.length; ++i) {
|
for (int i = 0; i < exceptions.length; ++i) {
|
||||||
if (exceptions[i] == null || isAssignableFrom(checker.getClassSource(), exceptions[i],
|
if (exceptions[i] == null || isAssignableFrom(checker.getClassSource(), exceptions[i],
|
||||||
type.getName())) {
|
type.getName())) {
|
||||||
vars[i].propagate(type);
|
if (vars[i] != null) {
|
||||||
|
vars[i].propagate(type);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +200,7 @@ class DependencyGraphBuilder {
|
||||||
methodDep.use();
|
methodDep.use();
|
||||||
DependencyNode[] targetParams = methodDep.getVariables();
|
DependencyNode[] targetParams = methodDep.getVariables();
|
||||||
for (int i = 0; i < parameters.length; ++i) {
|
for (int i = 0; i < parameters.length; ++i) {
|
||||||
if (parameters[i] != null) {
|
if (parameters[i] != null && targetParams[i] != null) {
|
||||||
parameters[i].connect(targetParams[i]);
|
parameters[i].connect(targetParams[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,18 +314,23 @@ class DependencyGraphBuilder {
|
||||||
String targetClsName = ((ValueType.Object)targetType).getClassName();
|
String targetClsName = ((ValueType.Object)targetType).getClassName();
|
||||||
final ClassReader targetClass = dependencyChecker.getClassSource().get(targetClsName);
|
final ClassReader targetClass = dependencyChecker.getClassSource().get(targetClsName);
|
||||||
if (targetClass != null) {
|
if (targetClass != null) {
|
||||||
valueNode.connect(receiverNode, new DependencyTypeFilter() {
|
if (valueNode != null && receiverNode != null) {
|
||||||
@Override public boolean match(DependencyType type) {
|
valueNode.connect(receiverNode, new DependencyTypeFilter() {
|
||||||
if (targetClass.getName().equals("java.lang.Object")) {
|
@Override public boolean match(DependencyType type) {
|
||||||
return true;
|
if (targetClass.getName().equals("java.lang.Object")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return isAssignableFrom(dependencyChecker.getClassSource(), targetClass,
|
||||||
|
type.getName());
|
||||||
}
|
}
|
||||||
return isAssignableFrom(dependencyChecker.getClassSource(), targetClass, type.getName());
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
valueNode.connect(receiverNode);
|
if (valueNode != null && receiverNode != null) {
|
||||||
|
valueNode.connect(receiverNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -481,7 +493,7 @@ class DependencyGraphBuilder {
|
||||||
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) {
|
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) {
|
||||||
DependencyNode arrayNode = nodes[array.getIndex()];
|
DependencyNode arrayNode = nodes[array.getIndex()];
|
||||||
DependencyNode receiverNode = nodes[receiver.getIndex()];
|
DependencyNode receiverNode = nodes[receiver.getIndex()];
|
||||||
if (arrayNode != null && receiverNode != null) {
|
if (arrayNode != null && receiverNode != null && receiverNode != arrayNode.getArrayItem()) {
|
||||||
arrayNode.getArrayItem().connect(receiverNode);
|
arrayNode.getArrayItem().connect(receiverNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,7 +502,7 @@ class DependencyGraphBuilder {
|
||||||
public void putElement(VariableReader array, VariableReader index, VariableReader value) {
|
public void putElement(VariableReader array, VariableReader index, VariableReader value) {
|
||||||
DependencyNode valueNode = nodes[value.getIndex()];
|
DependencyNode valueNode = nodes[value.getIndex()];
|
||||||
DependencyNode arrayNode = nodes[array.getIndex()];
|
DependencyNode arrayNode = nodes[array.getIndex()];
|
||||||
if (valueNode != null && arrayNode != null) {
|
if (valueNode != null && arrayNode != null && valueNode != arrayNode.getArrayItem()) {
|
||||||
valueNode.connect(arrayNode.getArrayItem());
|
valueNode.connect(arrayNode.getArrayItem());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.*;
|
||||||
public class DependencyNode implements ValueDependencyInfo {
|
public class DependencyNode implements ValueDependencyInfo {
|
||||||
private DependencyChecker dependencyChecker;
|
private DependencyChecker dependencyChecker;
|
||||||
private List<DependencyConsumer> followers;
|
private List<DependencyConsumer> followers;
|
||||||
|
private int[] smallTypes;
|
||||||
private BitSet types;
|
private BitSet types;
|
||||||
private List<DependencyNodeToNodeTransition> transitions;
|
private List<DependencyNodeToNodeTransition> transitions;
|
||||||
private volatile String tag;
|
private volatile String tag;
|
||||||
|
@ -41,6 +42,38 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
this.degree = degree;
|
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) {
|
public void propagate(DependencyType type) {
|
||||||
if (type.getDependencyChecker() != dependencyChecker) {
|
if (type.getDependencyChecker() != dependencyChecker) {
|
||||||
throw new IllegalArgumentException("The given type does not belong to the same dependency checker");
|
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) {
|
if (degree > 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (types == null) {
|
if (addType(type)) {
|
||||||
types = new BitSet();
|
|
||||||
}
|
|
||||||
if (!types.get(type.index)) {
|
|
||||||
types.set(type.index);
|
|
||||||
if (DependencyChecker.shouldLog) {
|
if (DependencyChecker.shouldLog) {
|
||||||
System.out.println(tag + " -> " + type.getName());
|
System.out.println(tag + " -> " + type.getName());
|
||||||
}
|
}
|
||||||
|
@ -64,30 +93,30 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void propagate(DependencyType[] agentTypes) {
|
public void propagate(DependencyType[] newTypes) {
|
||||||
DependencyType[] types = new DependencyType[agentTypes.length];
|
DependencyType[] types = new DependencyType[newTypes.length];
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i = 0; i < agentTypes.length; ++i) {
|
for (int i = 0; i < newTypes.length; ++i) {
|
||||||
DependencyType type = agentTypes[i];
|
DependencyType type = newTypes[i];
|
||||||
if (type.getDependencyChecker() != dependencyChecker) {
|
if (type.getDependencyChecker() != dependencyChecker) {
|
||||||
throw new IllegalArgumentException("The given type does not belong to the same dependency checker");
|
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;
|
types[j++] = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.types == null) {
|
if (j == 0) {
|
||||||
this.types = new BitSet();
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < j; ++i) {
|
if (DependencyChecker.shouldLog) {
|
||||||
this.types.set(types[i].index);
|
for (int i = 0; i < j; ++i) {
|
||||||
if (DependencyChecker.shouldLog) {
|
|
||||||
System.out.println(tag + " -> " + types[i].getName());
|
System.out.println(tag + " -> " + types[i].getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (followers != null) {
|
if (followers != null) {
|
||||||
|
types = Arrays.copyOf(types, j);
|
||||||
for (DependencyConsumer consumer : followers.toArray(new DependencyConsumer[followers.size()])) {
|
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));
|
types.add(dependencyChecker.types.get(index));
|
||||||
}
|
}
|
||||||
dependencyChecker.schedulePropagation(consumer, types.toArray(new DependencyType[types.size()]));
|
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
|
@Override
|
||||||
public boolean hasArrayType() {
|
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) {
|
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);
|
return types != null && type.getDependencyChecker() == dependencyChecker && types.get(type.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +215,13 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getTypes() {
|
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) {
|
if (types == null) {
|
||||||
return new String[0];
|
return new String[0];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user