Always eliminate constant variables in AST optimizer

This commit is contained in:
Alexey Andreev 2019-06-28 22:23:50 +03:00
parent 5593a2c557
commit 973cdf045b
7 changed files with 57 additions and 28 deletions

View File

@ -74,14 +74,11 @@ public class Decompiler {
private Deque<Block> stack;
private Program program;
private boolean friendlyToDebugger;
private boolean moveConstants;
public Decompiler(ClassHolderSource classSource, Set<MethodReference> splitMethods, boolean friendlyToDebugger,
boolean moveConstants) {
public Decompiler(ClassHolderSource classSource, Set<MethodReference> splitMethods, boolean friendlyToDebugger) {
this.classSource = classSource;
this.splitMethods = splitMethods;
this.friendlyToDebugger = friendlyToDebugger;
this.moveConstants = moveConstants;
}
static class Block {
@ -152,7 +149,7 @@ public class Decompiler {
methodNode.getVariables().add(variable);
}
Optimizer optimizer = new Optimizer(moveConstants);
Optimizer optimizer = new Optimizer();
optimizer.optimize(methodNode, method.getProgram(), friendlyToDebugger);
methodNode.getModifiers().addAll(method.getModifiers());
@ -185,7 +182,7 @@ public class Decompiler {
node.getVariables().add(variable);
}
Optimizer optimizer = new Optimizer(moveConstants);
Optimizer optimizer = new Optimizer();
optimizer.optimize(node, splitter, friendlyToDebugger);
node.getModifiers().addAll(method.getModifiers());

View File

@ -32,12 +32,6 @@ import org.teavm.model.util.ProgramUtils;
import org.teavm.model.util.UsageExtractor;
public class Optimizer {
private boolean moveConstants;
public Optimizer(boolean moveConstants) {
this.moveConstants = moveConstants;
}
public void optimize(RegularMethodNode method, Program program, boolean friendlyToDebugger) {
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
stats.analyze(program);
@ -54,7 +48,7 @@ public class Optimizer {
}
}
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads,
moveConstants ? stats.constants : new Object[stats.constants.length], friendlyToDebugger);
stats.constants, friendlyToDebugger);
method.getBody().acceptVisitor(optimizer);
method.setBody(optimizer.resultStmt);
int paramCount = method.getReference().parameterCount();
@ -89,7 +83,7 @@ public class Optimizer {
breakEliminator.eliminate(part.getStatement());
findEscapingLiveVars(liveness, cfg, splitter, i, preservedVars);
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads,
moveConstants ? stats.constants : new Object[stats.constants.length], friendlyToDebugger);
stats.constants, friendlyToDebugger);
part.getStatement().acceptVisitor(optimizer);
part.setStatement(optimizer.resultStmt);
}

View File

