mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Propagating variable name via compiler's pipeline
This commit is contained in:
parent
c5c453d95b
commit
1c1b0c69fa
|
@ -49,7 +49,7 @@ public final class TArray extends TObject {
|
|||
|
||||
@SuppressWarnings("unused")
|
||||
private static RuntimeObject newInstanceLowLevel(RuntimeClass cls, int length) {
|
||||
return Allocator.allocateArray(cls, length).toStructure();
|
||||
return Allocator.allocateArray(cls.arrayType, length).toStructure();
|
||||
}
|
||||
|
||||
public static TObject get(TObject array, int index) throws TIllegalArgumentException,
|
||||
|
|
|
@ -15,15 +15,12 @@
|
|||
*/
|
||||
package org.teavm.ast;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.teavm.model.TextLocation;
|
||||
|
||||
public class AssignmentStatement extends Statement {
|
||||
private Expr leftValue;
|
||||
private Expr rightValue;
|
||||
private TextLocation location;
|
||||
private Set<String> debugNames = new HashSet<>();
|
||||
private boolean async;
|
||||
|
||||
public Expr getLeftValue() {
|
||||
|
@ -50,10 +47,6 @@ public class AssignmentStatement extends Statement {
|
|||
this.location = location;
|
||||
}
|
||||
|
||||
public Set<String> getDebugNames() {
|
||||
return debugNames;
|
||||
}
|
||||
|
||||
public boolean isAsync() {
|
||||
return async;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@ package org.teavm.ast;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public class AsyncMethodNode extends MethodNode {
|
||||
|
@ -33,19 +31,11 @@ public class AsyncMethodNode extends MethodNode {
|
|||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VariableNode> getVariables() {
|
||||
return variables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Set<String>> getParameterDebugNames() {
|
||||
return variables.subList(0, getReference().parameterCount())
|
||||
.stream()
|
||||
.map(VariableNode::getDebugNames)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(MethodNodeVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
|
|
|
@ -42,5 +42,5 @@ public abstract class MethodNode {
|
|||
|
||||
public abstract boolean isAsync();
|
||||
|
||||
public abstract List<Set<String>> getParameterDebugNames();
|
||||
public abstract List<VariableNode> getVariables();
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ package org.teavm.ast;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
|
@ -52,7 +51,7 @@ public class NativeMethodNode extends MethodNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Set<String>> getParameterDebugNames() {
|
||||
public List<VariableNode> getVariables() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@ package org.teavm.ast;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public class RegularMethodNode extends MethodNode {
|
||||
|
@ -37,18 +35,11 @@ public class RegularMethodNode extends MethodNode {
|
|||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VariableNode> getVariables() {
|
||||
return variables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Set<String>> getParameterDebugNames() {
|
||||
return variables.subList(0, getReference().parameterCount())
|
||||
.stream()
|
||||
.map(VariableNode::getDebugNames)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(MethodNodeVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
|
|
|
@ -15,14 +15,12 @@
|
|||
*/
|
||||
package org.teavm.ast;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.teavm.model.util.VariableType;
|
||||
|
||||
public class VariableNode {
|
||||
private int index;
|
||||
private VariableType type;
|
||||
private Set<String> debugNames = new HashSet<>();
|
||||
private String name;
|
||||
|
||||
public VariableNode(int index, VariableType type) {
|
||||
this.index = index;
|
||||
|
@ -45,7 +43,11 @@ public class VariableNode {
|
|||
this.type = type;
|
||||
}
|
||||
|
||||
public Set<String> getDebugNames() {
|
||||
return debugNames;
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ import org.teavm.model.Program;
|
|||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.util.AsyncProgramSplitter;
|
||||
import org.teavm.model.util.ListingBuilder;
|
||||
import org.teavm.model.util.ProgramUtils;
|
||||
|
@ -271,17 +270,14 @@ public class Decompiler {
|
|||
typeInferer.inferTypes(program, method.getReference());
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
VariableNode variable = new VariableNode(program.variableAt(i).getRegister(), typeInferer.typeOf(i));
|
||||
variable.setName(program.variableAt(i).getDebugName());
|
||||
methodNode.getVariables().add(variable);
|
||||
}
|
||||
|
||||
Optimizer optimizer = new Optimizer();
|
||||
optimizer.optimize(methodNode, method.getProgram());
|
||||
methodNode.getModifiers().addAll(method.getModifiers());
|
||||
int paramCount = Math.min(method.getSignature().length, program.variableCount());
|
||||
for (int i = 0; i < paramCount; ++i) {
|
||||
Variable var = program.variableAt(i);
|
||||
methodNode.getParameterDebugNames().add(new HashSet<>(var.getDebugNames()));
|
||||
}
|
||||
|
||||
return methodNode;
|
||||
}
|
||||
|
||||
|
@ -338,17 +334,14 @@ public class Decompiler {
|
|||
typeInferer.inferTypes(program, method.getReference());
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
VariableNode variable = new VariableNode(program.variableAt(i).getRegister(), typeInferer.typeOf(i));
|
||||
variable.setName(program.variableAt(i).getDebugName());
|
||||
node.getVariables().add(variable);
|
||||
}
|
||||
|
||||
Optimizer optimizer = new Optimizer();
|
||||
optimizer.optimize(node, splitter);
|
||||
node.getModifiers().addAll(method.getModifiers());
|
||||
int paramCount = Math.min(method.getSignature().length, program.variableCount());
|
||||
for (int i = 0; i < paramCount; ++i) {
|
||||
Variable var = program.variableAt(i);
|
||||
node.getParameterDebugNames().add(new HashSet<>(var.getDebugNames()));
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
|
@ -202,7 +202,6 @@ class StatementGenerator implements InstructionVisitor {
|
|||
public void visit(AssignInstruction insn) {
|
||||
AssignmentStatement stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()),
|
||||
Expr.var(insn.getAssignee().getIndex()));
|
||||
stmt.getDebugNames().addAll(insn.getReceiver().getDebugNames());
|
||||
stmt.setLocation(currentLocation);
|
||||
statements.add(stmt);
|
||||
}
|
||||
|
@ -500,7 +499,6 @@ class StatementGenerator implements InstructionVisitor {
|
|||
AssignmentStatement stmt;
|
||||
if (insn.getReceiver() != null) {
|
||||
stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), invocationExpr);
|
||||
stmt.getDebugNames().addAll(insn.getReceiver().getDebugNames());
|
||||
} else {
|
||||
stmt = Statement.assign(null, invocationExpr);
|
||||
}
|
||||
|
@ -523,7 +521,6 @@ class StatementGenerator implements InstructionVisitor {
|
|||
private void assign(Expr source, Variable target) {
|
||||
AssignmentStatement stmt = Statement.assign(Expr.var(target.getIndex()), source);
|
||||
stmt.setLocation(currentLocation);
|
||||
stmt.getDebugNames().addAll(target.getDebugNames());
|
||||
statements.add(stmt);
|
||||
}
|
||||
|
||||
|
|
|
@ -126,8 +126,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
private boolean async;
|
||||
private Precedence precedence;
|
||||
private final Map<String, String> blockIdMap = new HashMap<>();
|
||||
private final List<Set<String>> debugNames = new ArrayList<>();
|
||||
private final List<String> cachedVariableNames = new ArrayList<>();
|
||||
private MethodNode currentMethod;
|
||||
private boolean end;
|
||||
private int currentPart;
|
||||
private List<PostponedFieldInitializer> postponedFieldInitializers = new ArrayList<>();
|
||||
|
@ -652,9 +652,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
}
|
||||
|
||||
private void renderBody(MethodNode method, boolean inner) throws IOException {
|
||||
debugNames.clear();
|
||||
currentMethod = method;
|
||||
cachedVariableNames.clear();
|
||||
debugNames.addAll(method.getParameterDebugNames());
|
||||
blockIdMap.clear();
|
||||
MethodReference ref = method.getReference();
|
||||
debugEmitter.emitMethod(ref.getDescriptor());
|
||||
|
@ -704,8 +703,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
Renderer.this.async = false;
|
||||
this.async = false;
|
||||
MethodReference ref = method.getReference();
|
||||
for (int i = 0; i < method.getParameterDebugNames().size(); ++i) {
|
||||
debugEmitter.emitVariable(method.getParameterDebugNames().get(i).toArray(new String[0]),
|
||||
for (int i = 0; i < method.getVariables().size(); ++i) {
|
||||
debugEmitter.emitVariable(new String[] { method.getVariables().get(i).getName() },
|
||||
variableName(i));
|
||||
}
|
||||
|
||||
|
@ -748,8 +747,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
Renderer.this.async = true;
|
||||
this.async = true;
|
||||
MethodReference ref = methodNode.getReference();
|
||||
for (int i = 0; i < methodNode.getParameterDebugNames().size(); ++i) {
|
||||
debugEmitter.emitVariable(methodNode.getParameterDebugNames().get(i).toArray(new String[0]),
|
||||
for (int i = 0; i < methodNode.getVariables().size(); ++i) {
|
||||
debugEmitter.emitVariable(new String[] { methodNode.getVariables().get(i).getName() },
|
||||
variableName(i));
|
||||
}
|
||||
int variableCount = 0;
|
||||
|
@ -967,11 +966,6 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
if (statement.getLocation() != null) {
|
||||
popLocation();
|
||||
}
|
||||
if (statement.getLeftValue() instanceof VariableExpr) {
|
||||
VariableExpr receiver = (VariableExpr) statement.getLeftValue();
|
||||
debugEmitter.emitVariable(statement.getDebugNames().toArray(new String[0]),
|
||||
variableName(receiver.getIndex()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO error occurred", e);
|
||||
}
|
||||
|
@ -1258,7 +1252,6 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
return minifying ? "$t" : "$this";
|
||||
}
|
||||
|
||||
Set<String> names = index < debugNames.size() ? debugNames.get(index) : null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
--index;
|
||||
if (index < variableNames.length()) {
|
||||
|
@ -1267,11 +1260,13 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
sb.append(Character.toString(variableNames.charAt(index % variableNames.length()))
|
||||
+ index / variableNames.length());
|
||||
}
|
||||
if (!minifying && names != null && !names.isEmpty()) {
|
||||
List<String> nameList = new ArrayList<>(names);
|
||||
Collections.sort(nameList);
|
||||
for (String name : nameList) {
|
||||
sb.append('_').append(escapeName(name));
|
||||
if (!minifying) {
|
||||
VariableNode variable = index < currentMethod.getVariables().size()
|
||||
? currentMethod.getVariables().get(index)
|
||||
: null;
|
||||
if (variable != null && variable.getName() != null) {
|
||||
sb.setLength(0);
|
||||
sb.append(escapeName(variable.getName()));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
|
|
|
@ -65,7 +65,7 @@ public class WasmGenerator {
|
|||
WasmType type = variable.getType() != null
|
||||
? WasmGeneratorUtil.mapType(variable.getType())
|
||||
: WasmType.INT32;
|
||||
function.add(new WasmLocal(type));
|
||||
function.add(new WasmLocal(type, variable.getName()));
|
||||
}
|
||||
|
||||
for (int i = firstVariable; i <= methodReference.parameterCount(); ++i) {
|
||||
|
|
|
@ -182,12 +182,16 @@ public class WasmCRenderer {
|
|||
}
|
||||
sb.append(WasmCRenderingVisitor.mapType(function.getResult())).append(' ');
|
||||
sb.append(function.getName()).append("(");
|
||||
WasmCRenderingVisitor visitor = new WasmCRenderingVisitor(function.getResult(), function.getModule());
|
||||
for (int i = 0; i < function.getParameters().size(); ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(WasmCRenderingVisitor.mapType(function.getParameters().get(i)));
|
||||
sb.append(" var_" + i);
|
||||
WasmLocal local = i < function.getLocalVariables().size()
|
||||
? function.getLocalVariables().get(i)
|
||||
: null;
|
||||
sb.append(" ").append(local != null ? visitor.getVariableName(local) : "var_" + i);
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmLocal;
|
||||
import org.teavm.backend.wasm.model.WasmModule;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||
|
@ -303,7 +304,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(WasmGetLocal expression) {
|
||||
value = new CExpression("var_" + expression.getLocal().getIndex());
|
||||
value = new CExpression(getVariableName(expression.getLocal()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -313,7 +314,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
|||
expression.getValue().acceptVisitor(this);
|
||||
result.getLines().addAll(value.getLines());
|
||||
|
||||
result.addLine("var_" + expression.getLocal().getIndex() + " = " + value.getText() + ";",
|
||||
result.addLine(getVariableName(expression.getLocal()) + " = " + value.getText() + ";",
|
||||
expression.getLocation());
|
||||
|
||||
value = result;
|
||||
|
@ -1033,4 +1034,11 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
|||
String temporaryVariable;
|
||||
WasmType type;
|
||||
}
|
||||
|
||||
String getVariableName(WasmLocal local) {
|
||||
if (local.getName() != null) {
|
||||
return local.getName();
|
||||
}
|
||||
return "var_" + local.getIndex();
|
||||
}
|
||||
}
|
||||
|
|
51
core/src/main/java/org/teavm/cache/AstIO.java
vendored
51
core/src/main/java/org/teavm/cache/AstIO.java
vendored
|
@ -20,7 +20,6 @@ import java.io.DataOutput;
|
|||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -45,7 +44,6 @@ import org.teavm.ast.InitClassStatement;
|
|||
import org.teavm.ast.InstanceOfExpr;
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.ast.InvocationType;
|
||||
import org.teavm.ast.MethodNode;
|
||||
import org.teavm.ast.MonitorEnterStatement;
|
||||
import org.teavm.ast.MonitorExitStatement;
|
||||
import org.teavm.ast.NewArrayExpr;
|
||||
|
@ -99,7 +97,6 @@ public class AstIO {
|
|||
for (VariableNode var : method.getVariables()) {
|
||||
write(output, var);
|
||||
}
|
||||
output.writeShort(method.getParameterDebugNames().size());
|
||||
try {
|
||||
method.getBody().acceptVisitor(new NodeWriter(output));
|
||||
} catch (IOExceptionWrapper e) {
|
||||
|
@ -110,10 +107,7 @@ public class AstIO {
|
|||
private void write(DataOutput output, VariableNode variable) throws IOException {
|
||||
output.writeShort(variable.getIndex());
|
||||
output.writeByte(variable.getType().ordinal());
|
||||
output.writeByte(variable.getDebugNames().size());
|
||||
for (String debugName : variable.getDebugNames()) {
|
||||
output.writeUTF(debugName);
|
||||
}
|
||||
output.writeUTF(variable.getName() != null ? variable.getName() : "");
|
||||
}
|
||||
|
||||
public RegularMethodNode read(DataInput input, MethodReference method) throws IOException {
|
||||
|
@ -133,7 +127,10 @@ public class AstIO {
|
|||
VariableNode variable = new VariableNode(index, type);
|
||||
int nameCount = input.readByte();
|
||||
for (int i = 0; i < nameCount; ++i) {
|
||||
variable.getDebugNames().add(input.readUTF());
|
||||
variable.setName(input.readUTF());
|
||||
if (variable.getName().isEmpty()) {
|
||||
variable.setName(null);
|
||||
}
|
||||
}
|
||||
return variable;
|
||||
}
|
||||
|
@ -144,8 +141,6 @@ public class AstIO {
|
|||
for (VariableNode var : method.getVariables()) {
|
||||
write(output, var);
|
||||
}
|
||||
output.writeShort(method.getParameterDebugNames().size());
|
||||
writeParameters(output, method);
|
||||
try {
|
||||
output.writeShort(method.getBody().size());
|
||||
for (int i = 0; i < method.getBody().size(); ++i) {
|
||||
|
@ -156,17 +151,6 @@ public class AstIO {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeParameters(DataOutput output, MethodNode method) throws IOException {
|
||||
for (Set<String> debugNames : method.getParameterDebugNames()) {
|
||||
output.writeShort(debugNames != null ? debugNames.size() : 0);
|
||||
if (debugNames != null) {
|
||||
for (String debugName : debugNames) {
|
||||
output.writeUTF(debugName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AsyncMethodNode readAsync(DataInput input, MethodReference method) throws IOException {
|
||||
AsyncMethodNode node = new AsyncMethodNode(method);
|
||||
node.getModifiers().addAll(unpackModifiers(input.readInt()));
|
||||
|
@ -174,7 +158,6 @@ public class AstIO {
|
|||
for (int i = 0; i < varCount; ++i) {
|
||||
node.getVariables().add(readVariable(input));
|
||||
}
|
||||
readParameters(input, node);
|
||||
int partCount = input.readShort();
|
||||
for (int i = 0; i < partCount; ++i) {
|
||||
AsyncMethodPart part = new AsyncMethodPart();
|
||||
|
@ -184,18 +167,6 @@ public class AstIO {
|
|||
return node;
|
||||
}
|
||||
|
||||
private void readParameters(DataInput input, MethodNode node) throws IOException {
|
||||
int paramDebugNameCount = input.readShort();
|
||||
for (int i = 0; i < paramDebugNameCount; ++i) {
|
||||
int debugNameCount = input.readShort();
|
||||
Set<String> debugNames = new HashSet<>();
|
||||
for (int j = 0; j < debugNameCount; ++j) {
|
||||
debugNames.add(input.readUTF());
|
||||
}
|
||||
node.getParameterDebugNames().add(debugNames);
|
||||
}
|
||||
}
|
||||
|
||||
private int packModifiers(Set<ElementModifier> modifiers) {
|
||||
int packed = 0;
|
||||
for (ElementModifier modifier : modifiers) {
|
||||
|
@ -257,10 +228,6 @@ public class AstIO {
|
|||
try {
|
||||
output.writeByte(statement.getLeftValue() != null ? 0 : 1);
|
||||
writeLocation(statement.getLocation());
|
||||
output.writeShort(statement.getDebugNames().size());
|
||||
for (String name : statement.getDebugNames()) {
|
||||
output.writeUTF(name);
|
||||
}
|
||||
if (statement.getLeftValue() != null) {
|
||||
writeExpr(statement.getLeftValue());
|
||||
}
|
||||
|
@ -674,10 +641,6 @@ public class AstIO {
|
|||
case 0: {
|
||||
AssignmentStatement stmt = new AssignmentStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
int debugNameCount = input.readShort();
|
||||
for (int i = 0; i < debugNameCount; ++i) {
|
||||
stmt.getDebugNames().add(input.readUTF());
|
||||
}
|
||||
stmt.setLeftValue(readExpr(input));
|
||||
stmt.setRightValue(readExpr(input));
|
||||
stmt.setAsync(input.readBoolean());
|
||||
|
@ -686,10 +649,6 @@ public class AstIO {
|
|||
case 1: {
|
||||
AssignmentStatement stmt = new AssignmentStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
int debugNameCount = input.readShort();
|
||||
for (int i = 0; i < debugNameCount; ++i) {
|
||||
stmt.getDebugNames().add(input.readUTF());
|
||||
}
|
||||
stmt.setRightValue(readExpr(input));
|
||||
stmt.setAsync(input.readBoolean());
|
||||
return stmt;
|
||||
|
|
|
@ -43,10 +43,7 @@ public class ProgramIO {
|
|||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
Variable var = program.variableAt(i);
|
||||
data.writeShort(var.getRegister());
|
||||
data.writeShort(var.getDebugNames().size());
|
||||
for (String debugString : var.getDebugNames()) {
|
||||
data.writeUTF(debugString);
|
||||
}
|
||||
data.writeUTF(var.getDebugName() != null ? var.getDebugName() : "");
|
||||
}
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlock basicBlock = program.basicBlockAt(i);
|
||||
|
@ -106,9 +103,9 @@ public class ProgramIO {
|
|||
for (int i = 0; i < varCount; ++i) {
|
||||
Variable var = program.createVariable();
|
||||
var.setRegister(data.readShort());
|
||||
int debugNameCount = data.readShort();
|
||||
for (int j = 0; j < debugNameCount; ++j) {
|
||||
var.getDebugNames().add(data.readUTF());
|
||||
var.setDebugName(data.readUTF());
|
||||
if (var.getDebugName().isEmpty()) {
|
||||
var.setDebugName(null);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < basicBlockCount; ++i) {
|
||||
|
|
|
@ -15,19 +15,14 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Variable implements VariableReader {
|
||||
private Program program;
|
||||
private int index;
|
||||
private int register;
|
||||
private Set<String> debugNames;
|
||||
private String debugName;
|
||||
|
||||
Variable(Program program) {
|
||||
this.program = program;
|
||||
this.debugNames = new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,12 +52,12 @@ public class Variable implements VariableReader {
|
|||
this.register = register;
|
||||
}
|
||||
|
||||
public Set<String> getDebugNames() {
|
||||
return debugNames;
|
||||
@Override
|
||||
public String getDebugName() {
|
||||
return debugName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> readDebugNames() {
|
||||
return Collections.unmodifiableSet(debugNames);
|
||||
public void setDebugName(String debugName) {
|
||||
this.debugName = debugName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,18 +15,12 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface VariableReader {
|
||||
int getIndex();
|
||||
|
||||
ProgramReader getProgram();
|
||||
|
||||
Set<String> readDebugNames();
|
||||
String getDebugName();
|
||||
|
||||
int getRegister();
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
if (map[i] != i) {
|
||||
Variable var = program.variableAt(i);
|
||||
Variable mapVar = program.variableAt(map[i]);
|
||||
mapVar.getDebugNames().addAll(var.getDebugNames());
|
||||
mapVar.setDebugName(var.getDebugName());
|
||||
program.deleteVariable(i);
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +165,12 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
}
|
||||
|
||||
private void bind(int var, String value) {
|
||||
KnownValue known = knownValues.get(value);
|
||||
String name = program.variableAt(var).getDebugName();
|
||||
if (name == null) {
|
||||
name = "";
|
||||
}
|
||||
|
||||
KnownValue known = knownValues.get(name + ":" + value);
|
||||
if (known != null && domTree.dominates(known.location, currentBlockIndex) && known.value != var) {
|
||||
eliminate = true;
|
||||
map[var] = known.value;
|
||||
|
@ -173,7 +178,7 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
known = new KnownValue();
|
||||
known.location = currentBlockIndex;
|
||||
known.value = var;
|
||||
knownValues.put(value, known);
|
||||
knownValues.put(name + ":" + value, known);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
|||
@Override
|
||||
public void visit(ClassConstantInstruction insn) {
|
||||
var = program.createVariable();
|
||||
var.getDebugNames().addAll(insn.getReceiver().getDebugNames());
|
||||
var.setDebugName(insn.getReceiver().getDebugName());
|
||||
ClassConstantInstruction copy = new ClassConstantInstruction();
|
||||
copy.setConstant(insn.getConstant());
|
||||
copy.setReceiver(var);
|
||||
|
@ -235,7 +235,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
|||
@Override
|
||||
public void visit(NullConstantInstruction insn) {
|
||||
var = program.createVariable();
|
||||
var.getDebugNames().addAll(insn.getReceiver().getDebugNames());
|
||||
var.setDebugName(insn.getReceiver().getDebugName());
|
||||
NullConstantInstruction copy = new NullConstantInstruction();
|
||||
copy.setReceiver(var);
|
||||
this.copy = copy;
|
||||
|
@ -244,7 +244,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
|||
@Override
|
||||
public void visit(IntegerConstantInstruction insn) {
|
||||
var = program.createVariable();
|
||||
var.getDebugNames().addAll(insn.getReceiver().getDebugNames());
|
||||
var.setDebugName(insn.getReceiver().getDebugName());
|
||||
IntegerConstantInstruction copy = new IntegerConstantInstruction();
|
||||
copy.setConstant(insn.getConstant());
|
||||
copy.setReceiver(var);
|
||||
|
@ -254,7 +254,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
|||
@Override
|
||||
public void visit(LongConstantInstruction insn) {
|
||||
var = program.createVariable();
|
||||
var.getDebugNames().addAll(insn.getReceiver().getDebugNames());
|
||||
var.setDebugName(insn.getReceiver().getDebugName());
|
||||
LongConstantInstruction copy = new LongConstantInstruction();
|
||||
copy.setConstant(insn.getConstant());
|
||||
copy.setReceiver(var);
|
||||
|
@ -264,7 +264,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
|||
@Override
|
||||
public void visit(FloatConstantInstruction insn) {
|
||||
var = program.createVariable();
|
||||
var.getDebugNames().addAll(insn.getReceiver().getDebugNames());
|
||||
var.setDebugName(insn.getReceiver().getDebugName());
|
||||
FloatConstantInstruction copy = new FloatConstantInstruction();
|
||||
copy.setConstant(insn.getConstant());
|
||||
copy.setReceiver(var);
|
||||
|
@ -274,7 +274,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
|||
@Override
|
||||
public void visit(DoubleConstantInstruction insn) {
|
||||
var = program.createVariable();
|
||||
var.getDebugNames().addAll(insn.getReceiver().getDebugNames());
|
||||
var.setDebugName(insn.getReceiver().getDebugName());
|
||||
DoubleConstantInstruction copy = new DoubleConstantInstruction();
|
||||
copy.setConstant(insn.getConstant());
|
||||
copy.setReceiver(var);
|
||||
|
@ -284,7 +284,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
|||
@Override
|
||||
public void visit(StringConstantInstruction insn) {
|
||||
var = program.createVariable();
|
||||
var.getDebugNames().addAll(insn.getReceiver().getDebugNames());
|
||||
var.setDebugName(insn.getReceiver().getDebugName());
|
||||
StringConstantInstruction copy = new StringConstantInstruction();
|
||||
copy.setConstant(insn.getConstant());
|
||||
copy.setReceiver(var);
|
||||
|
|
|
@ -193,7 +193,7 @@ public class AsyncProgramSplitter {
|
|||
copy.createVariable();
|
||||
Variable varCopy = copy.variableAt(i);
|
||||
varCopy.setRegister(var.getRegister());
|
||||
varCopy.getDebugNames().addAll(var.getDebugNames());
|
||||
varCopy.setDebugName(var.getDebugName());
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
|
|
@ -28,16 +28,8 @@ public class ListingBuilder {
|
|||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
sb.append(prefix).append("var @").append(i);
|
||||
VariableReader var = program.variableAt(i);
|
||||
if (var != null && !var.readDebugNames().isEmpty()) {
|
||||
sb.append(" as ");
|
||||
boolean first = true;
|
||||
for (String debugName : var.readDebugNames()) {
|
||||
if (!first) {
|
||||
sb.append(", ");
|
||||
}
|
||||
first = false;
|
||||
sb.append(debugName);
|
||||
}
|
||||
if (var != null && var.getDebugName() != null) {
|
||||
sb.append(" as ").append(var.getDebugName());
|
||||
}
|
||||
sb.append('\n');
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@ public class PhiUpdater {
|
|||
|
||||
for (Phi phi : synthesizedPhis.get(index)) {
|
||||
Variable var = program.createVariable();
|
||||
var.getDebugNames().addAll(phi.getReceiver().getDebugNames());
|
||||
var.setDebugName(phi.getReceiver().getDebugName());
|
||||
variableMap[phi.getReceiver().getIndex()] = var;
|
||||
phi.setReceiver(var);
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ public class PhiUpdater {
|
|||
incoming.setSource(currentBlock);
|
||||
incoming.setValue(var);
|
||||
phi.getIncomings().add(incoming);
|
||||
phi.getReceiver().getDebugNames().addAll(var.getDebugNames());
|
||||
phi.getReceiver().setDebugName(var.getDebugName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public final class ProgramUtils {
|
|||
Program copy = new Program();
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
Variable var = copy.createVariable();
|
||||
var.getDebugNames().addAll(program.variableAt(i).readDebugNames());
|
||||
var.setDebugName(program.variableAt(i).getDebugName());
|
||||
}
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
copy.createBasicBlock();
|
||||
|
|
|
@ -257,14 +257,13 @@ public class RegisterAllocator {
|
|||
BasicBlock block = program.basicBlockAt(i);
|
||||
mapper.apply(block);
|
||||
}
|
||||
String[][] originalNames = new String[program.variableCount()][];
|
||||
String[] originalNames = new String[program.variableCount()];
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
Variable var = program.variableAt(i);
|
||||
originalNames[i] = var.getDebugNames().toArray(new String[0]);
|
||||
var.getDebugNames().clear();
|
||||
originalNames[i] = var.getDebugName();
|
||||
}
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
program.variableAt(varMap[i]).getDebugNames().addAll(Arrays.asList(originalNames[i]));
|
||||
program.variableAt(varMap[i]).setDebugName(originalNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -113,6 +114,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
private final Properties properties = new Properties();
|
||||
private ProgramCache programCache;
|
||||
private boolean incremental;
|
||||
private TeaVMOptimizationLevel optimizationLevel = TeaVMOptimizationLevel.SIMPLE;
|
||||
private TeaVMProgressListener progressListener;
|
||||
private boolean cancelled;
|
||||
private ListableClassHolderSource writtenClasses;
|
||||
|
@ -202,6 +204,14 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
this.incremental = incremental;
|
||||
}
|
||||
|
||||
public TeaVMOptimizationLevel getOptimizationLevel() {
|
||||
return optimizationLevel;
|
||||
}
|
||||
|
||||
public void setOptimizationLevel(TeaVMOptimizationLevel optimizationLevel) {
|
||||
this.optimizationLevel = optimizationLevel;
|
||||
}
|
||||
|
||||
public TeaVMProgressListener getProgressListener() {
|
||||
return progressListener;
|
||||
}
|
||||
|
@ -359,12 +369,13 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
return;
|
||||
}
|
||||
|
||||
//inline(classSet);
|
||||
inline(classSet);
|
||||
if (wasCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
removeDebugNames(classSet);
|
||||
optimize(classSet);
|
||||
if (wasCancelled()) {
|
||||
return;
|
||||
|
@ -423,10 +434,13 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
}
|
||||
|
||||
private void inline(ListableClassHolderSource classes) {
|
||||
if (optimizationLevel != TeaVMOptimizationLevel.FULL) {
|
||||
return;
|
||||
}
|
||||
Inlining inlining = new Inlining();
|
||||
for (String className : classes.getClassNames()) {
|
||||
ClassHolder cls = classes.get(className);
|
||||
for (final MethodHolder method : cls.getMethods()) {
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
if (method.getProgram() != null) {
|
||||
inlining.apply(method.getProgram(), classes);
|
||||
}
|
||||
|
@ -437,6 +451,25 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
}
|
||||
}
|
||||
|
||||
private void removeDebugNames(ListableClassHolderSource classes) {
|
||||
if (optimizationLevel == TeaVMOptimizationLevel.SIMPLE) {
|
||||
return;
|
||||
}
|
||||
for (String className : classes.getClassNames()) {
|
||||
ClassHolder cls = classes.get(className);
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
if (method.getProgram() != null) {
|
||||
for (int i = 0; i < method.getProgram().variableCount(); ++i) {
|
||||
method.getProgram().variableAt(i).setDebugName(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wasCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void optimize(ListableClassHolderSource classSource) {
|
||||
for (String className : classSource.getClassNames()) {
|
||||
ClassHolder cls = classSource.get(className);
|
||||
|
@ -481,17 +514,22 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
}
|
||||
|
||||
private List<MethodOptimization> getOptimizations() {
|
||||
return Arrays.asList(
|
||||
new RedundantJumpElimination(),
|
||||
new ArrayUnwrapMotion(),
|
||||
new LoopInversion(),
|
||||
new LoopInvariantMotion(),
|
||||
new GlobalValueNumbering(),
|
||||
new ConstantConditionElimination(),
|
||||
new RedundantJumpElimination(),
|
||||
new UnusedVariableElimination(),
|
||||
new ClassInitElimination(),
|
||||
new UnreachableBasicBlockElimination());
|
||||
List<MethodOptimization> optimizations = new ArrayList<>();
|
||||
optimizations.add(new RedundantJumpElimination());
|
||||
optimizations.add(new ArrayUnwrapMotion());
|
||||
if (optimizationLevel.ordinal() >= TeaVMOptimizationLevel.ADVANCED.ordinal()) {
|
||||
optimizations.add(new LoopInversion());
|
||||
optimizations.add(new LoopInvariantMotion());
|
||||
}
|
||||
optimizations.add(new GlobalValueNumbering());
|
||||
if (optimizationLevel.ordinal() >= TeaVMOptimizationLevel.ADVANCED.ordinal()) {
|
||||
optimizations.add(new ConstantConditionElimination());
|
||||
optimizations.add(new RedundantJumpElimination());
|
||||
optimizations.add(new UnusedVariableElimination());
|
||||
}
|
||||
optimizations.add(new ClassInitElimination());
|
||||
optimizations.add(new UnreachableBasicBlockElimination());
|
||||
return optimizations;
|
||||
}
|
||||
|
||||
public void build(File dir, String fileName) {
|
||||
|
|
22
core/src/main/java/org/teavm/vm/TeaVMOptimizationLevel.java
Normal file
22
core/src/main/java/org/teavm/vm/TeaVMOptimizationLevel.java
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2016 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.vm;
|
||||
|
||||
public enum TeaVMOptimizationLevel {
|
||||
SIMPLE,
|
||||
ADVANCED,
|
||||
FULL
|
||||
}
|
|
@ -170,8 +170,7 @@ class JSClassProcessor {
|
|||
InstructionVariableMapper variableMapper = new InstructionVariableMapper(var ->
|
||||
program.variableAt(var.getIndex() + 1));
|
||||
for (int i = program.variableCount() - 1; i > 0; --i) {
|
||||
program.variableAt(i).getDebugNames().addAll(program.variableAt(i - 1).getDebugNames());
|
||||
program.variableAt(i - 1).getDebugNames().clear();
|
||||
program.variableAt(i).setDebugName(program.variableAt(i - 1).getDebugName());
|
||||
}
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlock block = program.basicBlockAt(i);
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.teavm.tooling.RuntimeCopyOperation;
|
|||
import org.teavm.tooling.TeaVMTargetType;
|
||||
import org.teavm.tooling.TeaVMTool;
|
||||
import org.teavm.tooling.TeaVMToolException;
|
||||
import org.teavm.vm.TeaVMOptimizationLevel;
|
||||
import org.teavm.vm.TeaVMPhase;
|
||||
import org.teavm.vm.TeaVMProgressFeedback;
|
||||
import org.teavm.vm.TeaVMProgressListener;
|
||||
|
@ -61,6 +62,9 @@ public final class TeaVMRunner {
|
|||
.withDescription("causes TeaVM to generate minimized JavaScript file")
|
||||
.withLongOpt("minify")
|
||||
.create("m"));
|
||||
options.addOption(OptionBuilder
|
||||
.withDescription("optimization level (1-3)")
|
||||
.create("O"));
|
||||
options.addOption(OptionBuilder
|
||||
.withArgName("separate|merge|none")
|
||||
.hasArg()
|
||||
|
@ -160,6 +164,33 @@ public final class TeaVMRunner {
|
|||
if (commandLine.hasOption('D')) {
|
||||
tool.setDebugInformationGenerated(true);
|
||||
}
|
||||
|
||||
if (commandLine.hasOption("O")) {
|
||||
int level;
|
||||
try {
|
||||
level = Integer.parseInt(commandLine.getOptionValue("O"));
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.print("Wrong optimization level");
|
||||
printUsage(options);
|
||||
return;
|
||||
}
|
||||
switch (level) {
|
||||
case 1:
|
||||
tool.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
|
||||
break;
|
||||
case 2:
|
||||
tool.setOptimizationLevel(TeaVMOptimizationLevel.ADVANCED);
|
||||
break;
|
||||
case 3:
|
||||
tool.setOptimizationLevel(TeaVMOptimizationLevel.FULL);
|
||||
break;
|
||||
default:
|
||||
System.err.print("Wrong optimization level");
|
||||
printUsage(options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (commandLine.hasOption('S')) {
|
||||
tool.setSourceMapsFileGenerated(true);
|
||||
}
|
||||
|
@ -174,6 +205,7 @@ public final class TeaVMRunner {
|
|||
if (commandLine.hasOption('p')) {
|
||||
classPath = commandLine.getOptionValues('p');
|
||||
}
|
||||
|
||||
boolean interactive = commandLine.hasOption('w');
|
||||
args = commandLine.getArgs();
|
||||
if (args.length > 1) {
|
||||
|
|
|
@ -62,6 +62,7 @@ import org.teavm.vm.DirectoryBuildTarget;
|
|||
import org.teavm.vm.TeaVM;
|
||||
import org.teavm.vm.TeaVMBuilder;
|
||||
import org.teavm.vm.TeaVMEntryPoint;
|
||||
import org.teavm.vm.TeaVMOptimizationLevel;
|
||||
import org.teavm.vm.TeaVMProgressListener;
|
||||
import org.teavm.vm.TeaVMTarget;
|
||||
import org.teavm.vm.spi.AbstractRendererListener;
|
||||
|
@ -93,6 +94,7 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
private boolean cancelled;
|
||||
private TeaVMProgressListener progressListener;
|
||||
private TeaVM vm;
|
||||
private TeaVMOptimizationLevel optimizationLevel = TeaVMOptimizationLevel.SIMPLE;
|
||||
private List<SourceFileProvider> sourceFileProviders = new ArrayList<>();
|
||||
private DebugInformationBuilder debugEmitter;
|
||||
private JavaScriptTarget javaScriptTarget;
|
||||
|
@ -227,6 +229,14 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
public TeaVMOptimizationLevel getOptimizationLevel() {
|
||||
return optimizationLevel;
|
||||
}
|
||||
|
||||
public void setOptimizationLevel(TeaVMOptimizationLevel optimizationLevel) {
|
||||
this.optimizationLevel = optimizationLevel;
|
||||
}
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
@ -361,6 +371,7 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
vm.setProperties(properties);
|
||||
vm.setProgramCache(programCache);
|
||||
vm.setIncremental(incremental);
|
||||
vm.setOptimizationLevel(optimizationLevel);
|
||||
|
||||
vm.installPlugins();
|
||||
for (ClassHolderTransformer transformer : transformers) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user