In class inference add rules for known types of method parameters

and method return value
This commit is contained in:
Alexey Andreev 2017-04-27 00:14:14 +03:00
parent 8d9240df36
commit 293e82a3c0
2 changed files with 46 additions and 15 deletions

View File

@ -53,6 +53,7 @@ import org.teavm.model.instructions.CloneArrayInstruction;
import org.teavm.model.instructions.ConstructArrayInstruction; import org.teavm.model.instructions.ConstructArrayInstruction;
import org.teavm.model.instructions.ConstructInstruction; import org.teavm.model.instructions.ConstructInstruction;
import org.teavm.model.instructions.ConstructMultiArrayInstruction; import org.teavm.model.instructions.ConstructMultiArrayInstruction;
import org.teavm.model.instructions.ExitInstruction;
import org.teavm.model.instructions.GetElementInstruction; import org.teavm.model.instructions.GetElementInstruction;
import org.teavm.model.instructions.GetFieldInstruction; import org.teavm.model.instructions.GetFieldInstruction;
import org.teavm.model.instructions.InvocationType; import org.teavm.model.instructions.InvocationType;
@ -81,11 +82,24 @@ public class ClassInference {
} }
public void infer(Program program, MethodReference methodReference) { public void infer(Program program, MethodReference methodReference) {
buildGraphs(program);
MethodDependencyInfo thisMethodDep = dependencyInfo.getMethod(methodReference); MethodDependencyInfo thisMethodDep = dependencyInfo.getMethod(methodReference);
for (String thisType : thisMethodDep.getVariable(0).getTypes()) { buildGraphs(program, thisMethodDep);
initialTasks.add(new Task(0, 0, thisType));
for (int i = 0; i <= methodReference.parameterCount(); ++i) {
ValueDependencyInfo paramDep = thisMethodDep.getVariable(i);
if (paramDep != null) {
int degree = 0;
while (true) {
for (String paramType : paramDep.getTypes()) {
initialTasks.add(new Task(i, degree, paramType));
}
if (!paramDep.hasArrayType()) {
break;
}
paramDep = paramDep.getArrayItem();
degree++;
}
}
} }
types = new ArrayList<>(program.variableCount()); types = new ArrayList<>(program.variableCount());
@ -118,8 +132,9 @@ public class ClassInference {
return finalTypes.get(variableIndex).toArray(new String[0]); return finalTypes.get(variableIndex).toArray(new String[0]);
} }
private void buildGraphs(Program program) { private void buildGraphs(Program program, MethodDependencyInfo thisMethodDep) {
GraphBuildingVisitor visitor = new GraphBuildingVisitor(program.variableCount(), dependencyInfo); GraphBuildingVisitor visitor = new GraphBuildingVisitor(program.variableCount(), dependencyInfo);
visitor.thisMethodDep = thisMethodDep;
for (BasicBlock block : program.getBasicBlocks()) { for (BasicBlock block : program.getBasicBlocks()) {
visitor.currentBlock = block; visitor.currentBlock = block;
for (Phi phi : block.getPhis()) { for (Phi phi : block.getPhis()) {
@ -279,6 +294,7 @@ public class ClassInference {
GraphBuilder cloneGraphBuilder; GraphBuilder cloneGraphBuilder;
GraphBuilder arrayGraphBuilder; GraphBuilder arrayGraphBuilder;
GraphBuilder itemGraphBuilder; GraphBuilder itemGraphBuilder;
MethodDependencyInfo thisMethodDep;
List<IntObjectMap<ValueType>> casts = new ArrayList<>(); List<IntObjectMap<ValueType>> casts = new ArrayList<>();
IntObjectMap<IntSet> exceptionMap = new IntObjectOpenHashMap<>(); IntObjectMap<IntSet> exceptionMap = new IntObjectOpenHashMap<>();
List<Task> tasks = new ArrayList<>(); List<Task> tasks = new ArrayList<>();
@ -388,6 +404,20 @@ public class ClassInference {
arrayGraphBuilder.addEdge(insn.getValue().getIndex(), insn.getArray().getIndex()); arrayGraphBuilder.addEdge(insn.getValue().getIndex(), insn.getArray().getIndex());
} }
@Override
public void visit(ExitInstruction insn) {
if (insn.getValueToReturn() != null) {
ValueDependencyInfo resultDependency = thisMethodDep.getResult();
int resultDegree = 0;
while (resultDependency.hasArrayType()) {
resultDependency = resultDependency.getArrayItem();
for (String paramType : resultDependency.getTypes()) {
tasks.add(new Task(insn.getValueToReturn().getIndex(), ++resultDegree, paramType));
}
}
}
}
@Override @Override
public void visit(InvokeInstruction insn) { public void visit(InvokeInstruction insn) {
if (insn.getType() == InvocationType.VIRTUAL) { if (insn.getType() == InvocationType.VIRTUAL) {
@ -412,7 +442,7 @@ public class ClassInference {
} }
MethodDependencyInfo methodDep = dependencyInfo.getMethod(insn.getMethod()); MethodDependencyInfo methodDep = dependencyInfo.getMethod(insn.getMethod());
if (methodDep != null) {
if (insn.getReceiver() != null) { if (insn.getReceiver() != null) {
readValue(methodDep.getResult(), insn.getReceiver(), tasks); readValue(methodDep.getResult(), insn.getReceiver(), tasks);
} }
@ -426,6 +456,7 @@ public class ClassInference {
} }
} }
} }
}
private static void readValue(ValueDependencyInfo valueDep, Variable receiver, Collection<Task> tasks) { private static void readValue(ValueDependencyInfo valueDep, Variable receiver, Collection<Task> tasks) {
int depth = 0; int depth = 0;