diff --git a/teavm-classlib/pom.xml b/teavm-classlib/pom.xml
index c3407f71d..f5e88105d 100644
--- a/teavm-classlib/pom.xml
+++ b/teavm-classlib/pom.xml
@@ -52,7 +52,7 @@
process-test-classes
- false
+ true
diff --git a/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java b/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java
index 87b323ea3..bc1692335 100644
--- a/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java
+++ b/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java
@@ -55,18 +55,21 @@ public class SourceWriter implements Appendable {
@Override
public SourceWriter append(char value) throws IOException {
+ appendIndent();
innerWriter.append(value);
return this;
}
@Override
public SourceWriter append(CharSequence csq) throws IOException {
+ appendIndent();
innerWriter.append(csq);
return this;
}
@Override
public SourceWriter append(CharSequence csq, int start, int end) throws IOException {
+ appendIndent();
innerWriter.append(csq, start, end);
return this;
}
diff --git a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java
index a3688c1cc..a0aef8f68 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java
@@ -183,9 +183,6 @@ public class Decompiler {
if (node >= 0) {
generator.currentBlock = program.basicBlockAt(node);
int tmp = indexer.nodeAt(next);
- if (tmp == -1) {
- System.out.println();
- }
generator.nextBlock = next < indexer.size() ? program.basicBlockAt(tmp) : null;
generator.statements.clear();
for (Instruction insn : generator.currentBlock.getInstructions()) {
@@ -200,7 +197,9 @@ public class Decompiler {
RegularMethodNode methodNode = new RegularMethodNode(reference);
methodNode.getModifiers().addAll(mapModifiers(method.getModifiers()));
methodNode.setBody(result);
- methodNode.setVariableCount(program.variableCount());
+ for (int i = 0; i < program.variableCount(); ++i) {
+ methodNode.getVariables().add(program.variableAt(i).getRegister());
+ }
Optimizer optimizer = new Optimizer();
optimizer.optimize(methodNode);
return methodNode;
diff --git a/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java b/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java
index cda48cd99..7e5047432 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java
@@ -112,6 +112,7 @@ public class JavascriptBuilder {
Decompiler decompiler = new Decompiler(classSet, classLoader);
ClassSetOptimizer optimizer = new ClassSetOptimizer();
optimizer.optimizeAll(classSet);
+ allocateRegisters(classSet);
if (bytecodeLogging) {
try {
logBytecode(new PrintWriter(new OutputStreamWriter(logStream, "UTF-8")), classSet);
@@ -138,6 +139,18 @@ public class JavascriptBuilder {
}
}
+ private void allocateRegisters(ListableClassHolderSource classes) {
+ RegisterAllocator allocator = new RegisterAllocator();
+ for (String className : classes.getClassNames()) {
+ ClassHolder cls = classes.getClassHolder(className);
+ for (MethodHolder method : cls.getMethods()) {
+ if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) {
+ allocator.allocateRegisters(method);
+ }
+ }
+ }
+ }
+
private void logBytecode(PrintWriter writer, ListableClassHolderSource classes) {
for (String className : classes.getClassNames()) {
ClassHolder classHolder = classes.getClassHolder(className);
@@ -161,14 +174,13 @@ public class JavascriptBuilder {
printType(writer, parameterTypes[i]);
}
writer.println(")");
- if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) {
+ Program program = method.getProgram();
+ if (program != null && program.basicBlockCount() > 0) {
ListingBuilder builder = new ListingBuilder();
- RegisterAllocator allocator = new RegisterAllocator();
- int[] colors = allocator.allocateRegisters(method);
- writer.print(builder.buildListing(method.getProgram(), " "));
+ writer.print(builder.buildListing(program, " "));
writer.print(" Register allocation:");
- for (int i = 0; i < colors.length; ++i) {
- writer.print(i + ":" + colors[i] + " ");
+ for (int i = 0; i < program.variableCount(); ++i) {
+ writer.print(i + ":" + program.variableAt(i).getRegister() + " ");
}
writer.println();
writer.println();
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 98a159b0f..d1275438a 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java
@@ -34,14 +34,17 @@ public class Optimizer {
}
public void optimize(RegularMethodNode method) {
- ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariableCount());
+ ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
method.getBody().acceptVisitor(stats);
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
method.getBody().acceptVisitor(optimizer);
method.setBody(optimizer.resultStmt);
int paramCount = method.getReference().parameterCount();
- UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariableCount());
+ UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariables());
method.getBody().acceptVisitor(unusedEliminator);
- method.setVariableCount(unusedEliminator.lastIndex);
+ method.getVariables().subList(unusedEliminator.lastIndex, method.getVariables().size()).clear();
+ for (int i = 0; i < method.getVariables().size(); ++i) {
+ method.getVariables().set(i, i);
+ }
}
}
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 fbc250e83..4a83b85ca 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java
@@ -271,16 +271,8 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
} else {
statement.getRightValue().acceptVisitor(this);
Expr right = resultExpr;
- Expr left;
- if (statement.getLeftValue() instanceof VariableExpr) {
- VariableExpr leftVar = (VariableExpr)statement.getLeftValue();
- left = statement.getLeftValue();
- if (stats.reads[leftVar.getIndex()] == 0) {
- left = null;
- } else {
- left = statement.getLeftValue();
- }
- } else {
+ Expr left = statement.getLeftValue();
+ if (!(statement.getLeftValue() instanceof VariableExpr)) {
statement.getLeftValue().acceptVisitor(this);
left = resultExpr;
}
diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java
index 51f93dd53..706b2f984 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java
@@ -332,7 +332,10 @@ public class Renderer implements ExprVisitor, StatementVisitor {
public void visit(RegularMethodNode method) {
try {
MethodReference ref = method.getReference();
- int variableCount = method.getVariableCount();
+ int variableCount = 0;
+ for (int var : method.getVariables()) {
+ variableCount = Math.max(variableCount, var + 1);
+ }
boolean hasVars = variableCount > ref.parameterCount() + 1;
if (hasVars) {
writer.append("var ");
diff --git a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java
index 37880481e..aa25c490a 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java
@@ -578,7 +578,7 @@ class StatementGenerator implements InstructionVisitor {
assign(castToInteger(Expr.binary(op, Expr.var(first), Expr.var(second))), result);
}
- private Statement generateJumpStatementWithoutPhis(BasicBlock target) {
+ private Statement generateJumpStatement(BasicBlock target) {
if (nextBlock == target) {
return null;
}
@@ -593,29 +593,8 @@ class StatementGenerator implements InstructionVisitor {
return contStmt;
}
}
-
- private Statement wrapWithPhis(Statement rawJump, BasicBlock target) {
- SequentialStatement seq = new SequentialStatement();
- for (Phi phi : target.getPhis()) {
- for (Incoming outgoing : phi.getIncomings()) {
- if (outgoing.getSource() == currentBlock) {
- seq.getSequence().add(Statement.assign(Expr.var(outgoing.getPhi().getReceiver().getIndex()),
- Expr.var(outgoing.getValue().getIndex())));
- }
- }
- }
- if (rawJump != null) {
- seq.getSequence().add(rawJump);
- }
- return !seq.getSequence().isEmpty() ? seq : null;
- }
-
- private Statement generateJumpStatement(BasicBlock target) {
- return wrapWithPhis(generateJumpStatementWithoutPhis(target), target);
- }
-
- private Statement generateJumpStatementWithoutPhis(SwitchStatement stmt, int target) {
- Statement body = generateJumpStatementWithoutPhis(program.basicBlockAt(target));
+ private Statement generateJumpStatement(SwitchStatement stmt, int target) {
+ Statement body = generateJumpStatement(program.basicBlockAt(target));
if (body == null) {
BreakStatement breakStmt = new BreakStatement();
breakStmt.setTarget(stmt);
@@ -623,11 +602,6 @@ class StatementGenerator implements InstructionVisitor {
}
return body;
}
-
- private Statement generateJumpStatement(SwitchStatement stmt, int target) {
- return wrapWithPhis(generateJumpStatementWithoutPhis(stmt, target), program.basicBlockAt(target));
- }
-
private void branch(Expr condition, BasicBlock consequentBlock, BasicBlock alternativeBlock) {
Statement consequent = generateJumpStatement(consequentBlock);
Statement alternative = generateJumpStatement(alternativeBlock);
diff --git a/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java
index 7832f4e17..ac9a4fd22 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java
@@ -16,6 +16,7 @@
package org.teavm.javascript;
import java.util.Arrays;
+import java.util.List;
import org.teavm.javascript.ast.*;
/**
@@ -23,10 +24,18 @@ import org.teavm.javascript.ast.*;
* @author Alexey Andreev
*/
class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
+ int[] variables;
int[] indexes;
int lastIndex;
- public UnusedVariableEliminator(int parameterCount, int variableCount) {
+ public UnusedVariableEliminator(int parameterCount, List variables) {
+ this.variables = new int[variables.size()];
+ int variableCount = 0;
+ for (int i = 0; i < variables.size(); ++i) {
+ int var = variables.get(i);
+ this.variables[i] = var;
+ variableCount = Math.max(variableCount, var + 1);
+ }
indexes = new int[variableCount];
Arrays.fill(indexes, -1);
for (int i = 0; i <= parameterCount; ++i) {
@@ -109,10 +118,10 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
}
private int renumber(int var) {
- int index = indexes[var];
+ int index = indexes[variables[var]];
if (index == -1) {
index = lastIndex++;
- indexes[var] = index;
+ indexes[variables[var]] = index;
}
return index;
}
diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/RegularMethodNode.java b/teavm-core/src/main/java/org/teavm/javascript/ast/RegularMethodNode.java
index 5e2041167..8184d8fac 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/ast/RegularMethodNode.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/ast/RegularMethodNode.java
@@ -15,6 +15,8 @@
*/
package org.teavm.javascript.ast;
+import java.util.ArrayList;
+import java.util.List;
import org.teavm.model.MethodReference;
/**
@@ -23,7 +25,7 @@ import org.teavm.model.MethodReference;
*/
public class RegularMethodNode extends MethodNode {
private Statement body;
- private int variableCount;
+ private List variables = new ArrayList<>();
public RegularMethodNode(MethodReference reference) {
super(reference);
@@ -37,12 +39,8 @@ public class RegularMethodNode extends MethodNode {
this.body = body;
}
- public int getVariableCount() {
- return variableCount;
- }
-
- public void setVariableCount(int variableCount) {
- this.variableCount = variableCount;
+ public List getVariables() {
+ return variables;
}
@Override
diff --git a/teavm-core/src/main/java/org/teavm/model/Program.java b/teavm-core/src/main/java/org/teavm/model/Program.java
index 470012c4e..57d66b4cb 100644
--- a/teavm-core/src/main/java/org/teavm/model/Program.java
+++ b/teavm-core/src/main/java/org/teavm/model/Program.java
@@ -27,6 +27,7 @@ public class Program {
private List variables = new ArrayList<>();
private MethodHolder method;
private boolean packed;
+ private int lastUsedRegister;
public BasicBlock createBasicBlock() {
BasicBlock block = new BasicBlock(this, basicBlocks.size());
@@ -38,6 +39,7 @@ public class Program {
Variable variable = new Variable(this);
variable.setIndex(variables.size());
variables.add(variable);
+ variable.setRegister(lastUsedRegister++);
return variable;
}
diff --git a/teavm-core/src/main/java/org/teavm/model/Variable.java b/teavm-core/src/main/java/org/teavm/model/Variable.java
index d363aed42..b0fb3b27a 100644
--- a/teavm-core/src/main/java/org/teavm/model/Variable.java
+++ b/teavm-core/src/main/java/org/teavm/model/Variable.java
@@ -22,6 +22,7 @@ package org.teavm.model;
public class Variable {
private Program program;
private int index;
+ private int register;
Variable(Program program) {
this.program = program;
@@ -42,4 +43,12 @@ public class Variable {
void setProgram(Program program) {
this.program = program;
}
+
+ public int getRegister() {
+ return register;
+ }
+
+ public void setRegister(int register) {
+ this.register = register;
+ }
}
diff --git a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java
index 0d38f09a5..1b6865807 100644
--- a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java
+++ b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java
@@ -28,7 +28,7 @@ import org.teavm.model.instructions.JumpInstruction;
* @author Alexey Andreev
*/
public class RegisterAllocator {
- public int[] allocateRegisters(MethodHolder method) {
+ public void allocateRegisters(MethodHolder method) {
Program program = method.getProgram();
List phiArgsCopies = insertPhiArgumentsCopies(program);
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
@@ -45,7 +45,9 @@ public class RegisterAllocator {
}
GraphColorer colorer = new GraphColorer();
colorer.colorize(interferenceGraph, classArray, colors);
- return colors;
+ for (int i = 0; i < colors.length; ++i) {
+ method.getProgram().variableAt(i).setRegister(colors[i]);
+ }
}
private static class PhiArgumentCopy {