mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 00:14:10 -08:00
Start refactoring of debug information
This commit is contained in:
parent
7e1ff76c5d
commit
88c47095a6
|
@ -76,7 +76,18 @@ public class RecordArrayBuilder {
|
||||||
}
|
}
|
||||||
builtSubstart[i + 1] = builtSubdata.size();
|
builtSubstart[i + 1] = builtSubdata.size();
|
||||||
}
|
}
|
||||||
return new RecordArray(recordSize, arraysPerRecord, size, data.getAll(), builtSubstart, builtSubdata.getAll());
|
int[] builtSubdataArray = builtSubdata.getAll();
|
||||||
|
for (int i = 1; i < builtSubstart.length; ++i) {
|
||||||
|
int start = builtSubstart[i - 1];
|
||||||
|
int end = builtSubstart[i];
|
||||||
|
int h = (builtSubstart[i] - start) / 2;
|
||||||
|
for (int j = 0; j < h; ++j) {
|
||||||
|
int tmp = builtSubdataArray[start + j];
|
||||||
|
builtSubdataArray[start + j] = builtSubdataArray[end - j - 1];
|
||||||
|
builtSubdataArray[end - j - 1] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new RecordArray(recordSize, arraysPerRecord, size, data.getAll(), builtSubstart, builtSubdataArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Record {
|
public class Record {
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class ClassNameIterator {
|
||||||
|
|
||||||
|
}
|
|
@ -40,41 +40,56 @@ public class DebugInformation {
|
||||||
Map<String, Integer> variableNameMap;
|
Map<String, Integer> variableNameMap;
|
||||||
long[] exactMethods;
|
long[] exactMethods;
|
||||||
Map<Long, Integer> exactMethodMap;
|
Map<Long, Integer> exactMethodMap;
|
||||||
FileDescription[] fileDescriptions;
|
RecordArray[] fileDescriptions;
|
||||||
Mapping fileMapping;
|
RecordArray fileMapping;
|
||||||
Mapping classMapping;
|
RecordArray classMapping;
|
||||||
Mapping methodMapping;
|
RecordArray methodMapping;
|
||||||
Mapping lineMapping;
|
RecordArray lineMapping;
|
||||||
Mapping callSiteMapping;
|
RecordArray callSiteMapping;
|
||||||
MultiMapping[] variableMappings;
|
MultiMapping[] variableMappings;
|
||||||
RecordArray[] lineCallSites;
|
RecordArray[] lineCallSites;
|
||||||
CFG[] controlFlowGraphs;
|
CFG[] controlFlowGraphs;
|
||||||
List<ClassMetadata> classesMetadata;
|
List<ClassMetadata> classesMetadata;
|
||||||
MethodEntrances methodEntrances;
|
RecordArray methodEntrances;
|
||||||
MethodTree methodTree;
|
MethodTree methodTree;
|
||||||
|
|
||||||
public String[] getCoveredSourceFiles() {
|
public String[] getFilesNames() {
|
||||||
return fileNames.clone();
|
return fileNames.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getVariableNames() {
|
||||||
|
return variableNames.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineNumberIterator iterateOverLineNumbers() {
|
||||||
|
return new LineNumberIterator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileNameIterator iterateOverFileNames() {
|
||||||
|
return new FileNameIterator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName(int fileNameId) {
|
||||||
|
return fileNames[fileNameId];
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<GeneratedLocation> getGeneratedLocations(String fileName, int line) {
|
public Collection<GeneratedLocation> getGeneratedLocations(String fileName, int line) {
|
||||||
Integer fileIndex = fileNameMap.get(fileName);
|
Integer fileIndex = fileNameMap.get(fileName);
|
||||||
if (fileIndex == null) {
|
if (fileIndex == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
FileDescription description = fileIndex >= 0 ? fileDescriptions[fileIndex] : null;
|
RecordArray description = fileIndex >= 0 ? fileDescriptions[fileIndex] : null;
|
||||||
if (description == null) {
|
if (description == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
if (line >= description.generatedLocationStart.length - 1) {
|
if (line >= description.size()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
int start = description.generatedLocationStart[line];
|
int[] data = description.get(line).getArray(0);
|
||||||
int end = description.generatedLocationStart[line + 1];
|
GeneratedLocation[] resultArray = new GeneratedLocation[data.length / 2];
|
||||||
GeneratedLocation[] resultArray = new GeneratedLocation[(end - start) / 2];
|
|
||||||
for (int i = 0; i < resultArray.length; ++i) {
|
for (int i = 0; i < resultArray.length; ++i) {
|
||||||
int genLine = description.generatedLocationData[start++];
|
int genLine = data[i * 2];
|
||||||
int genColumn = description.generatedLocationData[start++];
|
int genColumn = data[i * 2 + 1];
|
||||||
resultArray[i] = new GeneratedLocation(genLine, genColumn);
|
resultArray[i] = new GeneratedLocation(genLine, genColumn);
|
||||||
}
|
}
|
||||||
return Arrays.asList(resultArray);
|
return Arrays.asList(resultArray);
|
||||||
|
@ -84,6 +99,10 @@ public class DebugInformation {
|
||||||
return getGeneratedLocations(sourceLocation.getFileName(), sourceLocation.getLine());
|
return getGeneratedLocations(sourceLocation.getFileName(), sourceLocation.getLine());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SourceLocationIterator iterateOverSourceLocations() {
|
||||||
|
return new SourceLocationIterator(this);
|
||||||
|
}
|
||||||
|
|
||||||
public SourceLocation getSourceLocation(int line, int column) {
|
public SourceLocation getSourceLocation(int line, int column) {
|
||||||
return getSourceLocation(new GeneratedLocation(line, column));
|
return getSourceLocation(new GeneratedLocation(line, column));
|
||||||
}
|
}
|
||||||
|
@ -91,7 +110,7 @@ public class DebugInformation {
|
||||||
public SourceLocation getSourceLocation(GeneratedLocation generatedLocation) {
|
public SourceLocation getSourceLocation(GeneratedLocation generatedLocation) {
|
||||||
String fileName = componentByKey(fileMapping, fileNames, generatedLocation);
|
String fileName = componentByKey(fileMapping, fileNames, generatedLocation);
|
||||||
int lineNumberIndex = indexByKey(lineMapping, generatedLocation);
|
int lineNumberIndex = indexByKey(lineMapping, generatedLocation);
|
||||||
int lineNumber = lineNumberIndex >= 0 ? lineMapping.values[lineNumberIndex] : -1;
|
int lineNumber = lineNumberIndex >= 0 ? lineMapping.get(lineNumberIndex).get(2) : -1;
|
||||||
return new SourceLocation(fileName, lineNumber);
|
return new SourceLocation(fileName, lineNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,34 +197,31 @@ public class DebugInformation {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference getCallSite(GeneratedLocation location) {
|
public DebuggerCallSite getCallSite(GeneratedLocation location) {
|
||||||
int keyIndex = indexByKey(callSiteMapping, location);
|
int keyIndex = indexByKey(callSiteMapping, location);
|
||||||
if (keyIndex < 0) {
|
return keyIndex >= 0 ? getCallSite(keyIndex) : null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
int valueIndex = callSiteMapping.values[keyIndex];
|
|
||||||
if (valueIndex < 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return getExactMethod(valueIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference getCallSite(int line, int column) {
|
private DebuggerCallSite getCallSite(int index) {
|
||||||
|
RecordArray.Record record = callSiteMapping.get(index);
|
||||||
|
int type = record.get(0);
|
||||||
|
int[] data = record.getArray(0);
|
||||||
|
switch (type) {
|
||||||
|
case DebuggerCallSite.NONE:
|
||||||
|
return null;
|
||||||
|
case DebuggerCallSite.STATIC:
|
||||||
|
return new DebuggerStaticCallSite(getExactMethod(data[0]));
|
||||||
|
case DebuggerCallSite.VIRTUAL:
|
||||||
|
return new DebuggerVirtualCallSite(getExactMethod(data[0]), data[1], variableNames[data[1]]);
|
||||||
|
default:
|
||||||
|
throw new AssertionError("Unrecognized call site type: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DebuggerCallSite getCallSite(int line, int column) {
|
||||||
return getCallSite(new GeneratedLocation(line, column));
|
return getCallSite(new GeneratedLocation(line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneratedLocation[] getCallSiteEntrances(GeneratedLocation location) {
|
|
||||||
MethodReference method = getCallSite(location);
|
|
||||||
if (method == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Set<GeneratedLocation> locations = new HashSet<>();
|
|
||||||
for (MethodReference overriding : getOverridingMethods(method)) {
|
|
||||||
locations.addAll(Arrays.asList(getMethodEntrances(overriding)));
|
|
||||||
}
|
|
||||||
return locations.toArray(new GeneratedLocation[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GeneratedLocation[] getMethodEntrances(MethodReference methodRef) {
|
public GeneratedLocation[] getMethodEntrances(MethodReference methodRef) {
|
||||||
Integer index = getExactMethodIndex(methodRef);
|
Integer index = getExactMethodIndex(methodRef);
|
||||||
if (index == null) {
|
if (index == null) {
|
||||||
|
@ -261,27 +277,26 @@ public class DebugInformation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference[] getCallSites(SourceLocation location) {
|
public DebuggerCallSite[] getCallSites(SourceLocation location) {
|
||||||
Integer fileIndex = fileNameMap.get(location.getFileName());
|
Integer fileIndex = fileNameMap.get(location.getFileName());
|
||||||
if (fileIndex == null) {
|
if (fileIndex == null) {
|
||||||
return new MethodReference[0];
|
return new DebuggerCallSite[0];
|
||||||
}
|
}
|
||||||
RecordArray mapping = lineCallSites[fileIndex];
|
RecordArray mapping = lineCallSites[fileIndex];
|
||||||
if (location.getLine() >= mapping.size()) {
|
if (location.getLine() >= mapping.size()) {
|
||||||
return new MethodReference[0];
|
return new DebuggerCallSite[0];
|
||||||
}
|
}
|
||||||
int[] callSiteIds = mapping.get(location.getLine()).getArray(0);
|
int[] callSiteIds = mapping.get(location.getLine()).getArray(0);
|
||||||
MethodReference[] methods = new MethodReference[callSiteIds.length];
|
DebuggerCallSite[] callSites = new DebuggerCallSite[callSiteIds.length];
|
||||||
for (int i = 0; i < callSiteIds.length; ++i) {
|
for (int i = 0; i < callSiteIds.length; ++i) {
|
||||||
int exactMethodId = callSiteMapping.values[callSiteIds[i]];
|
callSites[i] = getCallSite(callSiteIds[i]);
|
||||||
methods[i] = getExactMethod(exactMethodId);
|
|
||||||
}
|
}
|
||||||
return methods;
|
return callSites;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T componentByKey(Mapping mapping, T[] values, GeneratedLocation location) {
|
private <T> T componentByKey(RecordArray mapping, T[] values, GeneratedLocation location) {
|
||||||
int keyIndex = indexByKey(mapping, location);
|
int keyIndex = indexByKey(mapping, location);
|
||||||
int valueIndex = keyIndex >= 0 ? mapping.values[keyIndex] : -1;
|
int valueIndex = keyIndex >= 0 ? mapping.get(keyIndex).get(2) : -1;
|
||||||
return valueIndex >= 0 ? values[valueIndex] : null;
|
return valueIndex >= 0 ? values[valueIndex] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,14 +314,14 @@ public class DebugInformation {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int indexByKey(Mapping mapping, GeneratedLocation location) {
|
private int indexByKey(RecordArray mapping, GeneratedLocation location) {
|
||||||
int index = Collections.binarySearch(mapping.keyList(), location);
|
int index = Collections.binarySearch(new LocationList(mapping), location);
|
||||||
return index >= 0 ? index : -index - 2;
|
return index >= 0 ? index : -index - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int valueByKey(Mapping mapping, GeneratedLocation location) {
|
private int valueByKey(RecordArray mapping, GeneratedLocation location) {
|
||||||
int index = indexByKey(mapping, location);
|
int index = indexByKey(mapping, location);
|
||||||
return index >= 0 ? mapping.values[index] : -1;
|
return index >= 0 ? mapping.get(index).get(2) : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int indexByKey(MultiMapping mapping, GeneratedLocation location) {
|
private int indexByKey(MultiMapping mapping, GeneratedLocation location) {
|
||||||
|
@ -363,33 +378,41 @@ public class DebugInformation {
|
||||||
int currentFile = -1;
|
int currentFile = -1;
|
||||||
int currentLine = -1;
|
int currentLine = -1;
|
||||||
while (fileIndex < fileMapping.size() && lineIndex < lineMapping.size()) {
|
while (fileIndex < fileMapping.size() && lineIndex < lineMapping.size()) {
|
||||||
GeneratedLocation fileLoc = fileMapping.key(fileIndex);
|
RecordArray.Record fileRec = fileMapping.get(fileIndex);
|
||||||
GeneratedLocation lineLoc = lineMapping.key(lineIndex);
|
RecordArray.Record lineRec = lineMapping.get(lineIndex);
|
||||||
|
GeneratedLocation fileLoc = key(fileRec);
|
||||||
|
GeneratedLocation lineLoc = key(lineRec);
|
||||||
int cmp = fileLoc.compareTo(lineLoc);
|
int cmp = fileLoc.compareTo(lineLoc);
|
||||||
if (cmp < 0) {
|
if (cmp < 0) {
|
||||||
currentFile = fileMapping.values[fileIndex++];
|
currentFile = fileRec.get(2);
|
||||||
|
fileIndex++;
|
||||||
} else if (cmp > 0){
|
} else if (cmp > 0){
|
||||||
currentLine = lineMapping.values[lineIndex++];
|
currentLine = lineRec.get(2);
|
||||||
|
lineIndex++;
|
||||||
} else {
|
} else {
|
||||||
currentFile = fileMapping.values[fileIndex++];
|
currentFile = fileRec.get(2);
|
||||||
currentLine = lineMapping.values[lineIndex++];
|
currentLine = lineRec.get(2);
|
||||||
|
fileIndex++;
|
||||||
|
lineIndex++;
|
||||||
}
|
}
|
||||||
builder.emit(fileLoc.getLine(), fileLoc.getColumn(), currentFile, currentLine);
|
builder.emit(fileLoc.getLine(), fileLoc.getColumn(), currentFile, currentLine);
|
||||||
}
|
}
|
||||||
while (fileIndex < fileMapping.size()) {
|
while (fileIndex < fileMapping.size()) {
|
||||||
builder.emit(fileMapping.lines[fileIndex], fileMapping.columns[fileIndex],
|
RecordArray.Record fileRec = fileMapping.get(fileIndex++);
|
||||||
fileMapping.values[fileIndex], currentLine);
|
builder.emit(fileRec.get(0), fileRec.get(1), fileRec.get(2), currentLine);
|
||||||
++fileIndex;
|
|
||||||
}
|
}
|
||||||
while (lineIndex < lineMapping.size()) {
|
while (lineIndex < lineMapping.size()) {
|
||||||
builder.emit(lineMapping.lines[lineIndex], lineMapping.columns[lineIndex], currentFile,
|
RecordArray.Record lineRec = lineMapping.get(lineIndex++);
|
||||||
lineMapping.values[lineIndex]);
|
builder.emit(lineRec.get(0), lineRec.get(1), currentFile, lineRec.get(2));
|
||||||
++lineIndex;
|
|
||||||
}
|
}
|
||||||
fileDescriptions = builder.build();
|
fileDescriptions = builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rebuildEntrances() {
|
void rebuildEntrances() {
|
||||||
|
RecordArrayBuilder builder = new RecordArrayBuilder(0, 1);
|
||||||
|
for (SourceLocationIterator iter = iterateOverSourceLocations(); !iter.isEndReached(); iter.next()) {
|
||||||
|
iter.getLocation();
|
||||||
|
}
|
||||||
methodEntrances = new MethodEntrancesBuilder().build();
|
methodEntrances = new MethodEntrancesBuilder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,10 +495,11 @@ public class DebugInformation {
|
||||||
for (int i = 0; i < lineCallSites.length; ++i) {
|
for (int i = 0; i < lineCallSites.length; ++i) {
|
||||||
builders[i] = new RecordArrayBuilder(0, 1);
|
builders[i] = new RecordArrayBuilder(0, 1);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < callSiteMapping.lines.length; ++i) {
|
for (int i = 0; i < callSiteMapping.size(); ++i) {
|
||||||
GeneratedLocation loc = callSiteMapping.key(i);
|
RecordArray.Record callSiteRec = callSiteMapping.get(i);
|
||||||
int methodId = callSiteMapping.values[i];
|
GeneratedLocation loc = key(callSiteRec);
|
||||||
if (methodId >= 0) {
|
int callSiteType = callSiteRec.get(2);
|
||||||
|
if (callSiteType != DebuggerCallSite.NONE) {
|
||||||
int line = valueByKey(lineMapping, loc);
|
int line = valueByKey(lineMapping, loc);
|
||||||
int fileId = valueByKey(fileMapping, loc);
|
int fileId = valueByKey(fileMapping, loc);
|
||||||
if (fileId >= 0 && line >= 0) {
|
if (fileId >= 0 && line >= 0) {
|
||||||
|
@ -606,14 +630,14 @@ public class DebugInformation {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class FileDescriptionBuilder {
|
static class FileDescriptionBuilder {
|
||||||
FileDescriptionProto[] files;
|
RecordArrayBuilder[] files;
|
||||||
int lastFileIndex = -1;
|
int lastFileIndex = -1;
|
||||||
int lastSourceLine = -1;
|
int lastSourceLine = -1;
|
||||||
|
|
||||||
public FileDescriptionBuilder(int size) {
|
public FileDescriptionBuilder(int size) {
|
||||||
files = new FileDescriptionProto[size];
|
files = new RecordArrayBuilder[size];
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
files[i] = new FileDescriptionProto();
|
files[i] = new RecordArrayBuilder(0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,12 +650,17 @@ public class DebugInformation {
|
||||||
}
|
}
|
||||||
lastFileIndex = fileIndex;
|
lastFileIndex = fileIndex;
|
||||||
lastSourceLine = sourceLine;
|
lastSourceLine = sourceLine;
|
||||||
FileDescriptionProto proto = files[fileIndex];
|
RecordArrayBuilder proto = files[fileIndex];
|
||||||
proto.addLocation(sourceLine, line, column);
|
while (proto.size() <= sourceLine) {
|
||||||
|
proto.add();
|
||||||
|
}
|
||||||
|
RecordArrayBuilder.RecordSubArray array = proto.get(sourceLine).getArray(0);
|
||||||
|
array.add(line);
|
||||||
|
array.add(column);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileDescription[] build() {
|
public RecordArray[] build() {
|
||||||
FileDescription[] descriptions = new FileDescription[files.length];
|
RecordArray[] descriptions = new RecordArray[files.length];
|
||||||
for (int i = 0; i < files.length; ++i) {
|
for (int i = 0; i < files.length; ++i) {
|
||||||
descriptions[i] = files[i].build();
|
descriptions[i] = files[i].build();
|
||||||
}
|
}
|
||||||
|
@ -639,81 +668,8 @@ public class DebugInformation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class FileDescriptionProto {
|
static GeneratedLocation key(RecordArray.Record record) {
|
||||||
IntegerArray generatedLocationData = new IntegerArray(1);
|
return new GeneratedLocation(record.get(0), record.get(1));
|
||||||
IntegerArray generatedLocationPointers = new IntegerArray(1);
|
|
||||||
IntegerArray generatedLocationStart = new IntegerArray(1);
|
|
||||||
IntegerArray generatedLocationSize = new IntegerArray(1);
|
|
||||||
|
|
||||||
public void addLocation(int sourceLine, int line, int column) {
|
|
||||||
ensureLine(sourceLine);
|
|
||||||
generatedLocationSize.set(sourceLine, generatedLocationSize.get(sourceLine) + 1);
|
|
||||||
int slot = generatedLocationStart.get(sourceLine);
|
|
||||||
slot = addData(slot, line);
|
|
||||||
slot = addData(slot, column);
|
|
||||||
generatedLocationStart.set(sourceLine, slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
int addData(int slot, int value) {
|
|
||||||
int result = generatedLocationData.size();
|
|
||||||
generatedLocationData.add(value);
|
|
||||||
generatedLocationPointers.add(slot);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ensureLine(int sourceLine) {
|
|
||||||
while (sourceLine >= generatedLocationSize.size()) {
|
|
||||||
generatedLocationSize.add(0);
|
|
||||||
generatedLocationStart.add(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FileDescription build() {
|
|
||||||
FileDescription description = new FileDescription();
|
|
||||||
description.generatedLocationData = new int[generatedLocationData.size()];
|
|
||||||
description.generatedLocationStart = new int[generatedLocationStart.size() + 1];
|
|
||||||
int current = 0;
|
|
||||||
for (int i = 0; i < generatedLocationStart.size(); ++i) {
|
|
||||||
current += generatedLocationSize.get(i) * 2;
|
|
||||||
int j = current;
|
|
||||||
int ptr = generatedLocationStart.get(i);
|
|
||||||
while (ptr >= 0) {
|
|
||||||
description.generatedLocationData[--j] = generatedLocationData.get(ptr);
|
|
||||||
ptr = generatedLocationPointers.get(ptr);
|
|
||||||
}
|
|
||||||
description.generatedLocationStart[i + 1] = current;
|
|
||||||
}
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class FileDescription {
|
|
||||||
int[] generatedLocationData;
|
|
||||||
int[] generatedLocationStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Mapping {
|
|
||||||
int[] lines;
|
|
||||||
int[] columns;
|
|
||||||
int[] values;
|
|
||||||
|
|
||||||
public Mapping(int[] lines, int[] columns, int[] values) {
|
|
||||||
this.lines = lines;
|
|
||||||
this.columns = columns;
|
|
||||||
this.values = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocationList keyList() {
|
|
||||||
return new LocationList(lines, columns);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return lines.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GeneratedLocation key(int index) {
|
|
||||||
return new GeneratedLocation(lines[index], columns[index]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MultiMapping {
|
static class MultiMapping {
|
||||||
|
@ -743,22 +699,21 @@ public class DebugInformation {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class LocationList extends AbstractList<GeneratedLocation> {
|
static class LocationList extends AbstractList<GeneratedLocation> {
|
||||||
private int[] lines;
|
private RecordArray recordArray;
|
||||||
private int[] columns;
|
|
||||||
|
|
||||||
public LocationList(int[] lines, int[] columns) {
|
public LocationList(RecordArray recordArray) {
|
||||||
this.lines = lines;
|
this.recordArray = recordArray;
|
||||||
this.columns = columns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GeneratedLocation get(int index) {
|
public GeneratedLocation get(int index) {
|
||||||
return new GeneratedLocation(lines[index], columns[index]);
|
RecordArray.Record record = recordArray.get(index);
|
||||||
|
return new GeneratedLocation(record.get(0), record.get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return lines.length;
|
return recordArray.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,24 +729,6 @@ public class DebugInformation {
|
||||||
int[] offsets;
|
int[] offsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MethodEntrances {
|
|
||||||
int[] data;
|
|
||||||
int[] offsets;
|
|
||||||
|
|
||||||
public GeneratedLocation[] getEntrances(int index) {
|
|
||||||
if (index < 0 || index > offsets.length - 1) {
|
|
||||||
return new GeneratedLocation[0];
|
|
||||||
}
|
|
||||||
int start = offsets[index];
|
|
||||||
int end = offsets[index + 1];
|
|
||||||
GeneratedLocation[] result = new GeneratedLocation[(end - start) / 2];
|
|
||||||
for (int i = 0; i < result.length; ++i) {
|
|
||||||
result[i] = new GeneratedLocation(data[start + i * 2], data[start + i * 2 + 1]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MethodTree {
|
class MethodTree {
|
||||||
int[] data;
|
int[] data;
|
||||||
int[] offsets;
|
int[] offsets;
|
||||||
|
|
|
@ -291,7 +291,7 @@ public class Debugger {
|
||||||
updateBreakpoints();
|
updateBreakpoints();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (String sourceFile : debugInfo.getCoveredSourceFiles()) {
|
for (String sourceFile : debugInfo.getFilesNames()) {
|
||||||
ConcurrentMap<DebugInformation, Object> list = debugInformationFileMap.get(sourceFile);
|
ConcurrentMap<DebugInformation, Object> list = debugInformationFileMap.get(sourceFile);
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
list = new ConcurrentHashMap<>();
|
list = new ConcurrentHashMap<>();
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public abstract class DebuggerCallSite {
|
||||||
|
static final int NONE = 0;
|
||||||
|
static final int STATIC = 1;
|
||||||
|
static final int VIRTUAL = 2;
|
||||||
|
|
||||||
|
public abstract void acceptVisitor(DebuggerCallSiteVisitor visitor);
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public interface DebuggerCallSiteVisitor {
|
||||||
|
void visit(DebuggerVirtualCallSite callSite);
|
||||||
|
|
||||||
|
void visit(DebuggerStaticCallSite callSite);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class DebuggerStaticCallSite extends DebuggerCallSite {
|
||||||
|
private MethodReference method;
|
||||||
|
|
||||||
|
DebuggerStaticCallSite(MethodReference method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodReference getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(DebuggerCallSiteVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class DebuggerVirtualCallSite extends DebuggerCallSite {
|
||||||
|
private MethodReference method;
|
||||||
|
private int variableId;
|
||||||
|
private String variableName;
|
||||||
|
|
||||||
|
DebuggerVirtualCallSite(MethodReference method, int variableId, String variableName) {
|
||||||
|
this.method = method;
|
||||||
|
this.variableId = variableId;
|
||||||
|
this.variableName = variableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodReference getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethod(MethodReference method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVariableId() {
|
||||||
|
return variableId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVariableId(int variableId) {
|
||||||
|
this.variableId = variableId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVariableName() {
|
||||||
|
return variableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVariableName(String variableName) {
|
||||||
|
this.variableName = variableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(DebuggerCallSiteVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class FileNameIterator {
|
||||||
|
private DebugInformation debugInformation;
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
FileNameIterator(DebugInformation debugInformation) {
|
||||||
|
this.debugInformation = debugInformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEndReached() {
|
||||||
|
return index < debugInformation.fileMapping.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeneratedLocation getLocation() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
return DebugInformation.key(debugInformation.fileMapping.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFileNameId() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
return debugInformation.fileMapping.get(index).get(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
int fileNameId = getFileNameId();
|
||||||
|
return fileNameId >= 0 ? debugInformation.getFileName(fileNameId) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void next() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class LineNumberIterator {
|
||||||
|
private DebugInformation debugInformation;
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
LineNumberIterator(DebugInformation debugInformation) {
|
||||||
|
this.debugInformation = debugInformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEndReached() {
|
||||||
|
return index < debugInformation.lineMapping.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeneratedLocation getLocation() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
return DebugInformation.key(debugInformation.lineMapping.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineNumber() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
return debugInformation.lineMapping.get(index).get(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void next() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
import org.teavm.common.RecordArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class SourceLocationIterator {
|
||||||
|
private DebugInformation debugInformation;
|
||||||
|
private int lineIndex;
|
||||||
|
private int fileIndex;
|
||||||
|
private GeneratedLocation location;
|
||||||
|
private int fileId = -1;
|
||||||
|
private int line = -1;
|
||||||
|
private boolean endReached;
|
||||||
|
|
||||||
|
SourceLocationIterator(DebugInformation debugInformation) {
|
||||||
|
this.debugInformation = debugInformation;
|
||||||
|
read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEndReached() {
|
||||||
|
return endReached;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void read() {
|
||||||
|
if (lineIndex >= debugInformation.lineMapping.size()) {
|
||||||
|
nextFileRecord();
|
||||||
|
} else if (fileIndex >= debugInformation.fileMapping.size()) {
|
||||||
|
nextLineRecord();
|
||||||
|
} else if (fileIndex < debugInformation.fileMapping.size() &&
|
||||||
|
lineIndex < debugInformation.lineMapping.size()) {
|
||||||
|
RecordArray.Record fileRecord = debugInformation.fileMapping.get(fileIndex++);
|
||||||
|
RecordArray.Record lineRecord = debugInformation.lineMapping.get(lineIndex++);
|
||||||
|
GeneratedLocation fileLoc = DebugInformation.key(fileRecord);
|
||||||
|
GeneratedLocation lineLoc = DebugInformation.key(lineRecord);
|
||||||
|
int cmp = fileLoc.compareTo(lineLoc);
|
||||||
|
if (cmp < 0) {
|
||||||
|
nextFileRecord();
|
||||||
|
} else if (cmp > 0) {
|
||||||
|
nextLineRecord();
|
||||||
|
} else {
|
||||||
|
nextFileRecord();
|
||||||
|
nextLineRecord();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
endReached = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void nextFileRecord() {
|
||||||
|
RecordArray.Record record = debugInformation.fileMapping.get(fileIndex++);
|
||||||
|
location = DebugInformation.key(record);
|
||||||
|
fileId = record.get(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void nextLineRecord() {
|
||||||
|
RecordArray.Record record = debugInformation.lineMapping.get(lineIndex++);
|
||||||
|
location = DebugInformation.key(record);
|
||||||
|
line = record.get(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void next() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeneratedLocation getLocation() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFileNameId() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
return fileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
int fileId = getFileNameId();
|
||||||
|
return fileId >= 0 ? debugInformation.getFileName(fileId) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLine() {
|
||||||
|
if (isEndReached()) {
|
||||||
|
throw new IllegalStateException("End already reached");
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user