mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 07:54:11 -08:00
Debug information construction
This commit is contained in:
parent
71415e71e1
commit
3b939d0853
|
@ -15,18 +15,26 @@
|
|||
*/
|
||||
package org.teavm.debugging;
|
||||
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class CallFrame {
|
||||
private SourceLocation location;
|
||||
private MethodReference method;
|
||||
|
||||
CallFrame(SourceLocation location) {
|
||||
CallFrame(SourceLocation location, MethodReference method) {
|
||||
this.location = location;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public SourceLocation getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public MethodReference getMethod() {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package org.teavm.debugging;
|
||||
|
||||
import java.util.*;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
|
@ -24,31 +23,31 @@ import org.teavm.model.MethodReference;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DebugInformation {
|
||||
List<String> fileNames = new ArrayList<>();
|
||||
Map<String, Integer> fileNameMap = new HashMap<>();
|
||||
List<String> classNames = new ArrayList<>();
|
||||
Map<String, Integer> classNameMap = new HashMap<>();
|
||||
List<MethodDescriptor> methods = new ArrayList<>();
|
||||
Map<MethodDescriptor, Integer> methodMap = new HashMap<>();
|
||||
List<FileDescription> fileDescriptions = new ArrayList<>();
|
||||
String[] fileNames;
|
||||
Map<String, Integer> fileNameMap;
|
||||
FileDescription[] fileDescriptions;
|
||||
// TODO: for less memory consumption replace with two arrays + custom binary search
|
||||
GeneratedLocation[] fileNameKeys;
|
||||
int[] fileNameValues;
|
||||
GeneratedLocation[] classKeys;
|
||||
int[] classValues;
|
||||
GeneratedLocation[] methodKeys;
|
||||
int[] methodValues;
|
||||
GeneratedLocation[] lineNumberKeys;
|
||||
int[] lineNumberValues;
|
||||
|
||||
public Collection<GeneratedLocation> getGeneratedLocations(String fileName, int lineNumber) {
|
||||
public Collection<GeneratedLocation> getGeneratedLocations(String fileName, int line) {
|
||||
Integer fileIndex = fileNameMap.get(fileName);
|
||||
if (fileIndex == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
FileDescription description = fileDescriptions.get(lineNumber);
|
||||
return lineNumber < description.generatedLocations.length ?
|
||||
Arrays.asList(description.generatedLocations[lineNumber]) :
|
||||
Collections.<GeneratedLocation>emptyList();
|
||||
FileDescription description = fileIndex >= 0 ? fileDescriptions[fileIndex] : null;
|
||||
if (description == null) {
|
||||
return null;
|
||||
}
|
||||
GeneratedLocation[] locations = line < description.generatedLocations.length ?
|
||||
description.generatedLocations[line] : null;
|
||||
return locations != null ? Arrays.asList(locations) : Collections.<GeneratedLocation>emptyList();
|
||||
}
|
||||
|
||||
public Collection<GeneratedLocation> getGeneratedLocations(SourceLocation sourceLocation) {
|
||||
return getGeneratedLocations(sourceLocation.getFileName(), sourceLocation.getLine());
|
||||
}
|
||||
|
||||
public SourceLocation getSourceLocation(int line, int column) {
|
||||
|
@ -57,18 +56,35 @@ public class DebugInformation {
|
|||
|
||||
public SourceLocation getSourceLocation(GeneratedLocation generatedLocation) {
|
||||
String fileName = componentByKey(fileNameKeys, fileNameValues, fileNames, generatedLocation);
|
||||
String className = componentByKey(classKeys, classValues, classNames, generatedLocation);
|
||||
MethodDescriptor method = componentByKey(methodKeys, methodValues, methods, generatedLocation);
|
||||
int lineNumberIndex = indexByKey(lineNumberKeys, generatedLocation);
|
||||
int lineNumber = lineNumberIndex >= 0 ? lineNumberValues[lineNumberIndex] : -1;
|
||||
return new SourceLocation(fileName, lineNumber, new MethodReference(className, method));
|
||||
return new SourceLocation(fileName, lineNumber);
|
||||
}
|
||||
|
||||
private <T> T componentByKey(GeneratedLocation[] keys, int[] valueIndexes, List<T> values,
|
||||
public MethodReference getMethodAt(String fileName, int line) {
|
||||
if (line < 0) {
|
||||
return null;
|
||||
}
|
||||
Integer fileIndex = fileNameMap.get(fileName);
|
||||
if (fileIndex == null) {
|
||||
return null;
|
||||
}
|
||||
FileDescription description = fileDescriptions[fileIndex];
|
||||
if (description == null) {
|
||||
return null;
|
||||
}
|
||||
return line < description.methodMap.length ? description.methodMap[line] : null;
|
||||
}
|
||||
|
||||
public MethodReference getMethodAt(SourceLocation sourceLocation) {
|
||||
return getMethodAt(sourceLocation.getFileName(), sourceLocation.getLine());
|
||||
}
|
||||
|
||||
private <T> T componentByKey(GeneratedLocation[] keys, int[] valueIndexes, T[] values,
|
||||
GeneratedLocation location) {
|
||||
int keyIndex = indexByKey(keys, location);
|
||||
int valueIndex = keyIndex >= 0 ? valueIndexes[keyIndex] : -1;
|
||||
return valueIndex >= 0 ? values.get(valueIndex) : null;
|
||||
return valueIndex >= 0 ? values[valueIndex] : null;
|
||||
}
|
||||
|
||||
private int indexByKey(GeneratedLocation[] keys, GeneratedLocation location) {
|
||||
|
@ -76,7 +92,8 @@ public class DebugInformation {
|
|||
return index >= 0 ? index : -index - 2;
|
||||
}
|
||||
|
||||
class FileDescription {
|
||||
static class FileDescription {
|
||||
GeneratedLocation[][] generatedLocations;
|
||||
MethodReference[] methodMap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.debugging;
|
||||
|
||||
import java.util.*;
|
||||
import org.teavm.codegen.LocationProvider;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
|
@ -24,6 +25,15 @@ import org.teavm.model.MethodReference;
|
|||
*/
|
||||
public class DebugInformationBuilder implements DebugInformationEmitter {
|
||||
private LocationProvider locationProvider;
|
||||
private DebugInformation debugInformation;
|
||||
private List<String> fileNames = new ArrayList<>();
|
||||
private Map<String, Integer> fileNameMap = new HashMap<>();
|
||||
private List<Entry> fileNameEntries = new ArrayList<>();
|
||||
private List<Entry> lineNumberEntries = new ArrayList<>();
|
||||
private MethodReference currentMethod;
|
||||
private String currentFileName;
|
||||
private int currentLine;
|
||||
private List<FileDescriptionProto> fileDescriptions = new ArrayList<>();
|
||||
|
||||
public LocationProvider getLocationProvider() {
|
||||
return locationProvider;
|
||||
|
@ -33,18 +43,111 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
this.locationProvider = locationProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitFile(String fileName) {
|
||||
private GeneratedLocation getGeneratedLocation() {
|
||||
return new GeneratedLocation(locationProvider.getLine(), locationProvider.getColumn());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitLocation(String fileName, int line) {
|
||||
Integer fileIndex;
|
||||
if (fileName != null) {
|
||||
fileIndex = fileNameMap.get(fileName);
|
||||
if (fileIndex == null) {
|
||||
fileIndex = fileNames.size();
|
||||
fileNames.add(fileName);
|
||||
fileNameMap.put(fileName, fileIndex);
|
||||
fileDescriptions.add(new FileDescriptionProto());
|
||||
}
|
||||
} else {
|
||||
fileIndex = -1;
|
||||
}
|
||||
if (currentFileName != fileName) {
|
||||
fileNameEntries.add(new Entry(getGeneratedLocation(), fileIndex));
|
||||
}
|
||||
if (currentLine != line) {
|
||||
lineNumberEntries.add(new Entry(getGeneratedLocation(), line));
|
||||
}
|
||||
if (fileName != null && line >= 0 && (currentFileName != fileName || currentLine != line)) {
|
||||
FileDescriptionProto fileDesc = fileDescriptions.get(fileIndex);
|
||||
fileDesc.setMethod(line, currentMethod);
|
||||
fileDesc.addGeneratedLocation(line, getGeneratedLocation());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitMethod(MethodReference method) {
|
||||
|
||||
currentMethod = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitLineNumber(String lineNumber) {
|
||||
public DebugInformation getDebugInformation() {
|
||||
if (debugInformation == null) {
|
||||
debugInformation = new DebugInformation();
|
||||
|
||||
debugInformation.fileNames = fileNames.toArray(new String[0]);
|
||||
debugInformation.fileNameMap = new HashMap<>(fileNameMap);
|
||||
|
||||
debugInformation.fileNameKeys = new GeneratedLocation[fileNameEntries.size()];
|
||||
debugInformation.fileNameValues = new int[fileNameEntries.size()];
|
||||
int index = 0;
|
||||
for (Entry entry : fileNameEntries) {
|
||||
debugInformation.fileNameKeys[index] = entry.key;
|
||||
debugInformation.fileNameValues[index] = entry.value;
|
||||
index++;
|
||||
}
|
||||
|
||||
debugInformation.lineNumberKeys = new GeneratedLocation[lineNumberEntries.size()];
|
||||
debugInformation.lineNumberValues = new int[lineNumberEntries.size()];
|
||||
index = 0;
|
||||
for (Entry entry : lineNumberEntries) {
|
||||
debugInformation.lineNumberKeys[index] = entry.key;
|
||||
debugInformation.lineNumberValues[index] = entry.value;
|
||||
index++;
|
||||
}
|
||||
|
||||
debugInformation.fileDescriptions = new DebugInformation.FileDescription[fileDescriptions.size()];
|
||||
index = 0;
|
||||
for (FileDescriptionProto fileDescProto : fileDescriptions) {
|
||||
DebugInformation.FileDescription fileDesc = new DebugInformation.FileDescription();
|
||||
debugInformation.fileDescriptions[index++] = fileDesc;
|
||||
fileDesc.methodMap = fileDescProto.methodMap.toArray(new MethodReference[0]);
|
||||
fileDesc.generatedLocations = new GeneratedLocation[fileDescProto.generatedLocations.size()][];
|
||||
for (int i = 0; i < fileDescProto.generatedLocations.size(); ++i) {
|
||||
fileDesc.generatedLocations[i] = fileDescProto.generatedLocations.get(index)
|
||||
.toArray(new GeneratedLocation[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return debugInformation;
|
||||
}
|
||||
|
||||
static class FileDescriptionProto {
|
||||
List<List<GeneratedLocation>> generatedLocations = new ArrayList<>();
|
||||
List<MethodReference> methodMap = new ArrayList<>();
|
||||
|
||||
void addGeneratedLocation(int line, GeneratedLocation location) {
|
||||
if (line >= generatedLocations.size()) {
|
||||
generatedLocations.addAll(Collections.<List<GeneratedLocation>>nCopies(
|
||||
line - generatedLocations.size() + 1, null));
|
||||
}
|
||||
List<GeneratedLocation> existingLocations = generatedLocations.get(line);
|
||||
existingLocations.add(location);
|
||||
}
|
||||
|
||||
void setMethod(int line, MethodReference method) {
|
||||
if (line >= methodMap.size()) {
|
||||
methodMap.addAll(Collections.<MethodReference>nCopies(line - methodMap.size() + 1, null));
|
||||
}
|
||||
methodMap.set(line, method);
|
||||
}
|
||||
}
|
||||
|
||||
static class Entry {
|
||||
GeneratedLocation key;
|
||||
int value;
|
||||
|
||||
public Entry(GeneratedLocation key, int value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,7 @@ import org.teavm.model.MethodReference;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface DebugInformationEmitter {
|
||||
void emitFile(String fileName);
|
||||
void emitLocation(String fileName, int line);
|
||||
|
||||
void emitMethod(MethodReference method);
|
||||
|
||||
void emitLineNumber(String lineNumber);
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.debugging;
|
||||
|
||||
import java.util.*;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -65,12 +66,14 @@ public class Debugger {
|
|||
return;
|
||||
}
|
||||
// TODO: lookup all locations that are "out of" the current location and create temporary breakpoints
|
||||
javaScriptDebugger.stepOut();
|
||||
}
|
||||
|
||||
public void stepOver() {
|
||||
if (!javaScriptDebugger.isSuspended()) {
|
||||
return;
|
||||
}
|
||||
javaScriptDebugger.stepOver();
|
||||
// TODO: lookup all locations that are "after" the current location and create temporary breakpoints
|
||||
}
|
||||
|
||||
|
@ -115,9 +118,10 @@ public class Debugger {
|
|||
boolean wasEmpty = false;
|
||||
for (JavaScriptCallFrame jsFrame : javaScriptDebugger.getCallStack()) {
|
||||
SourceLocation loc = debugInformation.getSourceLocation(jsFrame.getLocation());
|
||||
boolean empty = loc.getFileName() != null || loc.getMethod() != null || loc.getLine() < 0;
|
||||
boolean empty = loc == null || (loc.getFileName() == null && loc.getLine() < 0);
|
||||
MethodReference method = !empty ? debugInformation.getMethodAt(loc) : null;
|
||||
if (!empty || !wasEmpty) {
|
||||
frames.add(new CallFrame(loc));
|
||||
frames.add(new CallFrame(loc, method));
|
||||
}
|
||||
wasEmpty = empty;
|
||||
}
|
||||
|
|
|
@ -24,14 +24,10 @@ import org.teavm.model.MethodReference;
|
|||
*/
|
||||
public class DummyDebugInformationEmitter implements DebugInformationEmitter {
|
||||
@Override
|
||||
public void emitFile(String fileName) {
|
||||
public void emitLocation(String fileName, int line) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitMethod(MethodReference method) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitLineNumber(String lineNumber) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.teavm.debugging;
|
||||
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -24,12 +23,10 @@ import org.teavm.model.MethodReference;
|
|||
public class SourceLocation {
|
||||
private String fileName;
|
||||
private int line;
|
||||
private MethodReference method;
|
||||
|
||||
public SourceLocation(String fileName, int line, MethodReference method) {
|
||||
public SourceLocation(String fileName, int line) {
|
||||
this.fileName = fileName;
|
||||
this.line = line;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
|
@ -39,8 +36,4 @@ public class SourceLocation {
|
|||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public MethodReference getMethod() {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user