Further work on incremental phi updater

This commit is contained in:
Alexey Andreev 2016-06-06 00:51:45 +03:00 committed by Alexey Andreev
parent fd7ff3d538
commit 85cbb4a75c
4 changed files with 123 additions and 64 deletions

View File

@ -152,6 +152,53 @@ public class BasicBlock implements BasicBlockReader {
} }
}; };
private List<TryCatchJoint> safeJoints = new AbstractList<TryCatchJoint>() {
@Override
public TryCatchJoint get(int index) {
return joints.get(index);
}
@Override
public int size() {
return joints.size();
}
@Override
public void add(int index, TryCatchJoint e) {
if (e.getBlock() != null) {
throw new IllegalArgumentException("This joint is already in some basic block");
}
e.block = BasicBlock.this;
joints.add(index, e);
}
@Override
public TryCatchJoint set(int index, TryCatchJoint element) {
if (element.block != null) {
throw new IllegalArgumentException("This phi is already in some basic block");
}
TryCatchJoint oldJoint = joints.get(index);
oldJoint.block = null;
element.block = BasicBlock.this;
return joints.set(index, element);
}
@Override
public TryCatchJoint remove(int index) {
TryCatchJoint joint = joints.remove(index);
joint.block = null;
return joint;
}
@Override
public void clear() {
for (TryCatchJoint joint : joints) {
joint.block = null;
}
joints.clear();
}
};
public List<Phi> getPhis() { public List<Phi> getPhis() {
return safePhis; return safePhis;
} }
@ -257,13 +304,13 @@ public class BasicBlock implements BasicBlockReader {
} }
public List<TryCatchJoint> getTryCatchJoints() { public List<TryCatchJoint> getTryCatchJoints() {
return joints; return safeJoints;
} }
@Override @Override
public List<TryCatchJointReader> readTryCatchJoints() { public List<TryCatchJointReader> readTryCatchJoints() {
if (immutableJoints == null) { if (immutableJoints == null) {
immutableJoints = Collections.unmodifiableList(joints); immutableJoints = Collections.unmodifiableList(safeJoints);
} }
return immutableJoints; return immutableJoints;
} }

View File

