mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Minor optimizations
This commit is contained in:
parent
ef700237f5
commit
a32d6d037b
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user