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

View File

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

View File

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

View File

@ -20,7 +20,12 @@ import org.teavm.common.Graph;
import org.teavm.common.GraphUtils; import org.teavm.common.GraphUtils;
import org.teavm.common.IntegerStack; import org.teavm.common.IntegerStack;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.instructions.AbstractInstructionVisitor;
import org.teavm.model.instructions.ClassConstantInstruction; 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.instructions.StringConstantInstruction;
import org.teavm.model.util.DefinitionExtractor; import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.ProgramUtils; import org.teavm.model.util.ProgramUtils;
@ -54,6 +59,7 @@ class ReadWriteStatsBuilder {
UsageExtractor useExtractor = new UsageExtractor(); UsageExtractor useExtractor = new UsageExtractor();
IntegerStack stack = new IntegerStack(program.basicBlockCount()); IntegerStack stack = new IntegerStack(program.basicBlockCount());
stack.push(0); stack.push(0);
ConstantExtractor constantExtractor = new ConstantExtractor(constants);
while (!stack.isEmpty()) { while (!stack.isEmpty()) {
int node = stack.pop(); int node = stack.pop();
BasicBlock block = program.basicBlockAt(node); BasicBlock block = program.basicBlockAt(node);
@ -73,13 +79,7 @@ class ReadWriteStatsBuilder {
reads[var.getIndex()]++; reads[var.getIndex()]++;
} }
if (insn instanceof StringConstantInstruction) { insn.acceptVisitor(constantExtractor);
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();
}
} }
for (Phi phi : block.getPhis()) { 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); ClassHierarchy hierarchy = new ClassHierarchy(classes);
TagRegistry tagRegistry = new TagRegistry(classes, hierarchy); 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()); Characteristics characteristics = new Characteristics(controller.getUnprocessedClassSource());
NameProvider nameProvider = new NameProvider(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); Set<MethodReference> splitMethods = new HashSet<>(asyncMethods);
splitMethods.addAll(asyncFamilyMethods); 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<>(); List<PreparedClass> classNodes = new ArrayList<>();
for (String className : getClassOrdering(classes)) { for (String className : getClassOrdering(classes)) {

View File

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