Propagating variable name via compiler's pipeline

This commit is contained in:
Alexey Andreev 2016-08-25 23:36:28 +03:00
parent c5c453d95b
commit 1c1b0c69fa
29 changed files with 202 additions and 187 deletions

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -42,5 +42,5 @@ public abstract class MethodNode {
public abstract boolean isAsync();
public abstract List<Set<String>> getParameterDebugNames();
public abstract List<VariableNode> getVariables();
}

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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) {

View File

@ -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(")");

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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');
}

View File

@ -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());
}
}
}

View File

@ -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();

View File

@ -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]);
}
}

View File

@ -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) {

View 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
}

View File

@ -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);

View File

@ -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) {

View File

@ -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) {