@ -69,7 +69,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
Statement resultStmt;
private final boolean[] preservedVars;
private final int[] writeFrequencies;
private final int[] initialWriteFrequences;
private final int[] initialWriteFrequencies;
private final int[] readFrequencies;
private final Object[] constants;
private List<Statement> resultSequence;
@ -82,7 +82,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
boolean friendlyToDebugger) {
this.preservedVars = preservedVars;
this.writeFrequencies = writeFrequencies;
this.initialWriteFrequences = writeFrequencies.clone();
this.initialWriteFrequencies = writeFrequencies.clone();
this.readFrequencies = readFrequencies;
this.constants = constants;
this.friendlyToDebugger = friendlyToDebugger;
@ -279,7 +279,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
return;
}
if (!preservedVars[index] && initialWriteFrequences[index] == 1 && constants[index] != null) {
if (!preservedVars[index] && initialWriteFrequencies[index] == 1 && constants[index] != null) {
ConstantExpr constantExpr = new ConstantExpr();
constantExpr.setValue(constants[index]);
constantExpr.setLocation(expr.getLocation());
@ -561,7 +561,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
left = resultExpr;
} else {
int varIndex = ((VariableExpr) statement.getLeftValue()).getIndex();
if (!preservedVars[varIndex] && initialWriteFrequences[varIndex] == 1
if (!preservedVars[varIndex] && initialWriteFrequencies[varIndex] == 1
&& constants[varIndex] != null) {
resultStmt = new SequentialStatement();
return;

View File

@ -20,7 +20,12 @@ import org.teavm.common.Graph;
import org.teavm.common.GraphUtils;
import org.teavm.common.IntegerStack;
import org.teavm.model.*;
import org.teavm.model.instructions.AbstractInstructionVisitor;
import org.teavm.model.instructions.ClassConstantInstruction;
import org.teavm.model.instructions.DoubleConstantInstruction;
import org.teavm.model.instructions.FloatConstantInstruction;
import org.teavm.model.instructions.IntegerConstantInstruction;
import org.teavm.model.instructions.LongConstantInstruction;
import org.teavm.model.instructions.StringConstantInstruction;
import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.ProgramUtils;
@ -54,6 +59,7 @@ class ReadWriteStatsBuilder {
UsageExtractor useExtractor = new UsageExtractor();
IntegerStack stack = new IntegerStack(program.basicBlockCount());
stack.push(0);
ConstantExtractor constantExtractor = new ConstantExtractor(constants);
while (!stack.isEmpty()) {
int node = stack.pop();
BasicBlock block = program.basicBlockAt(node);
@ -73,13 +79,7 @@ class ReadWriteStatsBuilder {
reads[var.getIndex()]++;
}
if (insn instanceof StringConstantInstruction) {
StringConstantInstruction stringConstant = (StringConstantInstruction) insn;
constants[stringConstant.getReceiver().getIndex()] = stringConstant.getConstant();
} else if (insn instanceof ClassConstantInstruction) {
ClassConstantInstruction classConstant = (ClassConstantInstruction) insn;
constants[classConstant.getReceiver().getIndex()] = classConstant.getConstant();
}
insn.acceptVisitor(constantExtractor);
}
for (Phi phi : block.getPhis()) {
@ -96,4 +96,42 @@ class ReadWriteStatsBuilder {
}
}
}
static class ConstantExtractor extends AbstractInstructionVisitor {
private Object[] constants;
public ConstantExtractor(Object[] constants) {
this.constants = constants;
}
@Override
public void visit(ClassConstantInstruction insn) {
constants[insn.getReceiver().getIndex()] = insn.getConstant();
}
@Override
public void visit(StringConstantInstruction insn) {
constants[insn.getReceiver().getIndex()] = insn.getConstant();
}
@Override
public void visit(IntegerConstantInstruction insn) {
constants[insn.getReceiver().getIndex()] = insn.getConstant();
}
@Override
public void visit(LongConstantInstruction insn) {
constants[insn.getReceiver().getIndex()] = insn.getConstant();
}
@Override
public void visit(FloatConstantInstruction insn) {
constants[insn.getReceiver().getIndex()] = insn.getConstant();
}
@Override
public void visit(DoubleConstantInstruction insn) {
constants[insn.getReceiver().getIndex()] = insn.getConstant();
}
}
}

View File

@ -317,7 +317,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
ClassHierarchy hierarchy = new ClassHierarchy(classes);
TagRegistry tagRegistry = new TagRegistry(classes, hierarchy);
Decompiler decompiler = new Decompiler(classes, new HashSet<>(), false, true);
Decompiler decompiler = new Decompiler(classes, new HashSet<>(), controller.isFriendlyToDebugger());
Characteristics characteristics = new Characteristics(controller.getUnprocessedClassSource());
NameProvider nameProvider = new NameProvider(controller.getUnprocessedClassSource());

View File

@ -477,7 +477,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
Set<MethodReference> splitMethods = new HashSet<>(asyncMethods);
splitMethods.addAll(asyncFamilyMethods);
Decompiler decompiler = new Decompiler(classes, splitMethods, controller.isFriendlyToDebugger(), false);
Decompiler decompiler = new Decompiler(classes, splitMethods, controller.isFriendlyToDebugger());
List<PreparedClass> classNodes = new ArrayList<>();
for (String className : getClassOrdering(classes)) {

View File

@ -331,7 +331,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
WasmClassGenerator classGenerator = new WasmClassGenerator(classes, controller.getUnprocessedClassSource(),
vtableProvider, tagRegistry, binaryWriter, names);
Decompiler decompiler = new Decompiler(classes, new HashSet<>(), false, true);
Decompiler decompiler = new Decompiler(classes, new HashSet<>(), false);
WasmStringPool stringPool = classGenerator.getStringPool();
WasmGenerationContext context = new WasmGenerationContext(classes, module, controller.getDiagnostics(),
vtableProvider, tagRegistry, stringPool, names);