Fix phi updater

This commit is contained in:
Alexey Andreev 2016-06-11 20:47:24 +03:00 committed by Alexey Andreev
parent 85cbb4a75c
commit 7668ef66fb
3 changed files with 77 additions and 13 deletions

View File

@ -49,7 +49,7 @@ public class ListingBuilder {
} }
for (TryCatchJointReader joint : block.readTryCatchJoints()) { for (TryCatchJointReader joint : block.readTryCatchJoints()) {
sb.append(" @").append(joint.getReceiver().getIndex()).append(" := e-phi("); sb.append(" @").append(joint.getReceiver().getIndex()).append(" := e-phi(");
sb.append(joint.readSourceVariables().stream().map(sourceVar -> "@" + sourceVar.getIndex()) sb.append(joint.readSourceVariables().stream().map(sourceVar -> "@" + sourceVar.getIndex())
.collect(Collectors.joining(", "))); .collect(Collectors.joining(", ")));
sb.append(") from $").append(joint.getSource().getIndex()).append("\n"); sb.append(") from $").append(joint.getSource().getIndex()).append("\n");

View File

@ -15,8 +15,13 @@
*/ */
package org.teavm.model.util; package org.teavm.model.util;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -24,9 +29,12 @@ 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.model.BasicBlock; import org.teavm.model.BasicBlock;
import org.teavm.model.ClassHolder;
import org.teavm.model.Incoming; import org.teavm.model.Incoming;
import org.teavm.model.Instruction; import org.teavm.model.Instruction;
import org.teavm.model.InvokeDynamicInstruction; import org.teavm.model.InvokeDynamicInstruction;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodHolder;
import org.teavm.model.Phi; import org.teavm.model.Phi;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.TryCatchBlock; import org.teavm.model.TryCatchBlock;
@ -69,6 +77,7 @@ import org.teavm.model.instructions.RaiseInstruction;
import org.teavm.model.instructions.StringConstantInstruction; import org.teavm.model.instructions.StringConstantInstruction;
import org.teavm.model.instructions.SwitchInstruction; import org.teavm.model.instructions.SwitchInstruction;
import org.teavm.model.instructions.UnwrapArrayInstruction; import org.teavm.model.instructions.UnwrapArrayInstruction;
import org.teavm.parsing.ClasspathClassHolderSource;
public class PhiUpdater { public class PhiUpdater {
private Program program; private Program program;
@ -175,6 +184,7 @@ 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());
propagateToTryCatch(phi.getReceiver(), var, null);
variableMap[phi.getReceiver().getIndex()] = var; variableMap[phi.getReceiver().getIndex()] = var;
phi.setReceiver(var); phi.setReceiver(var);
} }
@ -208,12 +218,19 @@ public class PhiUpdater {
} }
for (Incoming output : phiOutputs.get(index)) { for (Incoming output : phiOutputs.get(index)) {
output.setValue(use(output.getValue())); Variable var = output.getValue();
Variable exceptionVar = tryCatchVariableMap
.getOrDefault(output.getPhi().getBasicBlock(), Collections.emptyMap())
.get(var);
output.setValue(exceptionVar != null ? exceptionVar : use(var));
} }
for (TryCatchJoint joint : existingOutputJoints.get(index)) { for (TryCatchJoint joint : existingOutputJoints.get(index)) {
for (int i = 0; i < joint.getSourceVariables().size(); ++i) { for (int i = 0; i < joint.getSourceVariables().size(); ++i) {
Variable var = joint.getSourceVariables().get(i); Variable var = joint.getSourceVariables().get(i);
joint.getSourceVariables().set(i, use(var)); Variable exceptionVar = tryCatchVariableMap
.getOrDefault(joint.getBlock(), Collections.emptyMap())
.get(var);
joint.getSourceVariables().set(i, exceptionVar != null ? exceptionVar : use(var));
} }
} }
@ -309,11 +326,14 @@ public class PhiUpdater {
if (!fromHandler) { if (!fromHandler) {
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
if (tryCatch.getExceptionVariable() == var || !hasReassignmentTo(block, var)) {
continue;
}
BasicBlock frontierBlock = tryCatch.getHandler(); BasicBlock frontierBlock = tryCatch.getHandler();
int frontier = frontierBlock.getIndex(); int frontier = frontierBlock.getIndex();
boolean jointExists = frontierBlock.getTryCatchJoints().stream() boolean exists = frontierBlock.getTryCatchJoints().stream()
.anyMatch(joint -> joint.getSourceVariables().contains(var) && joint.getSource() == block); .anyMatch(joint -> joint.getSourceVariables().contains(var) && joint.getSource() == block);
if (jointExists) { if (exists) {
continue; continue;
} }
@ -336,18 +356,33 @@ public class PhiUpdater {
} }
} }
private boolean hasReassignmentTo(BasicBlock block, Variable var) {
DefinitionExtractor defExtractor = new DefinitionExtractor();
for (int i = 0; i < block.instructionCount(); ++i) {
block.getInstructions().get(i).acceptVisitor(defExtractor);
for (Variable definedVar : defExtractor.getDefinedVariables()) {
if (definedVar == var) {
return true;
}
}
}
return false;
}
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 old = variableMap[var.getIndex()]; Variable old = variableMap[var.getIndex()];
if (old == null) {
old = var;
}
Variable original = var; Variable original = var;
var = introduce(var); var = introduce(var);
propagateToTryCatch(original, var, old);
variableMap[original.getIndex()] = var;
return var;
}
private void propagateToTryCatch(Variable original, Variable var, Variable old) {
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) { for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
if (tryCatch.getExceptionVariable() == original) { if (tryCatch.getExceptionVariable() == original) {
continue; continue;
@ -360,14 +395,11 @@ public class PhiUpdater {
if (joint == null) { if (joint == null) {
continue; continue;
} }
if (joint.getSourceVariables().isEmpty()) { if (joint.getSourceVariables().isEmpty() && old != null) {
joint.getSourceVariables().add(old); joint.getSourceVariables().add(old);
} }
joint.getSourceVariables().add(var); joint.getSourceVariables().add(var);
} }
variableMap[original.getIndex()] = var;
return var;
} }
private Variable introduce(Variable var) { private Variable introduce(Variable var) {
@ -619,4 +651,35 @@ public class PhiUpdater {
insn.setObjectRef(use(insn.getObjectRef())); insn.setObjectRef(use(insn.getObjectRef()));
} }
}; };
public static void main(String[] args) {
ClasspathClassHolderSource classSource = new ClasspathClassHolderSource();
ClassHolder cls = classSource.get(CharsetDecoder.class.getName());
MethodHolder method = cls.getMethod(new MethodDescriptor("decode", ByteBuffer.class, CharBuffer.class,
boolean.class, CoderResult.class));
Program program = method.getProgram();
System.out.println(new ListingBuilder().buildListing(program, ""));
Variable[] arguments = new Variable[method.parameterCount() + 1];
for (int i = 0; i <= method.parameterCount(); ++i) {
arguments[i] = program.variableAt(i);
}
new PhiUpdater().updatePhis(program, arguments);
System.out.println("After:");
System.out.println(new ListingBuilder().buildListing(program, ""));
}
private static void test() {
int a = 0;
try {
int x = Math.random() > 0.5 ? 50 : -50;
System.out.println("Foo " + x);
} catch (RuntimeException e) {
System.out.println("Foo " + a);
a = 23;
}
System.out.println("bar " + a);
}
} }

