mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 00:14:10 -08:00
Fix phi updater
This commit is contained in:
parent
85cbb4a75c
commit
7668ef66fb
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user