mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 08:34:11 -08:00
Further work on incremental phi updater
This commit is contained in:
parent
fd7ff3d538
commit
85cbb4a75c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,4 +23,6 @@ public interface TryCatchJointReader {
|
||||||
VariableReader getReceiver();
|
VariableReader getReceiver();
|
||||||
|
|
||||||
BasicBlockReader getSource();
|
BasicBlockReader getSource();
|
||||||
|
|
||||||
|
BasicBlockReader getBlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,6 +307,7 @@ public class PhiUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fromHandler) {
|
||||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||||
BasicBlock frontierBlock = tryCatch.getHandler();
|
BasicBlock frontierBlock = tryCatch.getHandler();
|
||||||
int frontier = frontierBlock.getIndex();
|
int frontier = frontierBlock.getIndex();
|
||||||
|
@ -321,40 +334,24 @@ public class PhiUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isExceptionHandler(BasicBlock source, BasicBlock target) {
|
private boolean isExceptionHandler(BasicBlock source, BasicBlock target) {
|
||||||
return source.getTryCatchBlocks().stream().anyMatch(tryCatch -> tryCatch.getHandler() == target);
|
return source.getTryCatchBlocks().stream().anyMatch(tryCatch -> tryCatch.getHandler() == target);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user