Fixes minor decompilation issues

This commit is contained in:
konsoletyper 2014-01-27 12:36:35 +04:00
parent 0eb4e54e51
commit 94fe8a0acf
13 changed files with 72 additions and 66 deletions

View File

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

View File

@ -55,18 +55,21 @@ public class SourceWriter implements Appendable {
@Override @Override
public SourceWriter append(char value) throws IOException { public SourceWriter append(char value) throws IOException {
appendIndent();
innerWriter.append(value); innerWriter.append(value);
return this; return this;
} }
@Override @Override
public SourceWriter append(CharSequence csq) throws IOException { public SourceWriter append(CharSequence csq) throws IOException {
appendIndent();
innerWriter.append(csq); innerWriter.append(csq);
return this; return this;
} }
@Override @Override
public SourceWriter append(CharSequence csq, int start, int end) throws IOException { public SourceWriter append(CharSequence csq, int start, int end) throws IOException {
appendIndent();
innerWriter.append(csq, start, end); innerWriter.append(csq, start, end);
return this; return this;
} }

View File

@ -183,9 +183,6 @@ public class Decompiler {
if (node >= 0) { if (node >= 0) {
generator.currentBlock = program.basicBlockAt(node); generator.currentBlock = program.basicBlockAt(node);
int tmp = indexer.nodeAt(next); int tmp = indexer.nodeAt(next);
if (tmp == -1) {
System.out.println();
}
generator.nextBlock = next < indexer.size() ? program.basicBlockAt(tmp) : null; generator.nextBlock = next < indexer.size() ? program.basicBlockAt(tmp) : null;
generator.statements.clear(); generator.statements.clear();
for (Instruction insn : generator.currentBlock.getInstructions()) { for (Instruction insn : generator.currentBlock.getInstructions()) {
@ -200,7 +197,9 @@ public class Decompiler {
RegularMethodNode methodNode = new RegularMethodNode(reference); RegularMethodNode methodNode = new RegularMethodNode(reference);
methodNode.getModifiers().addAll(mapModifiers(method.getModifiers())); methodNode.getModifiers().addAll(mapModifiers(method.getModifiers()));
methodNode.setBody(result); 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 optimizer = new Optimizer();
optimizer.optimize(methodNode); optimizer.optimize(methodNode);
return methodNode; return methodNode;

View File

@ -112,6 +112,7 @@ public class JavascriptBuilder {
Decompiler decompiler = new Decompiler(classSet, classLoader); Decompiler decompiler = new Decompiler(classSet, classLoader);
ClassSetOptimizer optimizer = new ClassSetOptimizer(); ClassSetOptimizer optimizer = new ClassSetOptimizer();
optimizer.optimizeAll(classSet); optimizer.optimizeAll(classSet);
allocateRegisters(classSet);
if (bytecodeLogging) { if (bytecodeLogging) {
try { try {
logBytecode(new PrintWriter(new OutputStreamWriter(logStream, "UTF-8")), classSet); 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) { private void logBytecode(PrintWriter writer, ListableClassHolderSource classes) {
for (String className : classes.getClassNames()) { for (String className : classes.getClassNames()) {
ClassHolder classHolder = classes.getClassHolder(className); ClassHolder classHolder = classes.getClassHolder(className);
@ -161,14 +174,13 @@ public class JavascriptBuilder {
printType(writer, parameterTypes[i]); printType(writer, parameterTypes[i]);
} }
writer.println(")"); writer.println(")");
if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) { Program program = method.getProgram();
if (program != null && program.basicBlockCount() > 0) {
ListingBuilder builder = new ListingBuilder(); ListingBuilder builder = new ListingBuilder();
RegisterAllocator allocator = new RegisterAllocator(); writer.print(builder.buildListing(program, " "));
int[] colors = allocator.allocateRegisters(method);
writer.print(builder.buildListing(method.getProgram(), " "));
writer.print(" Register allocation:"); writer.print(" Register allocation:");
for (int i = 0; i < colors.length; ++i) { for (int i = 0; i < program.variableCount(); ++i) {
writer.print(i + ":" + colors[i] + " "); writer.print(i + ":" + program.variableAt(i).getRegister() + " ");
} }
writer.println(); writer.println();
writer.println(); writer.println();

View File

@ -34,14 +34,17 @@ public class Optimizer {
} }
public void optimize(RegularMethodNode method) { public void optimize(RegularMethodNode method) {
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariableCount()); ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
method.getBody().acceptVisitor(stats); method.getBody().acceptVisitor(stats);
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);
int paramCount = method.getReference().parameterCount(); int paramCount = method.getReference().parameterCount();
UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariableCount()); UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariables());
method.getBody().acceptVisitor(unusedEliminator); 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);
}
} }
} }

View File

@ -271,16 +271,8 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
} else { } else {
statement.getRightValue().acceptVisitor(this); statement.getRightValue().acceptVisitor(this);
Expr right = resultExpr; Expr right = resultExpr;
Expr left; Expr left = statement.getLeftValue();
if (statement.getLeftValue() instanceof VariableExpr) { 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 {
statement.getLeftValue().acceptVisitor(this); statement.getLeftValue().acceptVisitor(this);
left = resultExpr; left = resultExpr;
} }

View File

@ -332,7 +332,10 @@ public class Renderer implements ExprVisitor, StatementVisitor {
public void visit(RegularMethodNode method) { public void visit(RegularMethodNode method) {
try { try {
MethodReference ref = method.getReference(); 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; boolean hasVars = variableCount > ref.parameterCount() + 1;
if (hasVars) { if (hasVars) {
writer.append("var "); writer.append("var ");

View File

@ -578,7 +578,7 @@ class StatementGenerator implements InstructionVisitor {
assign(castToInteger(Expr.binary(op, Expr.var(first), Expr.var(second))), result); 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) { if (nextBlock == target) {
return null; return null;
} }
@ -593,29 +593,8 @@ class StatementGenerator implements InstructionVisitor {
return contStmt; return contStmt;
} }
} }
private Statement generateJumpStatement(SwitchStatement stmt, int target) {
private Statement wrapWithPhis(Statement rawJump, BasicBlock target) { Statement body = generateJumpStatement(program.basicBlockAt(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));
if (body == null) { if (body == null) {
BreakStatement breakStmt = new BreakStatement(); BreakStatement breakStmt = new BreakStatement();
breakStmt.setTarget(stmt); breakStmt.setTarget(stmt);
@ -623,11 +602,6 @@ class StatementGenerator implements InstructionVisitor {
} }
return body; 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) { private void branch(Expr condition, BasicBlock consequentBlock, BasicBlock alternativeBlock) {
Statement consequent = generateJumpStatement(consequentBlock); Statement consequent = generateJumpStatement(consequentBlock);
Statement alternative = generateJumpStatement(alternativeBlock); Statement alternative = generateJumpStatement(alternativeBlock);

View File

@ -16,6 +16,7 @@
package org.teavm.javascript; package org.teavm.javascript;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import org.teavm.javascript.ast.*; import org.teavm.javascript.ast.*;
/** /**
@ -23,10 +24,18 @@ import org.teavm.javascript.ast.*;
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class UnusedVariableEliminator implements ExprVisitor, StatementVisitor { class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
int[] variables;
int[] indexes; int[] indexes;
int lastIndex; int lastIndex;
public UnusedVariableEliminator(int parameterCount, int variableCount) { public UnusedVariableEliminator(int parameterCount, List<Integer> 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]; indexes = new int[variableCount];
Arrays.fill(indexes, -1); Arrays.fill(indexes, -1);
for (int i = 0; i <= parameterCount; ++i) { for (int i = 0; i <= parameterCount; ++i) {
@ -109,10 +118,10 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
} }
private int renumber(int var) { private int renumber(int var) {
int index = indexes[var]; int index = indexes[variables[var]];
if (index == -1) { if (index == -1) {
index = lastIndex++; index = lastIndex++;
indexes[var] = index; indexes[variables[var]] = index;
} }
return index; return index;
} }

View File

@ -15,6 +15,8 @@
*/ */
package org.teavm.javascript.ast; package org.teavm.javascript.ast;
import java.util.ArrayList;
import java.util.List;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
/** /**
@ -23,7 +25,7 @@ import org.teavm.model.MethodReference;
*/ */
public class RegularMethodNode extends MethodNode { public class RegularMethodNode extends MethodNode {
private Statement body; private Statement body;
private int variableCount; private List<Integer> variables = new ArrayList<>();
public RegularMethodNode(MethodReference reference) { public RegularMethodNode(MethodReference reference) {
super(reference); super(reference);
@ -37,12 +39,8 @@ public class RegularMethodNode extends MethodNode {
this.body = body; this.body = body;
} }
public int getVariableCount() { public List<Integer> getVariables() {
return variableCount; return variables;
}
public void setVariableCount(int variableCount) {
this.variableCount = variableCount;
} }
@Override @Override

View File

@ -27,6 +27,7 @@ public class Program {
private List<Variable> variables = new ArrayList<>(); private List<Variable> variables = new ArrayList<>();
private MethodHolder method; private MethodHolder method;
private boolean packed; private boolean packed;
private int lastUsedRegister;
public BasicBlock createBasicBlock() { public BasicBlock createBasicBlock() {
BasicBlock block = new BasicBlock(this, basicBlocks.size()); BasicBlock block = new BasicBlock(this, basicBlocks.size());
@ -38,6 +39,7 @@ public class Program {
Variable variable = new Variable(this); Variable variable = new Variable(this);
variable.setIndex(variables.size()); variable.setIndex(variables.size());
variables.add(variable); variables.add(variable);
variable.setRegister(lastUsedRegister++);
return variable; return variable;
} }

View File

@ -22,6 +22,7 @@ package org.teavm.model;
public class Variable { public class Variable {
private Program program; private Program program;
private int index; private int index;
private int register;
Variable(Program program) { Variable(Program program) {
this.program = program; this.program = program;
@ -42,4 +43,12 @@ public class Variable {
void setProgram(Program program) { void setProgram(Program program) {
this.program = program; this.program = program;
} }
public int getRegister() {
return register;
}
public void setRegister(int register) {
this.register = register;
}
} }

View File

@ -28,7 +28,7 @@ import org.teavm.model.instructions.JumpInstruction;
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class RegisterAllocator { public class RegisterAllocator {
public int[] allocateRegisters(MethodHolder method) { public void allocateRegisters(MethodHolder method) {
Program program = method.getProgram(); Program program = method.getProgram();
List<PhiArgumentCopy> phiArgsCopies = insertPhiArgumentsCopies(program); List<PhiArgumentCopy> phiArgsCopies = insertPhiArgumentsCopies(program);
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder(); InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
@ -45,7 +45,9 @@ public class RegisterAllocator {
} }
GraphColorer colorer = new GraphColorer(); GraphColorer colorer = new GraphColorer();
colorer.colorize(interferenceGraph, classArray, colors); 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 { private static class PhiArgumentCopy {