View File

@ -95,6 +95,7 @@ import org.teavm.optimization.ArrayUnwrapMotion;
import org.teavm.optimization.Devirtualization; import org.teavm.optimization.Devirtualization;
import org.teavm.optimization.GlobalValueNumbering; import org.teavm.optimization.GlobalValueNumbering;
import org.teavm.optimization.LoopInvariantMotion; import org.teavm.optimization.LoopInvariantMotion;
import org.teavm.optimization.LoopInversion;
import org.teavm.optimization.MethodOptimization; import org.teavm.optimization.MethodOptimization;
import org.teavm.optimization.UnusedVariableElimination; import org.teavm.optimization.UnusedVariableElimination;
import org.teavm.vm.spi.RendererListener; import org.teavm.vm.spi.RendererListener;
@ -712,7 +713,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
} }
private List<MethodOptimization> getOptimizations() { private List<MethodOptimization> getOptimizations() {
return Arrays.asList(new ArrayUnwrapMotion(), /*new LoopInversion(),*/ new LoopInvariantMotion(), return Arrays.asList(new ArrayUnwrapMotion(), new LoopInversion(), new LoopInvariantMotion(),
new GlobalValueNumbering(), new UnusedVariableElimination()); new GlobalValueNumbering(), new UnusedVariableElimination());
} }