From 79b805ba6cff2a3bfb442b51d5a910000b55a5e6 Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Thu, 12 Mar 2015 21:20:36 +0300 Subject: [PATCH] Better fix for https://github.com/konsoletyper/teavm/issues/85 --- .../java/org/teavm/javascript/Optimizer.java | 23 +++++++++++++--- .../teavm/javascript/OptimizingVisitor.java | 12 +++++---- .../javascript/ReadWriteStatsBuilder.java | 26 ++++++++++++++++--- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java b/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java index 4c7e18804..fce043a1f 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java @@ -29,7 +29,13 @@ public class Optimizer { public void optimize(RegularMethodNode method, Program program) { ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); 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.setBody(optimizer.resultStmt); int paramCount = method.getReference().parameterCount(); @@ -44,12 +50,21 @@ public class Optimizer { } 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) { + ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); 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()) { - OptimizingVisitor optimizer = new OptimizingVisitor(stats.copy()); + for (int i = 0; i < splitter.size(); ++i) { + AsyncMethodPart part = method.getBody().get(i); + OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, readFrequencies[i]); part.getStatement().acceptVisitor(optimizer); part.setStatement(optimizer.resultStmt); } diff --git a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java index 718c86bbc..c0923f820 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java @@ -25,11 +25,13 @@ import org.teavm.javascript.ast.*; class OptimizingVisitor implements StatementVisitor, ExprVisitor { public Expr resultExpr; public Statement resultStmt; - private ReadWriteStatsBuilder stats; + private boolean[] preservedVars; + private int[] readFrequencies; private List resultSequence; - public OptimizingVisitor(ReadWriteStatsBuilder stats) { - this.stats = stats; + public OptimizingVisitor(boolean[] preservedVars, int[] readFreqencies) { + this.preservedVars = preservedVars; + this.readFrequencies = readFreqencies; } private static boolean isZero(Expr expr) { @@ -121,7 +123,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { public void visit(VariableExpr expr) { int index = expr.getIndex(); resultExpr = expr; - if (stats.reads[index] != 1 || stats.writes[index] != 1) { + if (readFrequencies[index] != 1 || preservedVars[index]) { return; } if (resultSequence.isEmpty()) { @@ -217,7 +219,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { InvocationExpr constructrExpr = Expr.constructObject(expr.getMethod(), args); constructrExpr.setLocation(expr.getLocation()); assignment.setRightValue(constructrExpr); - stats.reads[var.getIndex()]--; + readFrequencies[var.getIndex()]--; return true; } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java b/teavm-core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java index 0e39dd41c..9b02c1e99 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java @@ -16,8 +16,12 @@ package org.teavm.javascript; 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.util.DefinitionExtractor; +import org.teavm.model.util.ProgramUtils; import org.teavm.model.util.UsageExtractor; /** @@ -27,6 +31,7 @@ import org.teavm.model.util.UsageExtractor; class ReadWriteStatsBuilder { public int[] reads; public int[] writes; + public boolean[] readUninitialized; private ReadWriteStatsBuilder() { } @@ -34,6 +39,7 @@ class ReadWriteStatsBuilder { public ReadWriteStatsBuilder(int variableCount) { reads = new int[variableCount]; writes = new int[variableCount]; + readUninitialized = new boolean[variableCount]; } public ReadWriteStatsBuilder copy() { @@ -44,10 +50,15 @@ class ReadWriteStatsBuilder { } public void analyze(Program program) { + Graph cfg = ProgramUtils.buildControlFlowGraph(program); + Graph dom = GraphUtils.buildDominatorGraph(GraphUtils.buildDominatorTree(cfg), cfg.size()); DefinitionExtractor defExtractor = new DefinitionExtractor(); UsageExtractor useExtractor = new UsageExtractor(); - for (int i = 0; i < program.basicBlockCount(); ++i) { - BasicBlock block = program.basicBlockAt(i); + IntegerStack stack = new IntegerStack(program.basicBlockCount()); + stack.push(0); + while (!stack.isEmpty()) { + int node = stack.pop(); + BasicBlock block = program.basicBlockAt(node); for (Instruction insn : block.getInstructions()) { insn.acceptVisitor(defExtractor); insn.acceptVisitor(useExtractor); @@ -56,18 +67,27 @@ class ReadWriteStatsBuilder { } for (Variable var : useExtractor.getUsedVariables()) { reads[var.getIndex()]++; + if (writes[var.getIndex()] == 0) { + readUninitialized[var.getIndex()] = true; + } } } for (Phi phi : block.getPhis()) { writes[phi.getReceiver().getIndex()] += phi.getIncomings().size(); for (Incoming incoming : phi.getIncomings()) { - reads[incoming.getValue().getIndex()]++; + if (writes[incoming.getValue().getIndex()] == 0) { + reads[incoming.getValue().getIndex()]++; + } } } for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { writes[tryCatch.getExceptionVariable().getIndex()]++; reads[tryCatch.getExceptionVariable().getIndex()]++; } + + for (int succ : dom.outgoingEdges(node)) { + stack.push(succ); + } } } }