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() {
return safePhis;
}
@ -257,13 +304,13 @@ public class BasicBlock implements BasicBlockReader {
}
public List<TryCatchJoint> getTryCatchJoints() {
return joints;
return safeJoints;
}
@Override
public List<TryCatchJointReader> readTryCatchJoints() {
if (immutableJoints == null) {
immutableJoints = Collections.unmodifiableList(joints);
immutableJoints = Collections.unmodifiableList(safeJoints);
}
return immutableJoints;
}

View File

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

View File

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

View File

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