From 973cdf045bd7ce97e35c7d1132979a98f5eb6cdc Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 28 Jun 2019 22:23:50 +0300 Subject: [PATCH] Always eliminate constant variables in AST optimizer --- .../teavm/ast/decompilation/Decompiler.java | 9 ++-- .../org/teavm/ast/optimization/Optimizer.java | 10 +--- .../ast/optimization/OptimizingVisitor.java | 8 +-- .../optimization/ReadWriteStatsBuilder.java | 52 ++++++++++++++++--- .../java/org/teavm/backend/c/CTarget.java | 2 +- .../backend/javascript/JavaScriptTarget.java | 2 +- .../org/teavm/backend/wasm/WasmTarget.java | 2 +- 7 files changed, 57 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/org/teavm/ast/decompilation/Decompiler.java b/core/src/main/java/org/teavm/ast/decompilation/Decompiler.java index 35a484398..c719eb75a 100644 --- a/core/src/main/java/org/teavm/ast/decompilation/Decompiler.java +++ b/core/src/main/java/org/teavm/ast/decompilation/Decompiler.java @@ -74,14 +74,11 @@ public class Decompiler { private Deque stack; private Program program; private boolean friendlyToDebugger; - private boolean moveConstants; - public Decompiler(ClassHolderSource classSource, Set splitMethods, boolean friendlyToDebugger, - boolean moveConstants) { + public Decompiler(ClassHolderSource classSource, Set 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()); diff --git a/core/src/main/java/org/teavm/ast/optimization/Optimizer.java b/core/src/main/java/org/teavm/ast/optimization/Optimizer.java index 13d1e4c78..e68904e57 100644 --- a/core/src/main/java/org/teavm/ast/optimization/Optimizer.java +++ b/core/src/main/java/org/teavm/ast/optimization/Optimizer.java @@ -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); } diff --git a/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java b/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java index 25f892c17..be6959911 100644 --- a/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java +++ b/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java @@ -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 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; diff --git a/core/src/main/java/org/teavm/ast/optimization/ReadWriteStatsBuilder.java b/core/src/main/java/org/teavm/ast/optimization/ReadWriteStatsBuilder.java index 43a2cecfd..2b7414c7f 100644 --- a/core/src/main/java/org/teavm/ast/optimization/ReadWriteStatsBuilder.java +++ b/core/src/main/java/org/teavm/ast/optimization/ReadWriteStatsBuilder.java @@ -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(); + } + } } diff --git a/core/src/main/java/org/teavm/backend/c/CTarget.java b/core/src/main/java/org/teavm/backend/c/CTarget.java index 3716eeb72..80d0312bb 100644 --- a/core/src/main/java/org/teavm/backend/c/CTarget.java +++ b/core/src/main/java/org/teavm/backend/c/CTarget.java @@ -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()); diff --git a/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java b/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java index 0bf35c72c..3d4bd744f 100644 --- a/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java +++ b/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java @@ -477,7 +477,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost { Set 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 classNodes = new ArrayList<>(); for (String className : getClassOrdering(classes)) { diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java index ac7d12848..ec5d906b0 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java @@ -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);