mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fix bugs in debugger
This commit is contained in:
parent
75295f50e5
commit
a4b61bac19
|
@ -46,6 +46,13 @@ public class Optimizer {
|
||||||
boolean[] preservedVars = new boolean[stats.writes.length];
|
boolean[] preservedVars = new boolean[stats.writes.length];
|
||||||
BreakEliminator breakEliminator = new BreakEliminator();
|
BreakEliminator breakEliminator = new BreakEliminator();
|
||||||
breakEliminator.eliminate(method.getBody());
|
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,
|
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads,
|
||||||
moveConstants ? stats.constants : new Object[stats.constants.length], friendlyToDebugger);
|
moveConstants ? stats.constants : new Object[stats.constants.length], friendlyToDebugger);
|
||||||
method.getBody().acceptVisitor(optimizer);
|
method.getBody().acceptVisitor(optimizer);
|
||||||
|
|
|
@ -54,9 +54,24 @@ public class Value {
|
||||||
type = jsValue.getClassName().then(className -> {
|
type = jsValue.getClassName().then(className -> {
|
||||||
if (className.startsWith("a/")) {
|
if (className.startsWith("a/")) {
|
||||||
className = className.substring(2);
|
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);
|
String javaClassName = debugInformation.getClassNameByJsName(className);
|
||||||
if (javaClassName != null) {
|
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;
|
className = javaClassName;
|
||||||
|
} else {
|
||||||
|
className = origClassName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return className;
|
return className;
|
||||||
|
@ -68,35 +83,42 @@ public class Value {
|
||||||
public Promise<Map<String, Variable>> getProperties() {
|
public Promise<Map<String, Variable>> getProperties() {
|
||||||
if (properties == null) {
|
if (properties == null) {
|
||||||
properties = jsValue.getProperties().thenAsync(jsVariables -> {
|
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<>();
|
Map<String, Variable> vars = new HashMap<>();
|
||||||
for (Map.Entry<String, ? extends JavaScriptVariable> entry : jsVariables.entrySet()) {
|
for (Map.Entry<String, ? extends JavaScriptVariable> entry : jsVariables.entrySet()) {
|
||||||
JavaScriptVariable jsVar = entry.getValue();
|
JavaScriptVariable jsVar = entry.getValue();
|
||||||
String name;
|
String name;
|
||||||
if (className.endsWith("[]")) {
|
name = debugger.mapField(className, entry.getKey());
|
||||||
if (entry.getKey().equals("data")) {
|
if (name == null) {
|
||||||
name = entry.getKey();
|
continue;
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (isNumeric(entry.getKey())) {
|
|
||||||
name = entry.getKey();
|
|
||||||
} else {
|
|
||||||
name = debugger.mapField(className, entry.getKey());
|
|
||||||
if (name == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Value value = new Value(debugger, debugInformation, jsVar.getValue());
|
Value value = new Value(debugger, debugInformation, jsVar.getValue());
|
||||||
vars.put(name, new Variable(name, value));
|
vars.put(name, new Variable(name, value));
|
||||||
}
|
}
|
||||||
return vars;
|
return Promise.of(vars);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return properties;
|
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() {
|
public boolean hasInnerStructure() {
|
||||||
if (getType().equals("long")) {
|
if (getType().equals("long")) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -30,6 +30,8 @@ import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
|
import org.teavm.model.instructions.EmptyInstruction;
|
||||||
|
import org.teavm.model.instructions.JumpInstruction;
|
||||||
|
|
||||||
class LocationGraphBuilder {
|
class LocationGraphBuilder {
|
||||||
private Map<TextLocation, Set<TextLocation>> graphBuilder;
|
private Map<TextLocation, Set<TextLocation>> graphBuilder;
|
||||||
|
@ -44,7 +46,7 @@ class LocationGraphBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dfs(Graph graph, Program program) {
|
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<>();
|
additionalConnections = new ArrayList<>();
|
||||||
Deque<Step> stack = new ArrayDeque<>();
|
Deque<Step> stack = new ArrayDeque<>();
|
||||||
for (int i = 0; i < graph.size(); ++i) {
|
for (int i = 0; i < graph.size(); ++i) {
|
||||||
|
@ -69,6 +71,9 @@ class LocationGraphBuilder {
|
||||||
TextLocation location = step.location;
|
TextLocation location = step.location;
|
||||||
boolean started = false;
|
boolean started = false;
|
||||||
for (Instruction insn : block) {
|
for (Instruction insn : block) {
|
||||||
|
if (insn instanceof JumpInstruction || insn instanceof EmptyInstruction) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (insn.getLocation() != null) {
|
if (insn.getLocation() != null) {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
step.startLocations.add(insn.getLocation());
|
step.startLocations.add(insn.getLocation());
|
||||||
|
|
|
@ -36,7 +36,7 @@ import org.teavm.model.instructions.AssignInstruction;
|
||||||
import org.teavm.model.instructions.JumpInstruction;
|
import org.teavm.model.instructions.JumpInstruction;
|
||||||
|
|
||||||
public class RegisterAllocator {
|
public class RegisterAllocator {
|
||||||
public void allocateRegisters(MethodReader method, Program program) {
|
public void allocateRegisters(MethodReader method, Program program, boolean debuggerFriendly) {
|
||||||
insertPhiArgumentsCopies(program);
|
insertPhiArgumentsCopies(program);
|
||||||
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
||||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||||
|
@ -61,7 +61,7 @@ public class RegisterAllocator {
|
||||||
maxClass = Math.max(maxClass, cls + 1);
|
maxClass = Math.max(maxClass, cls + 1);
|
||||||
}
|
}
|
||||||
int[] categories = getVariableCategories(program, method.getReference());
|
int[] categories = getVariableCategories(program, method.getReference());
|
||||||
String[] names = getVariableNames(program);
|
String[] names = getVariableNames(program, debuggerFriendly);
|
||||||
colorer.colorize(MutableGraphNode.toGraph(interferenceGraph), colors, categories, names);
|
colorer.colorize(MutableGraphNode.toGraph(interferenceGraph), colors, categories, names);
|
||||||
|
|
||||||
int maxColor = 0;
|
int maxColor = 0;
|
||||||
|
@ -100,10 +100,13 @@ public class RegisterAllocator {
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] getVariableNames(ProgramReader program) {
|
private String[] getVariableNames(ProgramReader program, boolean debuggerFriendly) {
|
||||||
String[] names = new String[program.variableCount()];
|
String[] names = new String[program.variableCount()];
|
||||||
for (int i = 0; i < names.length; ++i) {
|
for (int i = 0; i < names.length; ++i) {
|
||||||
names[i] = program.variableAt(i).getDebugName();
|
names[i] = program.variableAt(i).getDebugName();
|
||||||
|
if (debuggerFriendly && names[i] == null) {
|
||||||
|
names[i] = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return names;
|
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 ->
|
InstructionVariableMapper mapper = new InstructionVariableMapper(var ->
|
||||||
program.variableAt(varMap[var.getIndex()]));
|
program.variableAt(varMap[var.getIndex()]));
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
mapper.apply(block);
|
mapper.apply(block);
|
||||||
}
|
}
|
||||||
String[] originalNames = getVariableNames(program);
|
String[] originalNames = getVariableNames(program, false);
|
||||||
for (int i = 0; i < program.variableCount(); ++i) {
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
program.variableAt(i).setDebugName(null);
|
program.variableAt(i).setDebugName(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -575,7 +575,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
target.afterOptimizations(optimizedProgram, method, classSource);
|
target.afterOptimizations(optimizedProgram, method, classSource);
|
||||||
if (target.requiresRegisterAllocation()) {
|
if (target.requiresRegisterAllocation()) {
|
||||||
RegisterAllocator allocator = new RegisterAllocator();
|
RegisterAllocator allocator = new RegisterAllocator();
|
||||||
allocator.allocateRegisters(method, optimizedProgram);
|
allocator.allocateRegisters(method, optimizedProgram,
|
||||||
|
optimizationLevel == TeaVMOptimizationLevel.SIMPLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,32 +63,26 @@ public class TeaVMValue extends XNamedValue {
|
||||||
if (charactersProperty == null) {
|
if (charactersProperty == null) {
|
||||||
return errorString();
|
return errorString();
|
||||||
}
|
}
|
||||||
return charactersProperty.getValue().getProperties().thenAsync(charsProperties -> {
|
return charactersProperty.getValue().getProperties().thenAsync(dataValueProperties -> {
|
||||||
Variable dataProperty = charsProperties.get("data");
|
int[] indexes = dataValueProperties.keySet().stream()
|
||||||
if (dataProperty == null) {
|
.filter(t -> isDigits(t))
|
||||||
return errorString();
|
.mapToInt(Integer::parseInt)
|
||||||
}
|
.toArray();
|
||||||
return dataProperty.getValue().getProperties().thenAsync(dataValueProperties -> {
|
int maxIndex = Math.min(Arrays.stream(indexes).max().orElse(-1) + 1, 256);
|
||||||
int[] indexes = dataValueProperties.keySet().stream()
|
char[] chars = new char[maxIndex];
|
||||||
.filter(t -> isDigits(t))
|
List<Promise<Void>> promises = new ArrayList<>();
|
||||||
.mapToInt(Integer::parseInt)
|
for (int i = 0; i < maxIndex; ++i) {
|
||||||
.toArray();
|
Variable charProperty = dataValueProperties.get(Integer.toString(i));
|
||||||
int maxIndex = Math.min(Arrays.stream(indexes).max().orElse(-1) + 1, 256);
|
if (charProperty != null) {
|
||||||
char[] chars = new char[maxIndex];
|
int index = i;
|
||||||
List<Promise<Void>> promises = new ArrayList<>();
|
promises.add(charProperty.getValue().getRepresentation().thenVoid(charRepr -> {
|
||||||
for (int i = 0; i < maxIndex; ++i) {
|
if (isDigits(charRepr)) {
|
||||||
Variable charProperty = dataValueProperties.get(Integer.toString(i));
|
chars[index] = (char) Integer.parseInt(charRepr);
|
||||||
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)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user