mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 07:54:11 -08:00
Fixes minor decompilation issues
This commit is contained in:
parent
0eb4e54e51
commit
94fe8a0acf
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user