@ -24,6 +24,7 @@ public class TryCatchJoint implements TryCatchJointReader {
private List<Variable> sourceVariables = new ArrayList<>(); private List<Variable> sourceVariables = new ArrayList<>();
private List<VariableReader> readonlySourceVariables; private List<VariableReader> readonlySourceVariables;
private Variable receiver; private Variable receiver;
BasicBlock block;
@Override @Override
public List<VariableReader> readSourceVariables() { public List<VariableReader> readSourceVariables() {
@ -54,4 +55,8 @@ public class TryCatchJoint implements TryCatchJointReader {
public void setSource(BasicBlock source) { public void setSource(BasicBlock source) {
this.source = source; this.source = source;
} }
public BasicBlock getBlock() {
return block;
}
} }

View File

@ -23,4 +23,6 @@ public interface TryCatchJointReader {
VariableReader getReceiver(); VariableReader getReceiver();
BasicBlockReader getSource(); BasicBlockReader getSource();
BasicBlockReader getBlock();
} }

View File

@ -23,7 +23,6 @@ import java.util.Map;
import org.teavm.common.DominatorTree; import org.teavm.common.DominatorTree;
import org.teavm.common.Graph; import org.teavm.common.Graph;
import org.teavm.common.GraphUtils; import org.teavm.common.GraphUtils;
import org.teavm.common.IntegerArray;
import org.teavm.model.BasicBlock; import org.teavm.model.BasicBlock;
import org.teavm.model.Incoming; import org.teavm.model.Incoming;
import org.teavm.model.Instruction; import org.teavm.model.Instruction;
@ -83,11 +82,6 @@ public class PhiUpdater {
private List<List<Phi>> synthesizedPhis = new ArrayList<>(); private List<List<Phi>> synthesizedPhis = new ArrayList<>();
private List<List<TryCatchJoint>> synthesizedJoints = new ArrayList<>(); private List<List<TryCatchJoint>> synthesizedJoints = new ArrayList<>();
private boolean[] usedDefinitions; private boolean[] usedDefinitions;
private IntegerArray variableToSourceMap = new IntegerArray(10);
public int getSourceVariable(int var) {
return variableToSourceMap.get(var);
}
public void updatePhis(Program program, Variable[] arguments) { public void updatePhis(Program program, Variable[] arguments) {
if (program.basicBlockCount() == 0) { if (program.basicBlockCount() == 0) {
@ -99,11 +93,8 @@ public class PhiUpdater {
domFrontiers = new int[cfg.size()][]; domFrontiers = new int[cfg.size()][];
variableMap = new Variable[program.variableCount()]; variableMap = new Variable[program.variableCount()];
usedDefinitions = new boolean[program.variableCount()]; usedDefinitions = new boolean[program.variableCount()];
for (int i = 0; i < program.variableCount(); ++i) {
variableToSourceMap.add(-1);
}
for (int i = 0; i < arguments.length; ++i) { for (int i = 0; i < arguments.length; ++i) {
mapVariable(i, arguments[i]); variableMap[i] = arguments[i];
usedDefinitions[i] = true; usedDefinitions[i] = true;
} }
phiMap = new Phi[program.basicBlockCount()][]; phiMap = new Phi[program.basicBlockCount()][];
@ -184,13 +175,13 @@ public class PhiUpdater {
for (Phi phi : synthesizedPhis.get(index)) { for (Phi phi : synthesizedPhis.get(index)) {
Variable var = program.createVariable(); Variable var = program.createVariable();
var.getDebugNames().addAll(phi.getReceiver().getDebugNames()); var.getDebugNames().addAll(phi.getReceiver().getDebugNames());
mapVariable(phi.getReceiver().getIndex(), var); variableMap[phi.getReceiver().getIndex()] = var;
phi.setReceiver(var); phi.setReceiver(var);
} }
for (TryCatchJoint joint : synthesizedJoints.get(index)) { for (TryCatchJoint joint : synthesizedJoints.get(index)) {
Variable var = program.createVariable(); Variable var = program.createVariable();
var.getDebugNames().addAll(joint.getReceiver().getDebugNames()); var.getDebugNames().addAll(joint.getReceiver().getDebugNames());
mapVariable(joint.getReceiver().getIndex(), var); variableMap[joint.getReceiver().getIndex()] = var;
joint.setReceiver(var); joint.setReceiver(var);
} }
for (Phi phi : currentBlock.getPhis()) { for (Phi phi : currentBlock.getPhis()) {
@ -204,11 +195,15 @@ public class PhiUpdater {
insn.acceptVisitor(consumer); insn.acceptVisitor(consumer);
} }
Map<BasicBlock, Map<Variable, Variable>> tryCatchVariableMap = new HashMap<>();
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) { for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
Map<Variable, Variable> catchVariableMap = new HashMap<>();
tryCatchVariableMap.put(tryCatch.getHandler(), catchVariableMap);
Variable var = tryCatch.getExceptionVariable(); Variable var = tryCatch.getExceptionVariable();
if (var != null) { if (var != null) {
Variable newVar = introduce(var, true); Variable newVar = introduce(var);
tryCatch.setExceptionVariable(newVar); tryCatch.setExceptionVariable(newVar);
catchVariableMap.put(var, newVar);
} }
} }
@ -227,15 +222,28 @@ public class PhiUpdater {
Task next = new Task(); Task next = new Task();
next.variables = Arrays.copyOf(variableMap, variableMap.length); next.variables = Arrays.copyOf(variableMap, variableMap.length);
next.block = program.basicBlockAt(successor); next.block = program.basicBlockAt(successor);
Map<Variable, Variable> catchVariableMap = tryCatchVariableMap.get(next.block);
if (catchVariableMap != null) {
for (Map.Entry<Variable, Variable> entry : catchVariableMap.entrySet()) {
next.variables[entry.getKey().getIndex()] = entry.getValue();
}
}
stack[head++] = next; stack[head++] = next;
} }
successors = cfg.outgoingEdges(index); successors = cfg.outgoingEdges(index);
for (int successor : successors) { for (int successor : successors) {
int[] phiIndexes = phiIndexMap[successor]; int[] phiIndexes = phiIndexMap[successor];
List<Phi> phis = synthesizedPhis.get(successor); List<Phi> phis = synthesizedPhis.get(successor);
Map<Variable, Variable> catchVariableMap = tryCatchVariableMap.get(program.basicBlockAt(successor));
for (int j = 0; j < phis.size(); ++j) { for (int j = 0; j < phis.size(); ++j) {
Phi phi = phis.get(j); Phi phi = phis.get(j);
Variable var = variableMap[phiIndexes[j]]; Variable var = null;
if (catchVariableMap != null) {
var = catchVariableMap.get(program.variableAt(phiIndexes[j]));
}
if (var == null) {
var = variableMap[phiIndexes[j]];
}
if (var != null) { if (var != null) {
Incoming incoming = new Incoming(); Incoming incoming = new Incoming();
incoming.setSource(currentBlock); incoming.setSource(currentBlock);
@ -262,6 +270,9 @@ public class PhiUpdater {
} }
private void markAssignment(Variable var) { private void markAssignment(Variable var) {
boolean fromHandler = currentBlock.getTryCatchBlocks().stream().anyMatch(
tryCatch -> tryCatch.getExceptionVariable() == var);
BasicBlock[] worklist = new BasicBlock[program.basicBlockCount() * 4]; BasicBlock[] worklist = new BasicBlock[program.basicBlockCount() * 4];
int head = 0; int head = 0;
worklist[head++] = currentBlock; worklist[head++] = currentBlock;
@ -271,9 +282,10 @@ public class PhiUpdater {
if (frontiers == null) { if (frontiers == null) {
continue; continue;
} }
for (int frontier : frontiers) { for (int frontier : frontiers) {
BasicBlock frontierBlock = program.basicBlockAt(frontier); BasicBlock frontierBlock = program.basicBlockAt(frontier);
if (isExceptionHandler(block, frontierBlock)) { if (!fromHandler && isExceptionHandler(block, frontierBlock)) {
continue; continue;
} }
@ -295,28 +307,30 @@ public class PhiUpdater {
} }
} }
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { if (!fromHandler) {
BasicBlock frontierBlock = tryCatch.getHandler(); for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
int frontier = frontierBlock.getIndex(); BasicBlock frontierBlock = tryCatch.getHandler();
boolean jointExists = frontierBlock.getTryCatchJoints().stream() int frontier = frontierBlock.getIndex();
.anyMatch(joint -> joint.getSourceVariables().contains(var) && joint.getSource() == block); boolean jointExists = frontierBlock.getTryCatchJoints().stream()
if (jointExists) { .anyMatch(joint -> joint.getSourceVariables().contains(var) && joint.getSource() == block);
continue; if (jointExists) {
} continue;
}
Map<Variable, TryCatchJoint> jointSubmap = jointMap.get(frontier).get(block); Map<Variable, TryCatchJoint> jointSubmap = jointMap.get(frontier).get(block);
if (jointSubmap == null) { if (jointSubmap == null) {
jointSubmap = new HashMap<>(); jointSubmap = new HashMap<>();
jointMap.get(frontier).put(block, jointSubmap); jointMap.get(frontier).put(block, jointSubmap);
} }
TryCatchJoint joint = jointSubmap.get(var); TryCatchJoint joint = jointSubmap.get(var);
if (joint == null) { if (joint == null) {
joint = new TryCatchJoint(); joint = new TryCatchJoint();
joint.setSource(block); joint.setSource(block);
joint.setReceiver(var); joint.setReceiver(var);
synthesizedJoints.get(frontier).add(joint); synthesizedJoints.get(frontier).add(joint);
jointSubmap.put(var, joint); jointSubmap.put(var, joint);
worklist[head++] = frontierBlock; worklist[head++] = frontierBlock;
}
} }
} }
} }
@ -327,34 +341,17 @@ public class PhiUpdater {
} }
private Variable define(Variable var) { private Variable define(Variable var) {
Variable original = var;
var = introduce(var, false);
mapVariable(original.getIndex(), var);
return var;
}
private void mapVariable(int index, Variable var) {
variableMap[index] = var;
while (variableToSourceMap.size() <= var.getIndex()) {
variableToSourceMap.add(-1);
}
variableToSourceMap.set(var.getIndex(), index);
}
private Variable introduce(Variable var, boolean clear) {
Variable original = var;
Variable old = variableMap[var.getIndex()]; Variable old = variableMap[var.getIndex()];
if (old == null) { if (old == null) {
old = var; old = var;
} }
Variable original = var;
if (!usedDefinitions[var.getIndex()]) { var = introduce(var);
usedDefinitions[var.getIndex()] = true;
} else {
var = program.createVariable();
}
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) { for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
if (tryCatch.getExceptionVariable() == original) {
continue;
}
Map<Variable, TryCatchJoint> joints = jointMap.get(tryCatch.getHandler().getIndex()).get(currentBlock); Map<Variable, TryCatchJoint> joints = jointMap.get(tryCatch.getHandler().getIndex()).get(currentBlock);
if (joints == null) { if (joints == null) {
continue; continue;
@ -364,14 +361,22 @@ public class PhiUpdater {
continue; continue;
} }
if (joint.getSourceVariables().isEmpty()) { if (joint.getSourceVariables().isEmpty()) {
joint.getSourceVariables().add(original); joint.getSourceVariables().add(old);
}
if (clear) {
joint.getSourceVariables().clear();
} }
joint.getSourceVariables().add(var); joint.getSourceVariables().add(var);
} }
variableMap[original.getIndex()] = var;
return var;
}
private Variable introduce(Variable var) {
if (!usedDefinitions[var.getIndex()]) {
usedDefinitions[var.getIndex()] = true;
} else {
var = program.createVariable();
}
return var; return var;
} }