Fix bugs in debugger

This commit is contained in:
Alexey Andreev 2018-12-19 19:28:35 +03:00
parent 75295f50e5
commit a4b61bac19
6 changed files with 79 additions and 47 deletions

View File

@ -46,6 +46,13 @@ public class Optimizer {
boolean[] preservedVars = new boolean[stats.writes.length];
BreakEliminator breakEliminator = new BreakEliminator();
breakEliminator.eliminate(method.getBody());
if (friendlyToDebugger) {
for (int i = 0; i < method.getVariables().size(); ++i) {
if (method.getVariables().get(i).getName() != null) {
preservedVars[i] = true;
}
}
}
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads,
moveConstants ? stats.constants : new Object[stats.constants.length], friendlyToDebugger);
method.getBody().acceptVisitor(optimizer);

View File

@ -54,9 +54,24 @@ public class Value {
type = jsValue.getClassName().then(className -> {
if (className.startsWith("a/")) {
className = className.substring(2);
String origClassName = className;
int degree = 0;
while (className.endsWith("[]")) {
className = className.substring(0, className.length() - 2);
++degree;
}
String javaClassName = debugInformation.getClassNameByJsName(className);
if (javaClassName != null) {
if (degree > 0) {
StringBuilder sb = new StringBuilder(javaClassName);
for (int i = 0; i < degree; ++i) {
sb.append("[]");
}
javaClassName = sb.toString();
}
className = javaClassName;
} else {
className = origClassName;
}
}
return className;
@ -68,35 +83,42 @@ public class Value {
public Promise<Map<String, Variable>> getProperties() {
if (properties == null) {
properties = jsValue.getProperties().thenAsync(jsVariables -> {
return jsValue.getClassName().then(className -> {
return getType().thenAsync(className -> {
if (!className.startsWith("@") && className.endsWith("[]") && jsVariables.containsKey("data")) {
return jsVariables.get("data").getValue().getProperties()
.then(arrayData -> fillArray(arrayData));
}
Map<String, Variable> vars = new HashMap<>();
for (Map.Entry<String, ? extends JavaScriptVariable> entry : jsVariables.entrySet()) {
JavaScriptVariable jsVar = entry.getValue();
String name;
if (className.endsWith("[]")) {
if (entry.getKey().equals("data")) {
name = entry.getKey();
} else {
continue;
}
} else if (isNumeric(entry.getKey())) {
name = entry.getKey();
} else {
name = debugger.mapField(className, entry.getKey());
if (name == null) {
continue;
}
name = debugger.mapField(className, entry.getKey());
if (name == null) {
continue;
}
Value value = new Value(debugger, debugInformation, jsVar.getValue());
vars.put(name, new Variable(name, value));
}
return vars;
return Promise.of(vars);
});
});
}
return properties;
}
private Map<String, Variable> fillArray(Map<String, ? extends JavaScriptVariable> jsVariables) {
Map<String, Variable> vars = new HashMap<>();
for (Map.Entry<String, ? extends JavaScriptVariable> entry : jsVariables.entrySet()) {
JavaScriptVariable jsVar = entry.getValue();
if (!isNumeric(entry.getKey())) {
continue;
}
Value value = new Value(debugger, debugInformation, jsVar.getValue());
vars.put(entry.getKey(), new Variable(entry.getKey(), value));
}
return vars;
}
public boolean hasInnerStructure() {
if (getType().equals("long")) {
return false;

View File

@ -30,6 +30,8 @@ import org.teavm.model.BasicBlock;
import org.teavm.model.Instruction;
import org.teavm.model.Program;
import org.teavm.model.TextLocation;
import org.teavm.model.instructions.EmptyInstruction;
import org.teavm.model.instructions.JumpInstruction;
class LocationGraphBuilder {
private Map<TextLocation, Set<TextLocation>> graphBuilder;
@ -44,7 +46,7 @@ class LocationGraphBuilder {
}
private void dfs(Graph graph, Program program) {
startLocations = new ArrayList<>(Collections.<Set<TextLocation>>nCopies(graph.size(), null));
startLocations = new ArrayList<>(Collections.nCopies(graph.size(), null));
additionalConnections = new ArrayList<>();
Deque<Step> stack = new ArrayDeque<>();
for (int i = 0; i < graph.size(); ++i) {
@ -69,6 +71,9 @@ class LocationGraphBuilder {
TextLocation location = step.location;
boolean started = false;
for (Instruction insn : block) {
if (insn instanceof JumpInstruction || insn instanceof EmptyInstruction) {
continue;
}
if (insn.getLocation() != null) {
if (!started) {
step.startLocations.add(insn.getLocation());

View File

@ -36,7 +36,7 @@ import org.teavm.model.instructions.AssignInstruction;
import org.teavm.model.instructions.JumpInstruction;
public class RegisterAllocator {
public void allocateRegisters(MethodReader method, Program program) {
public void allocateRegisters(MethodReader method, Program program, boolean debuggerFriendly) {
insertPhiArgumentsCopies(program);
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
LivenessAnalyzer liveness = new LivenessAnalyzer();
@ -61,7 +61,7 @@ public class RegisterAllocator {
maxClass = Math.max(maxClass, cls + 1);
}
int[] categories = getVariableCategories(program, method.getReference());
String[] names = getVariableNames(program);
String[] names = getVariableNames(program, debuggerFriendly);
colorer.colorize(MutableGraphNode.toGraph(interferenceGraph), colors, categories, names);
int maxColor = 0;
@ -100,10 +100,13 @@ public class RegisterAllocator {
return categories;
}
private String[] getVariableNames(ProgramReader program) {
private String[] getVariableNames(ProgramReader program, boolean debuggerFriendly) {
String[] names = new String[program.variableCount()];
for (int i = 0; i < names.length; ++i) {
names[i] = program.variableAt(i).getDebugName();
if (debuggerFriendly && names[i] == null) {
names[i] = "";
}
}
return names;
}
@ -231,14 +234,14 @@ public class RegisterAllocator {
}
}
private void renameVariables(final Program program, final int[] varMap) {
private void renameVariables(Program program, int[] varMap) {
InstructionVariableMapper mapper = new InstructionVariableMapper(var ->
program.variableAt(varMap[var.getIndex()]));
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
mapper.apply(block);
}
String[] originalNames = getVariableNames(program);
String[] originalNames = getVariableNames(program, false);
for (int i = 0; i < program.variableCount(); ++i) {
program.variableAt(i).setDebugName(null);
}

View File

@ -575,7 +575,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
target.afterOptimizations(optimizedProgram, method, classSource);
if (target.requiresRegisterAllocation()) {
RegisterAllocator allocator = new RegisterAllocator();
allocator.allocateRegisters(method, optimizedProgram);
allocator.allocateRegisters(method, optimizedProgram,
optimizationLevel == TeaVMOptimizationLevel.SIMPLE);
}
}

View File

@ -63,32 +63,26 @@ public class TeaVMValue extends XNamedValue {
if (charactersProperty == null) {
return errorString();
}
return charactersProperty.getValue().getProperties().thenAsync(charsProperties -> {
Variable dataProperty = charsProperties.get("data");
if (dataProperty == null) {
return errorString();
}
return dataProperty.getValue().getProperties().thenAsync(dataValueProperties -> {
int[] indexes = dataValueProperties.keySet().stream()
.filter(t -> isDigits(t))
.mapToInt(Integer::parseInt)
.toArray();
int maxIndex = Math.min(Arrays.stream(indexes).max().orElse(-1) + 1, 256);
char[] chars = new char[maxIndex];
List<Promise<Void>> promises = new ArrayList<>();
for (int i = 0; i < maxIndex; ++i) {
Variable charProperty = dataValueProperties.get(Integer.toString(i));
if (charProperty != null) {
int index = i;
promises.add(charProperty.getValue().getRepresentation().thenVoid(charRepr -> {
if (isDigits(charRepr)) {
chars[index] = (char) Integer.parseInt(charRepr);
}
}));
}
return charactersProperty.getValue().getProperties().thenAsync(dataValueProperties -> {
int[] indexes = dataValueProperties.keySet().stream()
.filter(t -> isDigits(t))
.mapToInt(Integer::parseInt)
.toArray();
int maxIndex = Math.min(Arrays.stream(indexes).max().orElse(-1) + 1, 256);
char[] chars = new char[maxIndex];
List<Promise<Void>> promises = new ArrayList<>();
for (int i = 0; i < maxIndex; ++i) {
Variable charProperty = dataValueProperties.get(Integer.toString(i));
if (charProperty != null) {
int index = i;
promises.add(charProperty.getValue().getRepresentation().thenVoid(charRepr -> {
if (isDigits(charRepr)) {
chars[index] = (char) Integer.parseInt(charRepr);
}
}));
}
return Promise.allVoid(promises).thenAsync(v -> Promise.of(new String(chars)));
});
}
return Promise.allVoid(promises).thenAsync(v -> Promise.of(new String(chars)));
});
});
}