mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
All tests pass with register allocation
This commit is contained in:
parent
94fe8a0acf
commit
c9a891d9cd
|
@ -52,7 +52,7 @@
|
||||||
</goals>
|
</goals>
|
||||||
<phase>process-test-classes</phase>
|
<phase>process-test-classes</phase>
|
||||||
<configuration>
|
<configuration>
|
||||||
<minifying>true</minifying>
|
<minifying>false</minifying>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
|
|
@ -201,7 +201,7 @@ public class Decompiler {
|
||||||
methodNode.getVariables().add(program.variableAt(i).getRegister());
|
methodNode.getVariables().add(program.variableAt(i).getRegister());
|
||||||
}
|
}
|
||||||
Optimizer optimizer = new Optimizer();
|
Optimizer optimizer = new Optimizer();
|
||||||
optimizer.optimize(methodNode);
|
optimizer.optimize(methodNode, method.getProgram());
|
||||||
return methodNode;
|
return methodNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class JavascriptBuilder {
|
||||||
private DependencyChecker dependencyChecker;
|
private DependencyChecker dependencyChecker;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
private boolean minifying = true;
|
private boolean minifying = true;
|
||||||
private boolean bytecodeLogging;
|
private boolean bytecodeLogging = true;
|
||||||
private OutputStream logStream = System.out;
|
private OutputStream logStream = System.out;
|
||||||
private Map<String, JavascriptEntryPoint> entryPoints = new HashMap<>();
|
private Map<String, JavascriptEntryPoint> entryPoints = new HashMap<>();
|
||||||
private Map<String, String> exportedClasses = new HashMap<>();
|
private Map<String, String> exportedClasses = new HashMap<>();
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
package org.teavm.javascript;
|
package org.teavm.javascript;
|
||||||
|
|
||||||
import org.teavm.javascript.ast.RegularMethodNode;
|
import org.teavm.javascript.ast.RegularMethodNode;
|
||||||
import org.teavm.javascript.ast.Statement;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.MethodHolder;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,17 +24,9 @@ import org.teavm.model.MethodHolder;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class Optimizer {
|
public class Optimizer {
|
||||||
public Statement optimize(MethodHolder method, Statement statement) {
|
public void optimize(RegularMethodNode method, Program program) {
|
||||||
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) {
|
|
||||||
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
||||||
method.getBody().acceptVisitor(stats);
|
stats.analyze(program);
|
||||||
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
|
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
|
||||||
method.getBody().acceptVisitor(optimizer);
|
method.getBody().acceptVisitor(optimizer);
|
||||||
method.setBody(optimizer.resultStmt);
|
method.setBody(optimizer.resultStmt);
|
||||||
|
|
|
@ -377,7 +377,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
WhileStatement result = new WhileStatement();
|
WhileStatement result = new WhileStatement();
|
||||||
result.setId(statement.getId());
|
result.setId(statement.getId());
|
||||||
visitIdentified(statement, result);
|
visitIdentified(statement, result);
|
||||||
List<Statement> statements = processSequence(statement.getBody(), false);
|
List<Statement> statements = processSequence(statement.getBody(), true);
|
||||||
if (statement.getCondition() != null) {
|
if (statement.getCondition() != null) {
|
||||||
statement.getCondition().acceptVisitor(this);
|
statement.getCondition().acceptVisitor(this);
|
||||||
result.setCondition(resultExpr);
|
result.setCondition(resultExpr);
|
||||||
|
|
|
@ -15,13 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.javascript;
|
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
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
class ReadWriteStatsBuilder implements StatementVisitor, ExprVisitor {
|
class ReadWriteStatsBuilder {
|
||||||
public int[] reads;
|
public int[] reads;
|
||||||
public int[] writes;
|
public int[] writes;
|
||||||
|
|
||||||
|
@ -30,169 +32,27 @@ class ReadWriteStatsBuilder implements StatementVisitor, ExprVisitor {
|
||||||
writes = new int[variableCount];
|
writes = new int[variableCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void analyze(Program program) {
|
||||||
public void visit(BinaryExpr expr) {
|
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||||
expr.getFirstOperand().acceptVisitor(this);
|
UsageExtractor useExtractor = new UsageExtractor();
|
||||||
expr.getSecondOperand().acceptVisitor(this);
|
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()]++;
|
||||||
}
|
}
|
||||||
|
for (Variable var : useExtractor.getUsedVariables()) {
|
||||||
@Override
|
reads[var.getIndex()]++;
|
||||||
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 (Phi phi : block.getPhis()) {
|
||||||
@Override
|
writes[phi.getReceiver().getIndex()] += phi.getIncomings().size();
|
||||||
public void visit(QualificationExpr expr) {
|
for (Incoming incoming : phi.getIncomings()) {
|
||||||
expr.getQualified().acceptVisitor(this);
|
reads[incoming.getValue().getIndex()]++;
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,13 +35,11 @@ class GraphColorer {
|
||||||
classMembers.get(cls).add(i);
|
classMembers.get(cls).add(i);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < colors.length; ++i) {
|
for (int i = 0; i < colors.length; ++i) {
|
||||||
int color = colors[i];
|
if (colors[i] >= 0) {
|
||||||
if (color != -1) {
|
|
||||||
int cls = classes[i];
|
int cls = classes[i];
|
||||||
for (int member : classMembers.get(cls)) {
|
for (int member : classMembers.get(cls)) {
|
||||||
colors[member] = color;
|
colors[member] = colors[i];
|
||||||
}
|
}
|
||||||
classMembers.get(cls).clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BitSet usedColors = new BitSet();
|
BitSet usedColors = new BitSet();
|
||||||
|
@ -49,15 +47,18 @@ class GraphColorer {
|
||||||
if (colors[v] >= 0) {
|
if (colors[v] >= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
int cls = classes[v];
|
||||||
usedColors.clear();
|
usedColors.clear();
|
||||||
usedColors.set(0);
|
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) {
|
if (colors[succ] >= 0) {
|
||||||
usedColors.set(colors[succ]);
|
usedColors.set(colors[succ]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
int color = usedColors.nextClearBit(0);
|
int color = usedColors.nextClearBit(0);
|
||||||
for (int member : classMembers.get(classes[v])) {
|
for (int member : classMembers.get(cls)) {
|
||||||
colors[member] = color;
|
colors[member] = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import org.teavm.model.*;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
class InterferenceGraphBuilder {
|
class InterferenceGraphBuilder {
|
||||||
public Graph build(Program program, LivenessAnalyzer liveness) {
|
public Graph build(Program program, int paramCount, LivenessAnalyzer liveness) {
|
||||||
List<Set<Integer>> edges = new ArrayList<>();
|
List<Set<Integer>> edges = new ArrayList<>();
|
||||||
for (int i = 0; i < program.variableCount(); ++i) {
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
edges.add(new HashSet<Integer>());
|
edges.add(new HashSet<Integer>());
|
||||||
|
@ -64,6 +64,11 @@ class InterferenceGraphBuilder {
|
||||||
live.add(var.getIndex());
|
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);
|
BitSet liveIn = liveness.liveIn(i);
|
||||||
live = new HashSet<>();
|
live = new HashSet<>();
|
||||||
for (int j = 0; j < liveOut.length(); ++j) {
|
for (int j = 0; j < liveOut.length(); ++j) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class RegisterAllocator {
|
||||||
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
||||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||||
liveness.analyze(program);
|
liveness.analyze(program);
|
||||||
Graph interferenceGraph = interferenceBuilder.build(program, liveness);
|
Graph interferenceGraph = interferenceBuilder.build(program, method.parameterCount(), liveness);
|
||||||
DisjointSet congruenceClasses = buildPhiCongruenceClasses(program);
|
DisjointSet congruenceClasses = buildPhiCongruenceClasses(program);
|
||||||
removeRedundantCopies(program, phiArgsCopies, interferenceGraph, congruenceClasses);
|
removeRedundantCopies(program, phiArgsCopies, interferenceGraph, congruenceClasses);
|
||||||
int[] classArray = congruenceClasses.pack(program.variableCount());
|
int[] classArray = congruenceClasses.pack(program.variableCount());
|
||||||
|
|
Loading…
Reference in New Issue
Block a user