This commit is contained in:
konsoletyper 2015-03-12 21:20:36 +03:00
parent 14dd352cb6
commit 79b805ba6c
3 changed files with 49 additions and 12 deletions

View File

@ -29,7 +29,13 @@ public class Optimizer {
public void optimize(RegularMethodNode method, Program program) { public void optimize(RegularMethodNode method, Program program) {
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
stats.analyze(program); stats.analyze(program);
OptimizingVisitor optimizer = new OptimizingVisitor(stats); boolean[] preservedVars = new boolean[stats.writes.length];
for (int i = 0; i < preservedVars.length; ++i) {
if (stats.writes[i] != 1) {
preservedVars[i] = true;
}
}
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.reads);
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();
@ -44,12 +50,21 @@ public class Optimizer {
} }
public void optimize(AsyncMethodNode method, AsyncProgramSplitter splitter) { public void optimize(AsyncMethodNode method, AsyncProgramSplitter splitter) {
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); boolean[] preservedVars = new boolean[method.getVariables().size()];
int[][] readFrequencies = new int[splitter.size()][];
for (int i = 0; i < splitter.size(); ++i) { for (int i = 0; i < splitter.size(); ++i) {
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
stats.analyze(splitter.getProgram(i)); stats.analyze(splitter.getProgram(i));
readFrequencies[i] = stats.reads;
for (int j = 0; j < stats.writes.length; ++j) {
if (stats.readUninitialized[j] || stats.writes[j] != 1 && stats.reads[j] > 0) {
preservedVars[j] = true;
}
}
} }
for (AsyncMethodPart part : method.getBody()) { for (int i = 0; i < splitter.size(); ++i) {
OptimizingVisitor optimizer = new OptimizingVisitor(stats.copy()); AsyncMethodPart part = method.getBody().get(i);
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, readFrequencies[i]);
part.getStatement().acceptVisitor(optimizer); part.getStatement().acceptVisitor(optimizer);
part.setStatement(optimizer.resultStmt); part.setStatement(optimizer.resultStmt);
} }

View File

@ -25,11 +25,13 @@ import org.teavm.javascript.ast.*;
class OptimizingVisitor implements StatementVisitor, ExprVisitor { class OptimizingVisitor implements StatementVisitor, ExprVisitor {
public Expr resultExpr; public Expr resultExpr;
public Statement resultStmt; public Statement resultStmt;
private ReadWriteStatsBuilder stats; private boolean[] preservedVars;
private int[] readFrequencies;
private List<Statement> resultSequence; private List<Statement> resultSequence;
public OptimizingVisitor(ReadWriteStatsBuilder stats) { public OptimizingVisitor(boolean[] preservedVars, int[] readFreqencies) {
this.stats = stats; this.preservedVars = preservedVars;
this.readFrequencies = readFreqencies;
} }
private static boolean isZero(Expr expr) { private static boolean isZero(Expr expr) {
@ -121,7 +123,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
public void visit(VariableExpr expr) { public void visit(VariableExpr expr) {
int index = expr.getIndex(); int index = expr.getIndex();
resultExpr = expr; resultExpr = expr;
if (stats.reads[index] != 1 || stats.writes[index] != 1) { if (readFrequencies[index] != 1 || preservedVars[index]) {
return; return;
} }
if (resultSequence.isEmpty()) { if (resultSequence.isEmpty()) {
@ -217,7 +219,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
InvocationExpr constructrExpr = Expr.constructObject(expr.getMethod(), args); InvocationExpr constructrExpr = Expr.constructObject(expr.getMethod(), args);
constructrExpr.setLocation(expr.getLocation()); constructrExpr.setLocation(expr.getLocation());
assignment.setRightValue(constructrExpr); assignment.setRightValue(constructrExpr);
stats.reads[var.getIndex()]--; readFrequencies[var.getIndex()]--;
return true; return true;
} }

View File

@ -16,8 +16,12 @@
package org.teavm.javascript; package org.teavm.javascript;
import java.util.Arrays; import java.util.Arrays;
import org.teavm.common.Graph;
import org.teavm.common.GraphUtils;
import org.teavm.common.IntegerStack;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.util.DefinitionExtractor; import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.ProgramUtils;
import org.teavm.model.util.UsageExtractor; import org.teavm.model.util.UsageExtractor;
/** /**
@ -27,6 +31,7 @@ import org.teavm.model.util.UsageExtractor;
class ReadWriteStatsBuilder { class ReadWriteStatsBuilder {
public int[] reads; public int[] reads;
public int[] writes; public int[] writes;
public boolean[] readUninitialized;
private ReadWriteStatsBuilder() { private ReadWriteStatsBuilder() {
} }
@ -34,6 +39,7 @@ class ReadWriteStatsBuilder {
public ReadWriteStatsBuilder(int variableCount) { public ReadWriteStatsBuilder(int variableCount) {
reads = new int[variableCount]; reads = new int[variableCount];
writes = new int[variableCount]; writes = new int[variableCount];
readUninitialized = new boolean[variableCount];
} }
public ReadWriteStatsBuilder copy() { public ReadWriteStatsBuilder copy() {
@ -44,10 +50,15 @@ class ReadWriteStatsBuilder {
} }
public void analyze(Program program) { public void analyze(Program program) {
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
Graph dom = GraphUtils.buildDominatorGraph(GraphUtils.buildDominatorTree(cfg), cfg.size());
DefinitionExtractor defExtractor = new DefinitionExtractor(); DefinitionExtractor defExtractor = new DefinitionExtractor();
UsageExtractor useExtractor = new UsageExtractor(); UsageExtractor useExtractor = new UsageExtractor();
for (int i = 0; i < program.basicBlockCount(); ++i) { IntegerStack stack = new IntegerStack(program.basicBlockCount());
BasicBlock block = program.basicBlockAt(i); stack.push(0);
while (!stack.isEmpty()) {
int node = stack.pop();
BasicBlock block = program.basicBlockAt(node);
for (Instruction insn : block.getInstructions()) { for (Instruction insn : block.getInstructions()) {
insn.acceptVisitor(defExtractor); insn.acceptVisitor(defExtractor);
insn.acceptVisitor(useExtractor); insn.acceptVisitor(useExtractor);
@ -56,18 +67,27 @@ class ReadWriteStatsBuilder {
} }
for (Variable var : useExtractor.getUsedVariables()) { for (Variable var : useExtractor.getUsedVariables()) {
reads[var.getIndex()]++; reads[var.getIndex()]++;
if (writes[var.getIndex()] == 0) {
readUninitialized[var.getIndex()] = true;
}
} }
} }
for (Phi phi : block.getPhis()) { for (Phi phi : block.getPhis()) {
writes[phi.getReceiver().getIndex()] += phi.getIncomings().size(); writes[phi.getReceiver().getIndex()] += phi.getIncomings().size();
for (Incoming incoming : phi.getIncomings()) { for (Incoming incoming : phi.getIncomings()) {
reads[incoming.getValue().getIndex()]++; if (writes[incoming.getValue().getIndex()] == 0) {
reads[incoming.getValue().getIndex()]++;
}
} }
} }
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
writes[tryCatch.getExceptionVariable().getIndex()]++; writes[tryCatch.getExceptionVariable().getIndex()]++;
reads[tryCatch.getExceptionVariable().getIndex()]++; reads[tryCatch.getExceptionVariable().getIndex()]++;
} }
for (int succ : dom.outgoingEdges(node)) {
stack.push(succ);
}
} }
} }
} }