mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Adds unused variable elimination
This commit is contained in:
parent
ac0df0ca6b
commit
601fcf0824
|
@ -27,9 +27,6 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||||
case "hashCode":
|
case "hashCode":
|
||||||
generateHashCode(context, writer);
|
generateHashCode(context, writer);
|
||||||
break;
|
break;
|
||||||
case "equals":
|
|
||||||
generateEquals(context, writer);
|
|
||||||
break;
|
|
||||||
case "clone":
|
case "clone":
|
||||||
generateClone(context, writer);
|
generateClone(context, writer);
|
||||||
break;
|
break;
|
||||||
|
@ -84,11 +81,6 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||||
writer.append("return ").append(context.getParameterName(0)).append(".$id;").newLine();
|
writer.append("return ").append(context.getParameterName(0)).append(".$id;").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateEquals(GeneratorContext context, SourceWriter writer) {
|
|
||||||
writer.append("return ").append(context.getParameterName(0)).append(" == ")
|
|
||||||
.append(context.getParameterName(1)).append(";").newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateClone(GeneratorContext context, SourceWriter writer) {
|
private void generateClone(GeneratorContext context, SourceWriter writer) {
|
||||||
writer.append("var copy = new ").append(context.getParameterName(0)).append(".$class();").newLine();
|
writer.append("var copy = new ").append(context.getParameterName(0)).append(".$class();").newLine();
|
||||||
writer.append("for (var field in obj) {").newLine().indent();
|
writer.append("for (var field in obj) {").newLine().indent();
|
||||||
|
|
|
@ -28,8 +28,9 @@ public class TObject {
|
||||||
@GeneratedBy(ObjectNativeGenerator.class)
|
@GeneratedBy(ObjectNativeGenerator.class)
|
||||||
public native int hashCode();
|
public native int hashCode();
|
||||||
|
|
||||||
@GeneratedBy(ObjectNativeGenerator.class)
|
public boolean equals(TObject other) {
|
||||||
public native boolean equals(TObject other);
|
return this == other;
|
||||||
|
}
|
||||||
|
|
||||||
@Rename("toString")
|
@Rename("toString")
|
||||||
public native TString toString0();
|
public native TString toString0();
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.teavm.javascript.Renderer;
|
||||||
import org.teavm.javascript.ast.ClassNode;
|
import org.teavm.javascript.ast.ClassNode;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.resource.ClasspathClassHolderSource;
|
import org.teavm.model.resource.ClasspathClassHolderSource;
|
||||||
|
import org.teavm.optimization.ClassSetOptimizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -55,8 +56,10 @@ public class ClasslibTestGenerator {
|
||||||
dependencyChecker.addEntryPoint(methodRef);
|
dependencyChecker.addEntryPoint(methodRef);
|
||||||
}
|
}
|
||||||
dependencyChecker.checkDependencies();
|
dependencyChecker.checkDependencies();
|
||||||
dependencyChecker.cutUnachievableClasses();
|
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
|
||||||
decompileClasses(dependencyChecker.getAchievableClasses());
|
ClassSetOptimizer optimizer = new ClassSetOptimizer();
|
||||||
|
optimizer.optimizeAll(classSet);
|
||||||
|
decompileClasses(classSet.getClassNames());
|
||||||
renderHead();
|
renderHead();
|
||||||
ClassLoader classLoader = ClasslibTestGenerator.class.getClassLoader();
|
ClassLoader classLoader = ClasslibTestGenerator.class.getClassLoader();
|
||||||
try (InputStream input = classLoader.getResourceAsStream("org/teavm/classlib/junit-support.js")) {
|
try (InputStream input = classLoader.getResourceAsStream("org/teavm/classlib/junit-support.js")) {
|
||||||
|
|
|
@ -289,6 +289,7 @@ public class DependencyChecker {
|
||||||
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
||||||
for (String className : achievableClasses.keySet()) {
|
for (String className : achievableClasses.keySet()) {
|
||||||
ClassHolder classHolder = classSource.getClassHolder(className);
|
ClassHolder classHolder = classSource.getClassHolder(className);
|
||||||
|
cutClasses.putClassHolder(classHolder);
|
||||||
for (MethodHolder method : classHolder.getMethods().toArray(new MethodHolder[0])) {
|
for (MethodHolder method : classHolder.getMethods().toArray(new MethodHolder[0])) {
|
||||||
MethodReference methodRef = new MethodReference(className, method.getDescriptor());
|
MethodReference methodRef = new MethodReference(className, method.getDescriptor());
|
||||||
if (!methodCache.getCachedPreimages().contains(methodRef)) {
|
if (!methodCache.getCachedPreimages().contains(methodRef)) {
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class BasicBlock {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Instruction remove(int index) {
|
public Instruction remove(int index) {
|
||||||
Instruction insn = super.remove(index);
|
Instruction insn = instructions.remove(index);
|
||||||
insn.setBasicBlock(null);
|
insn.setBasicBlock(null);
|
||||||
return insn;
|
return insn;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.teavm.optimization;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ListableClassHolderSource;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class ClassSetOptimizer {
|
||||||
|
private List<MethodOptimization> optimizations = Arrays.<MethodOptimization>asList(
|
||||||
|
new UnusedVariableElimination());
|
||||||
|
|
||||||
|
public void optimizeAll(ListableClassHolderSource classSource) {
|
||||||
|
for (String className : classSource.getClassNames()) {
|
||||||
|
ClassHolder cls = classSource.getClassHolder(className);
|
||||||
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
|
for (MethodOptimization optimization : optimizations) {
|
||||||
|
optimization.optimize(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.teavm.optimization;
|
||||||
|
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public interface MethodOptimization {
|
||||||
|
void optimize(MethodHolder method);
|
||||||
|
}
|
|
@ -0,0 +1,224 @@
|
||||||
|
package org.teavm.optimization;
|
||||||
|
|
||||||
|
import org.teavm.common.Graph;
|
||||||
|
import org.teavm.model.*;
|
||||||
|
import org.teavm.model.instructions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class UnusedVariableElimination implements MethodOptimization {
|
||||||
|
@Override
|
||||||
|
public void optimize(MethodHolder method) {
|
||||||
|
if (method.getProgram() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Graph graph = VariableUsageGraphBuilder.build(method.getProgram());
|
||||||
|
boolean[] escaping = VariableEscapeAnalyzer.findEscapingVariables(method.getProgram());
|
||||||
|
boolean[] used = new boolean[escaping.length];
|
||||||
|
|
||||||
|
int[] stack = new int[graph.size() * 2];
|
||||||
|
int top = 0;
|
||||||
|
for (int i = 0; i < used.length; ++i) {
|
||||||
|
if (escaping[i]) {
|
||||||
|
stack[top++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (top > 0) {
|
||||||
|
int var = stack[--top];
|
||||||
|
if (used[var]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
used[var] = true;
|
||||||
|
for (int arg : graph.incomingEdges(var)) {
|
||||||
|
if (!used[arg]) {
|
||||||
|
stack[top++] = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Program program = method.getProgram();
|
||||||
|
InstructionOptimizer insnOptimizer = new InstructionOptimizer(used);
|
||||||
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
|
for (int j = 0; j < block.getInstructions().size(); ++j) {
|
||||||
|
insnOptimizer.eliminate = false;
|
||||||
|
block.getInstructions().get(j).acceptVisitor(insnOptimizer);
|
||||||
|
if (insnOptimizer.eliminate) {
|
||||||
|
block.getInstructions().remove(j--);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int j = 0; j < block.getPhis().size(); ++j) {
|
||||||
|
Phi phi = block.getPhis().get(j);
|
||||||
|
if (!used[phi.getReceiver().getIndex()]) {
|
||||||
|
block.getPhis().remove(j--);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InstructionOptimizer implements InstructionVisitor {
|
||||||
|
private boolean[] used;
|
||||||
|
boolean eliminate;
|
||||||
|
|
||||||
|
public InstructionOptimizer(boolean[] used) {
|
||||||
|
this.used = used;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestUsage(Variable var) {
|
||||||
|
if (!used[var.getIndex()]) {
|
||||||
|
eliminate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(EmptyInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ClassConstantInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NullConstantInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IntegerConstantInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LongConstantInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(FloatConstantInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(DoubleConstantInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StringConstantInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NegateInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastNumberInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BranchingInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryBranchingInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(JumpInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExitInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(RaiseInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructArrayInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructMultiArrayInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GetFieldInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(PutFieldInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ArrayLengthInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CloneArrayInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnwrapArrayInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GetElementInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(PutElementInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InvokeInstruction insn) {
|
||||||
|
if (insn.getReceiver() != null && !used[insn.getReceiver().getIndex()]) {
|
||||||
|
insn.setReceiver(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IsInstanceInstruction insn) {
|
||||||
|
requestUsage(insn.getReceiver());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
package org.teavm.optimization;
|
||||||
|
|
||||||
|
import org.teavm.model.BasicBlock;
|
||||||
|
import org.teavm.model.Instruction;
|
||||||
|
import org.teavm.model.Program;
|
||||||
|
import org.teavm.model.Variable;
|
||||||
|
import org.teavm.model.instructions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class VariableEscapeAnalyzer {
|
||||||
|
public static boolean[] findEscapingVariables(Program program) {
|
||||||
|
boolean[] escaping = new boolean[program.variableCount()];
|
||||||
|
InstructionAnalyzer analyzer = new InstructionAnalyzer(escaping);
|
||||||
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
|
for (Instruction insn : block.getInstructions()) {
|
||||||
|
insn.acceptVisitor(analyzer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return escaping;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class InstructionAnalyzer implements InstructionVisitor {
|
||||||
|
private boolean[] escaping;
|
||||||
|
|
||||||
|
public InstructionAnalyzer(boolean[] escaping) {
|
||||||
|
this.escaping = escaping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(EmptyInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ClassConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NullConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IntegerConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LongConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(FloatConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(DoubleConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StringConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NegateInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastNumberInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BranchingInstruction insn) {
|
||||||
|
escaping[insn.getOperand().getIndex()] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryBranchingInstruction insn) {
|
||||||
|
escaping[insn.getFirstOperand().getIndex()] = true;
|
||||||
|
escaping[insn.getSecondOperand().getIndex()] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(JumpInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchInstruction insn) {
|
||||||
|
escaping[insn.getCondition().getIndex()] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExitInstruction insn) {
|
||||||
|
if (insn.getValueToReturn() != null) {
|
||||||
|
escaping[insn.getValueToReturn().getIndex()] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(RaiseInstruction insn) {
|
||||||
|
escaping[insn.getException().getIndex()] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructArrayInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructMultiArrayInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GetFieldInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(PutFieldInstruction insn) {
|
||||||
|
if (insn.getInstance() != null) {
|
||||||
|
escaping[insn.getInstance().getIndex()] = true;
|
||||||
|
}
|
||||||
|
escaping[insn.getValue().getIndex()] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ArrayLengthInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CloneArrayInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnwrapArrayInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GetElementInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(PutElementInstruction insn) {
|
||||||
|
escaping[insn.getArray().getIndex()] = true;
|
||||||
|
escaping[insn.getIndex().getIndex()] = true;
|
||||||
|
escaping[insn.getValue().getIndex()] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InvokeInstruction insn) {
|
||||||
|
if (insn.getInstance() != null) {
|
||||||
|
escaping[insn.getInstance().getIndex()] = true;
|
||||||
|
}
|
||||||
|
for (Variable arg : insn.getArguments()) {
|
||||||
|
escaping[arg.getIndex()] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IsInstanceInstruction insn) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
package org.teavm.optimization;
|
||||||
|
|
||||||
|
import org.teavm.common.Graph;
|
||||||
|
import org.teavm.common.GraphBuilder;
|
||||||
|
import org.teavm.model.*;
|
||||||
|
import org.teavm.model.instructions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class VariableUsageGraphBuilder {
|
||||||
|
public static Graph build(Program program) {
|
||||||
|
GraphBuilder builder = new GraphBuilder(program.variableCount());
|
||||||
|
InstructionAnalyzer analyzer = new InstructionAnalyzer(builder);
|
||||||
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
|
for (Instruction insn : block.getInstructions()) {
|
||||||
|
insn.acceptVisitor(analyzer);
|
||||||
|
}
|
||||||
|
for (Phi phi : block.getPhis()) {
|
||||||
|
for (Incoming incoming : phi.getIncomings()) {
|
||||||
|
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class InstructionAnalyzer implements InstructionVisitor {
|
||||||
|
private GraphBuilder builder;
|
||||||
|
|
||||||
|
public InstructionAnalyzer(GraphBuilder builder) {
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void use(Variable receiver, Variable... arguments) {
|
||||||
|
for (Variable arg : arguments) {
|
||||||
|
builder.addEdge(arg.getIndex(), receiver.getIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(EmptyInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ClassConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NullConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IntegerConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(LongConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(FloatConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(DoubleConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StringConstantInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getFirstOperand(), insn.getSecondOperand());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NegateInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getOperand());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getAssignee());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastNumberInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BranchingInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryBranchingInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(JumpInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExitInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(RaiseInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructArrayInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstructMultiArrayInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getDimensions().toArray(new Variable[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GetFieldInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(PutFieldInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ArrayLengthInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CloneArrayInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnwrapArrayInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(GetElementInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getArray(), insn.getIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(PutElementInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InvokeInstruction insn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IsInstanceInstruction insn) {
|
||||||
|
use(insn.getReceiver(), insn.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user