All tests pass with register allocation

This commit is contained in:
konsoletyper 2014-01-27 16:02:23 +04:00
parent 94fe8a0acf
commit c9a891d9cd
9 changed files with 47 additions and 190 deletions

View File

@ -52,7 +52,7 @@
</goals>
<phase>process-test-classes</phase>
<configuration>
<minifying>true</minifying>
<minifying>false</minifying>
</configuration>
</execution>
</executions>

View File

@ -201,7 +201,7 @@ public class Decompiler {
methodNode.getVariables().add(program.variableAt(i).getRegister());
}
Optimizer optimizer = new Optimizer();
optimizer.optimize(methodNode);
optimizer.optimize(methodNode, method.getProgram());
return methodNode;
}

View File

@ -37,7 +37,7 @@ public class JavascriptBuilder {
private DependencyChecker dependencyChecker;
private ClassLoader classLoader;
private boolean minifying = true;
private boolean bytecodeLogging;
private boolean bytecodeLogging = true;
private OutputStream logStream = System.out;
private Map<String, JavascriptEntryPoint> entryPoints = new HashMap<>();
private Map<String, String> exportedClasses = new HashMap<>();

View File

@ -16,8 +16,7 @@
package org.teavm.javascript;
import org.teavm.javascript.ast.RegularMethodNode;
import org.teavm.javascript.ast.Statement;
import org.teavm.model.MethodHolder;
import org.teavm.model.Program;
/**
@ -25,17 +24,9 @@ import org.teavm.model.MethodHolder;
* @author Alexey Andreev
*/
public class Optimizer {
public Statement optimize(MethodHolder method, Statement statement) {
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getProgram().variableCount());
statement.acceptVisitor(stats);
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
statement.acceptVisitor(optimizer);
return optimizer.resultStmt;
}
public void optimize(RegularMethodNode method) {
public void optimize(RegularMethodNode method, Program program) {
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
method.getBody().acceptVisitor(stats);
stats.analyze(program);
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
method.getBody().acceptVisitor(optimizer);
method.setBody(optimizer.resultStmt);

View File

@ -377,7 +377,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
WhileStatement result = new WhileStatement();
result.setId(statement.getId());
visitIdentified(statement, result);
List<Statement> statements = processSequence(statement.getBody(), false);
List<Statement> statements = processSequence(statement.getBody(), true);
if (statement.getCondition() != null) {
statement.getCondition().acceptVisitor(this);
result.setCondition(resultExpr);

View File

@ -15,13 +15,15 @@
*/
package org.teavm.javascript;
import org.teavm.javascript.ast.*;
import org.teavm.model.*;
import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.UsageExtractor;
/**
*
* @author Alexey Andreev
*/
class ReadWriteStatsBuilder implements StatementVisitor, ExprVisitor {
class ReadWriteStatsBuilder {
public int[] reads;
public int[] writes;
@ -30,169 +32,27 @@ class ReadWriteStatsBuilder implements StatementVisitor, ExprVisitor {
writes = new int[variableCount];
}
@Override
public void visit(BinaryExpr expr) {
expr.getFirstOperand().acceptVisitor(this);
expr.getSecondOperand().acceptVisitor(this);
public void analyze(Program program) {
DefinitionExtractor defExtractor = new DefinitionExtractor();
UsageExtractor useExtractor = new UsageExtractor();
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
for (Instruction insn : block.getInstructions()) {
insn.acceptVisitor(defExtractor);
insn.acceptVisitor(useExtractor);
for (Variable var : defExtractor.getDefinedVariables()) {
writes[var.getIndex()]++;
}
@Override
public void visit(UnaryExpr expr) {
expr.getOperand().acceptVisitor(this);
}
@Override
public void visit(ConditionalExpr expr) {
expr.getCondition().acceptVisitor(this);
expr.getConsequent().acceptVisitor(this);
expr.getAlternative().acceptVisitor(this);
}
@Override
public void visit(ConstantExpr expr) {
}
@Override
public void visit(VariableExpr expr) {
reads[expr.getIndex()]++;
}
@Override
public void visit(SubscriptExpr expr) {
expr.getArray().acceptVisitor(this);
expr.getIndex().acceptVisitor(this);
}
@Override
public void visit(UnwrapArrayExpr expr) {
expr.getArray().acceptVisitor(this);
}
@Override
public void visit(InvocationExpr expr) {
for (Expr arg : expr.getArguments()) {
arg.acceptVisitor(this);
for (Variable var : useExtractor.getUsedVariables()) {
reads[var.getIndex()]++;
}
}
@Override
public void visit(QualificationExpr expr) {
expr.getQualified().acceptVisitor(this);
}
@Override
public void visit(NewExpr expr) {
}
@Override
public void visit(NewArrayExpr expr) {
expr.getLength().acceptVisitor(this);
}
@Override
public void visit(NewMultiArrayExpr expr) {
for (Expr dimension : expr.getDimensions()) {
dimension.acceptVisitor(this);
for (Phi phi : block.getPhis()) {
writes[phi.getReceiver().getIndex()] += phi.getIncomings().size();
for (Incoming incoming : phi.getIncomings()) {
reads[incoming.getValue().getIndex()]++;
}
}
@Override
public void visit(InstanceOfExpr expr) {
expr.getExpr().acceptVisitor(this);
}
@Override
public void visit(StaticClassExpr expr) {
}
@Override
public void visit(AssignmentStatement statement) {
if (statement.getLeftValue() != null) {
if (statement.getLeftValue() instanceof VariableExpr) {
VariableExpr leftVar = (VariableExpr)statement.getLeftValue();
writes[leftVar.getIndex()]++;
} else {
statement.getLeftValue().acceptVisitor(this);
}
}
statement.getRightValue().acceptVisitor(this);
}
@Override
public void visit(SequentialStatement statement) {
for (Statement part : statement.getSequence()) {
part.acceptVisitor(this);
}
}
@Override
public void visit(ConditionalStatement statement) {
statement.getCondition().acceptVisitor(this);
statement.getConsequent().acceptVisitor(this);
if (statement.getAlternative() != null) {
statement.getAlternative().acceptVisitor(this);
}
}
@Override
public void visit(SwitchStatement statement) {
statement.getValue().acceptVisitor(this);
for (SwitchClause clause : statement.getClauses()) {
clause.getStatement().acceptVisitor(this);
}
if (statement.getDefaultClause() != null) {
statement.getDefaultClause().acceptVisitor(this);
}
}
@Override
public void visit(WhileStatement statement) {
if (statement.getCondition() != null) {
statement.getCondition().acceptVisitor(this);
}
for (Statement part : statement.getBody()) {
part.acceptVisitor(this);
}
}
@Override
public void visit(BlockStatement statement) {
for (Statement part : statement.getBody()) {
part.acceptVisitor(this);
}
}
@Override
public void visit(ForStatement statement) {
}
@Override
public void visit(BreakStatement statement) {
}
@Override
public void visit(ContinueStatement statement) {
}
@Override
public void visit(ReturnStatement statement) {
if (statement.getResult() != null) {
statement.getResult().acceptVisitor(this);
}
}
@Override
public void visit(ThrowStatement statement) {
statement.getException().acceptVisitor(this);
}
@Override
public void visit(IncrementStatement statement) {
reads[statement.getVar()]++;
writes[statement.getVar()]++;
}
@Override
public void visit(InitClassStatement statement) {
}
}

View File

@ -35,13 +35,11 @@ class GraphColorer {
classMembers.get(cls).add(i);
}
for (int i = 0; i < colors.length; ++i) {
int color = colors[i];
if (color != -1) {
if (colors[i] >= 0) {
int cls = classes[i];
for (int member : classMembers.get(cls)) {
colors[member] = color;
colors[member] = colors[i];
}
classMembers.get(cls).clear();
}
}
BitSet usedColors = new BitSet();
@ -49,15 +47,18 @@ class GraphColorer {
if (colors[v] >= 0) {
continue;
}
int cls = classes[v];
usedColors.clear();
usedColors.set(0);
for (int succ : graph.outgoingEdges(v)) {
for (int member : classMembers.get(cls)) {
for (int succ : graph.outgoingEdges(member)) {
if (colors[succ] >= 0) {
usedColors.set(colors[succ]);
}
}
}
int color = usedColors.nextClearBit(0);
for (int member : classMembers.get(classes[v])) {
for (int member : classMembers.get(cls)) {
colors[member] = color;
}
}

View File

@ -25,7 +25,7 @@ import org.teavm.model.*;
* @author Alexey Andreev
*/
class InterferenceGraphBuilder {
public Graph build(Program program, LivenessAnalyzer liveness) {
public Graph build(Program program, int paramCount, LivenessAnalyzer liveness) {
List<Set<Integer>> edges = new ArrayList<>();
for (int i = 0; i < program.variableCount(); ++i) {
edges.add(new HashSet<Integer>());
@ -64,6 +64,11 @@ class InterferenceGraphBuilder {
live.add(var.getIndex());
}
}
if (block.getIndex() == 0) {
for (int j = 0; j <= paramCount; ++j) {
edges.get(j).addAll(live);
}
}
BitSet liveIn = liveness.liveIn(i);
live = new HashSet<>();
for (int j = 0; j < liveOut.length(); ++j) {

View File

@ -34,7 +34,7 @@ public class RegisterAllocator {
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
LivenessAnalyzer liveness = new LivenessAnalyzer();
liveness.analyze(program);
Graph interferenceGraph = interferenceBuilder.build(program, liveness);
Graph interferenceGraph = interferenceBuilder.build(program, method.parameterCount(), liveness);
DisjointSet congruenceClasses = buildPhiCongruenceClasses(program);
removeRedundantCopies(program, phiArgsCopies, interferenceGraph, congruenceClasses);
int[] classArray = congruenceClasses.pack(program.variableCount());