mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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":
|
||||
generateHashCode(context, writer);
|
||||
break;
|
||||
case "equals":
|
||||
generateEquals(context, writer);
|
||||
break;
|
||||
case "clone":
|
||||
generateClone(context, writer);
|
||||
break;
|
||||
|
@ -84,11 +81,6 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
|||
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) {
|
||||
writer.append("var copy = new ").append(context.getParameterName(0)).append(".$class();").newLine();
|
||||
writer.append("for (var field in obj) {").newLine().indent();
|
||||
|
|
|
@ -28,8 +28,9 @@ public class TObject {
|
|||
@GeneratedBy(ObjectNativeGenerator.class)
|
||||
public native int hashCode();
|
||||
|
||||
@GeneratedBy(ObjectNativeGenerator.class)
|
||||
public native boolean equals(TObject other);
|
||||
public boolean equals(TObject other) {
|
||||
return this == other;
|
||||
}
|
||||
|
||||
@Rename("toString")
|
||||
public native TString toString0();
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.teavm.javascript.Renderer;
|
|||
import org.teavm.javascript.ast.ClassNode;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.resource.ClasspathClassHolderSource;
|
||||
import org.teavm.optimization.ClassSetOptimizer;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -55,8 +56,10 @@ public class ClasslibTestGenerator {
|
|||
dependencyChecker.addEntryPoint(methodRef);
|
||||
}
|
||||
dependencyChecker.checkDependencies();
|
||||
dependencyChecker.cutUnachievableClasses();
|
||||
decompileClasses(dependencyChecker.getAchievableClasses());
|
||||
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
|
||||
ClassSetOptimizer optimizer = new ClassSetOptimizer();
|
||||
optimizer.optimizeAll(classSet);
|
||||
decompileClasses(classSet.getClassNames());
|
||||
renderHead();
|
||||
ClassLoader classLoader = ClasslibTestGenerator.class.getClassLoader();
|
||||
try (InputStream input = classLoader.getResourceAsStream("org/teavm/classlib/junit-support.js")) {
|
||||
|
|
|
@ -289,6 +289,7 @@ public class DependencyChecker {
|
|||
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
||||
for (String className : achievableClasses.keySet()) {
|
||||
ClassHolder classHolder = classSource.getClassHolder(className);
|
||||
cutClasses.putClassHolder(classHolder);
|
||||
for (MethodHolder method : classHolder.getMethods().toArray(new MethodHolder[0])) {
|
||||
MethodReference methodRef = new MethodReference(className, method.getDescriptor());
|
||||
if (!methodCache.getCachedPreimages().contains(methodRef)) {
|
||||
|
|
|
@ -66,7 +66,7 @@ public class BasicBlock {
|
|||
|
||||
@Override
|
||||
public Instruction remove(int index) {
|
||||
Instruction insn = super.remove(index);
|
||||
Instruction insn = instructions.remove(index);
|
||||
insn.setBasicBlock(null);
|
||||
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