From a32d6d037b19916b94d3e58ffac2e2bafb817248 Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Mon, 7 Jul 2014 17:35:30 +0400 Subject: [PATCH] Minor optimizations --- ...tor.java => CertainBlockCountVisitor.java} | 72 +++++++++--------- .../java/org/teavm/javascript/Optimizer.java | 3 - .../teavm/javascript/OptimizingVisitor.java | 18 +++-- .../teavm/optimization/ArrayUnwrapMotion.java | 73 +++++++++++++++++++ .../teavm/optimization/ClassSetOptimizer.java | 4 +- 5 files changed, 123 insertions(+), 47 deletions(-) rename teavm-core/src/main/java/org/teavm/javascript/{BlockRefCountVisitor.java => CertainBlockCountVisitor.java} (59%) create mode 100644 teavm-core/src/main/java/org/teavm/optimization/ArrayUnwrapMotion.java diff --git a/teavm-core/src/main/java/org/teavm/javascript/BlockRefCountVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/CertainBlockCountVisitor.java similarity index 59% rename from teavm-core/src/main/java/org/teavm/javascript/BlockRefCountVisitor.java rename to teavm-core/src/main/java/org/teavm/javascript/CertainBlockCountVisitor.java index 08f3f5467..89380765d 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/BlockRefCountVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/CertainBlockCountVisitor.java @@ -15,16 +15,33 @@ */ package org.teavm.javascript; -import java.util.HashMap; -import java.util.Map; +import java.util.List; import org.teavm.javascript.ast.*; /** * * @author Alexey Andreev */ -class BlockRefCountVisitor implements StatementVisitor { - Map refs = new HashMap<>(); +class CertainBlockCountVisitor implements StatementVisitor { + private BlockStatement blockToCount; + private int count; + + public CertainBlockCountVisitor(BlockStatement blockToCount) { + this.blockToCount = blockToCount; + } + + public int getCount() { + return count; + } + + public void visit(List statements) { + if (statements == null) { + return; + } + for (Statement part : statements) { + part.acceptVisitor(this); + } + } @Override public void visit(AssignmentStatement statement) { @@ -32,48 +49,31 @@ class BlockRefCountVisitor implements StatementVisitor { @Override public void visit(SequentialStatement statement) { - for (Statement part : statement.getSequence()) { - part.acceptVisitor(this); - } + visit(statement.getSequence()); } @Override public void visit(ConditionalStatement statement) { - for (Statement stmt : statement.getConsequent()) { - stmt.acceptVisitor(this); - } - for (Statement stmt : statement.getAlternative()) { - stmt.acceptVisitor(this); - } + visit(statement.getConsequent()); + visit(statement.getAlternative()); } @Override public void visit(SwitchStatement statement) { - refs.put(statement, 0); for (SwitchClause clause : statement.getClauses()) { - for (Statement part : clause.getBody()) { - part.acceptVisitor(this); - } - } - for (Statement part : statement.getDefaultClause()) { - part.acceptVisitor(this); + visit(clause.getBody()); } + visit(statement.getDefaultClause()); } @Override public void visit(WhileStatement statement) { - refs.put(statement, 0); - for (Statement part : statement.getBody()) { - part.acceptVisitor(this); - } + visit(statement.getBody()); } @Override public void visit(BlockStatement statement) { - refs.put(statement, 0); - for (Statement part : statement.getBody()) { - part.acceptVisitor(this); - } + visit(statement.getBody()); } @Override @@ -82,12 +82,16 @@ class BlockRefCountVisitor implements StatementVisitor { @Override public void visit(BreakStatement statement) { - refs.put(statement.getTarget(), refs.get(statement.getTarget()) + 1); + if (statement.getTarget() == blockToCount) { + ++count; + } } @Override public void visit(ContinueStatement statement) { - refs.put(statement.getTarget(), refs.get(statement.getTarget()) + 1); + if (statement.getTarget() == blockToCount) { + ++count; + } } @Override @@ -108,11 +112,7 @@ class BlockRefCountVisitor implements StatementVisitor { @Override public void visit(TryCatchStatement statement) { - for (Statement part : statement.getProtectedBody()) { - part.acceptVisitor(this); - } - for (Statement part : statement.getHandler()) { - part.acceptVisitor(this); - } + visit(statement.getProtectedBody()); + visit(statement.getHandler()); } } 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 f107401c2..c5174b0ea 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java @@ -27,10 +27,7 @@ public class Optimizer { public void optimize(RegularMethodNode method, Program program) { ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); stats.analyze(program); - BlockRefCountVisitor refsCounter = new BlockRefCountVisitor(); - method.getBody().acceptVisitor(refsCounter); OptimizingVisitor optimizer = new OptimizingVisitor(stats); - optimizer.referencedStatements = refsCounter.refs; method.getBody().acceptVisitor(optimizer); method.setBody(optimizer.resultStmt); int paramCount = method.getReference().parameterCount(); 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 77543beea..1e4624c67 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java @@ -26,7 +26,6 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { public Expr resultExpr; public Statement resultStmt; private ReadWriteStatsBuilder stats; - Map referencedStatements = new HashMap<>(); private List resultSequence; public OptimizingVisitor(ReadWriteStatsBuilder stats) { @@ -344,8 +343,6 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { if (last instanceof BreakStatement) { BreakStatement breakStmt = (BreakStatement)last; if (exit != null && exit == breakStmt.getTarget()) { - int refs = referencedStatements.get(breakStmt.getTarget()); - referencedStatements.put(breakStmt.getTarget(), refs - 1); cond.getConsequent().remove(cond.getConsequent().size() - 1); List remaining = statements.subList(i + 1, statements.size()); cond.getAlternative().addAll(remaining); @@ -358,8 +355,6 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { if (last instanceof BreakStatement) { BreakStatement breakStmt = (BreakStatement)last; if (exit != null && exit == breakStmt.getTarget()) { - int refs = referencedStatements.get(breakStmt.getTarget()); - referencedStatements.put(breakStmt.getTarget(), refs - 1); cond.getAlternative().remove(cond.getConsequent().size() - 1); List remaining = statements.subList(i + 1, statements.size()); cond.getConsequent().addAll(remaining); @@ -476,6 +471,15 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { statement.getBody().addAll(innerLoop.getBody()); } List statements = processSequence(statement.getBody()); + for (int i = 0; i < statements.size(); ++i) { + if (statements.get(i) instanceof ContinueStatement) { + ContinueStatement continueStmt = (ContinueStatement)statements.get(i); + if (continueStmt.getTarget() == statement) { + statements.subList(i, statements.size()).clear(); + break; + } + } + } statement.getBody().clear(); statement.getBody().addAll(statements); if (statement.getCondition() != null) { @@ -511,7 +515,9 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { public void visit(BlockStatement statement) { List statements = processSequence(statement.getBody()); eliminateRedundantBreaks(statements, statement); - if (referencedStatements.get(statement).equals(0)) { + CertainBlockCountVisitor usageCounter = new CertainBlockCountVisitor(statement); + usageCounter.visit(statements); + if (usageCounter.getCount() == 0) { SequentialStatement result = new SequentialStatement(); result.getSequence().addAll(statements); resultStmt = result; diff --git a/teavm-core/src/main/java/org/teavm/optimization/ArrayUnwrapMotion.java b/teavm-core/src/main/java/org/teavm/optimization/ArrayUnwrapMotion.java new file mode 100644 index 000000000..ed8b79a0f --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/optimization/ArrayUnwrapMotion.java @@ -0,0 +1,73 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.optimization; + +import java.util.ArrayList; +import java.util.List; +import org.teavm.model.*; +import org.teavm.model.instructions.EmptyInstruction; +import org.teavm.model.instructions.UnwrapArrayInstruction; +import org.teavm.model.util.DefinitionExtractor; + +/** + * + * @author Alexey Andreev + */ +public class ArrayUnwrapMotion implements MethodOptimization { + @Override + public void optimize(MethodReader method, Program program) { + for (int i = 0; i < program.basicBlockCount(); ++i) { + optimize(program.basicBlockAt(i)); + } + } + + private void optimize(BasicBlock block) { + List newInstructions = new ArrayList<>(); + List instructions = block.getInstructions(); + for (int i = 0; i < instructions.size(); ++i) { + Instruction insn = instructions.get(i); + if (insn instanceof UnwrapArrayInstruction) { + UnwrapArrayInstruction unwrap = (UnwrapArrayInstruction)insn; + instructions.set(i, new EmptyInstruction()); + int def = whereDefined(instructions, i, unwrap.getArray()); + if (def < 0) { + newInstructions.add(unwrap); + } else { + instructions.add(def + 1, unwrap); + ++i; + } + } + } + if (!newInstructions.isEmpty()) { + instructions.addAll(0, newInstructions); + } + } + + private int whereDefined(List instructions, int index, Variable var) { + DefinitionExtractor def = new DefinitionExtractor(); + while (index >= 0) { + Instruction insn = instructions.get(index); + insn.acceptVisitor(def); + for (Variable defVar : def.getDefinedVariables()) { + if (defVar == var) { + return index; + } + } + --index; + } + return index; + } +} diff --git a/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java b/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java index 5ff73991c..c62b2da8f 100644 --- a/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java +++ b/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java @@ -36,8 +36,8 @@ public class ClassSetOptimizer { } private List getOptimizations() { - return Arrays.asList(new LoopInvariantMotion(), new GlobalValueNumbering(), - new UnusedVariableElimination()); + return Arrays.asList(new ArrayUnwrapMotion(), new LoopInvariantMotion(), + new GlobalValueNumbering(), new UnusedVariableElimination()); } public void optimizeAll(ListableClassHolderSource classSource) {