mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Better fix for https://github.com/konsoletyper/teavm/issues/85
This commit is contained in:
parent
14dd352cb6
commit
79b805ba6c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user