Minor optimizations

This commit is contained in:
konsoletyper 2014-07-07 17:35:30 +04:00
parent ef700237f5
commit a32d6d037b
5 changed files with 123 additions and 47 deletions

View File

@ -15,16 +15,33 @@
*/ */
package org.teavm.javascript; package org.teavm.javascript;
import java.util.HashMap; import java.util.List;
import java.util.Map;
import org.teavm.javascript.ast.*; import org.teavm.javascript.ast.*;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class BlockRefCountVisitor implements StatementVisitor { class CertainBlockCountVisitor implements StatementVisitor {
Map<IdentifiedStatement, Integer> refs = new HashMap<>(); private BlockStatement blockToCount;
private int count;
public CertainBlockCountVisitor(BlockStatement blockToCount) {
this.blockToCount = blockToCount;
}
public int getCount() {
return count;
}
public void visit(List<Statement> statements) {
if (statements == null) {
return;
}
for (Statement part : statements) {
part.acceptVisitor(this);
}
}
@Override @Override
public void visit(AssignmentStatement statement) { public void visit(AssignmentStatement statement) {
@ -32,48 +49,31 @@ class BlockRefCountVisitor implements StatementVisitor {
@Override @Override
public void visit(SequentialStatement statement) { public void visit(SequentialStatement statement) {
for (Statement part : statement.getSequence()) { visit(statement.getSequence());
part.acceptVisitor(this);
}
} }
@Override @Override
public void visit(ConditionalStatement statement) { public void visit(ConditionalStatement statement) {
for (Statement stmt : statement.getConsequent()) { visit(statement.getConsequent());
stmt.acceptVisitor(this); visit(statement.getAlternative());
}
for (Statement stmt : statement.getAlternative()) {
stmt.acceptVisitor(this);
}
} }
@Override @Override
public void visit(SwitchStatement statement) { public void visit(SwitchStatement statement) {
refs.put(statement, 0);
for (SwitchClause clause : statement.getClauses()) { for (SwitchClause clause : statement.getClauses()) {
for (Statement part : clause.getBody()) { visit(clause.getBody());
part.acceptVisitor(this);
}
}
for (Statement part : statement.getDefaultClause()) {
part.acceptVisitor(this);
} }
visit(statement.getDefaultClause());
} }
@Override @Override
public void visit(WhileStatement statement) { public void visit(WhileStatement statement) {
refs.put(statement, 0); visit(statement.getBody());
for (Statement part : statement.getBody()) {
part.acceptVisitor(this);
}
} }
@Override @Override
public void visit(BlockStatement statement) { public void visit(BlockStatement statement) {
refs.put(statement, 0); visit(statement.getBody());
for (Statement part : statement.getBody()) {
part.acceptVisitor(this);
}
} }
@Override @Override
@ -82,12 +82,16 @@ class BlockRefCountVisitor implements StatementVisitor {
@Override @Override
public void visit(BreakStatement statement) { public void visit(BreakStatement statement) {
refs.put(statement.getTarget(), refs.get(statement.getTarget()) + 1); if (statement.getTarget() == blockToCount) {
++count;
}
} }
@Override @Override
public void visit(ContinueStatement statement) { public void visit(ContinueStatement statement) {
refs.put(statement.getTarget(), refs.get(statement.getTarget()) + 1); if (statement.getTarget() == blockToCount) {
++count;
}
} }
@Override @Override
@ -108,11 +112,7 @@ class BlockRefCountVisitor implements StatementVisitor {
@Override @Override
public void visit(TryCatchStatement statement) { public void visit(TryCatchStatement statement) {
for (Statement part : statement.getProtectedBody()) { visit(statement.getProtectedBody());
part.acceptVisitor(this); visit(statement.getHandler());
}
for (Statement part : statement.getHandler()) {
part.acceptVisitor(this);
}
} }
} }

View File

@ -27,10 +27,7 @@ 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);
BlockRefCountVisitor refsCounter = new BlockRefCountVisitor();
method.getBody().acceptVisitor(refsCounter);
OptimizingVisitor optimizer = new OptimizingVisitor(stats); OptimizingVisitor optimizer = new OptimizingVisitor(stats);
optimizer.referencedStatements = refsCounter.refs;
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();

View File

@ -26,7 +26,6 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
public Expr resultExpr; public Expr resultExpr;
public Statement resultStmt; public Statement resultStmt;
private ReadWriteStatsBuilder stats; private ReadWriteStatsBuilder stats;
Map<IdentifiedStatement, Integer> referencedStatements = new HashMap<>();
private List<Statement> resultSequence; private List<Statement> resultSequence;
public OptimizingVisitor(ReadWriteStatsBuilder stats) { public OptimizingVisitor(ReadWriteStatsBuilder stats) {
@ -344,8 +343,6 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
if (last instanceof BreakStatement) { if (last instanceof BreakStatement) {
BreakStatement breakStmt = (BreakStatement)last; BreakStatement breakStmt = (BreakStatement)last;
if (exit != null && exit == breakStmt.getTarget()) { 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); cond.getConsequent().remove(cond.getConsequent().size() - 1);
List<Statement> remaining = statements.subList(i + 1, statements.size()); List<Statement> remaining = statements.subList(i + 1, statements.size());
cond.getAlternative().addAll(remaining); cond.getAlternative().addAll(remaining);
@ -358,8 +355,6 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
if (last instanceof BreakStatement) { if (last instanceof BreakStatement) {
BreakStatement breakStmt = (BreakStatement)last; BreakStatement breakStmt = (BreakStatement)last;
if (exit != null && exit == breakStmt.getTarget()) { 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); cond.getAlternative().remove(cond.getConsequent().size() - 1);
List<Statement> remaining = statements.subList(i + 1, statements.size()); List<Statement> remaining = statements.subList(i + 1, statements.size());
cond.getConsequent().addAll(remaining); cond.getConsequent().addAll(remaining);
@ -476,6 +471,15 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
statement.getBody().addAll(innerLoop.getBody()); statement.getBody().addAll(innerLoop.getBody());
} }
List<Statement> statements = processSequence(statement.getBody()); List<Statement> 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().clear();
statement.getBody().addAll(statements); statement.getBody().addAll(statements);
if (statement.getCondition() != null) { if (statement.getCondition() != null) {
@ -511,7 +515,9 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
public void visit(BlockStatement statement) { public void visit(BlockStatement statement) {
List<Statement> statements = processSequence(statement.getBody()); List<Statement> statements = processSequence(statement.getBody());
eliminateRedundantBreaks(statements, statement); 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(); SequentialStatement result = new SequentialStatement();
result.getSequence().addAll(statements); result.getSequence().addAll(statements);
resultStmt = result; resultStmt = result;

View File

@ -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<Instruction> newInstructions = new ArrayList<>();
List<Instruction> 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<Instruction> 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;
}
}

View File

@ -36,8 +36,8 @@ public class ClassSetOptimizer {
} }
private List<MethodOptimization> getOptimizations() { private List<MethodOptimization> getOptimizations() {
return Arrays.<MethodOptimization>asList(new LoopInvariantMotion(), new GlobalValueNumbering(), return Arrays.<MethodOptimization>asList(new ArrayUnwrapMotion(), new LoopInvariantMotion(),
new UnusedVariableElimination()); new GlobalValueNumbering(), new UnusedVariableElimination());
} }
public void optimizeAll(ListableClassHolderSource classSource) { public void optimizeAll(ListableClassHolderSource classSource) {