From 94fe8a0acfa1dff8a7b9c8bfe7f509dd40858576 Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Mon, 27 Jan 2014 12:36:35 +0400 Subject: [PATCH] Fixes minor decompilation issues --- teavm-classlib/pom.xml | 2 +- .../java/org/teavm/codegen/SourceWriter.java | 3 ++ .../java/org/teavm/javascript/Decompiler.java | 7 ++-- .../teavm/javascript/JavascriptBuilder.java | 24 ++++++++++---- .../java/org/teavm/javascript/Optimizer.java | 9 ++++-- .../teavm/javascript/OptimizingVisitor.java | 12 ++----- .../java/org/teavm/javascript/Renderer.java | 5 ++- .../teavm/javascript/StatementGenerator.java | 32 ++----------------- .../javascript/UnusedVariableEliminator.java | 15 +++++++-- .../javascript/ast/RegularMethodNode.java | 12 +++---- .../main/java/org/teavm/model/Program.java | 2 ++ .../main/java/org/teavm/model/Variable.java | 9 ++++++ .../teavm/model/util/RegisterAllocator.java | 6 ++-- 13 files changed, 72 insertions(+), 66 deletions(-) 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 {