Refactoring of debug information reader/writer

This commit is contained in:
konsoletyper 2014-08-30 19:13:14 +04:00
parent deea4e995a
commit 31b5895640
7 changed files with 218 additions and 130 deletions

View File

@ -125,18 +125,18 @@ public class RecordArrayBuilder {
return arraysPerRecord;
}
public RecordSubArray getArray(int index) {
public SubArray getArray(int index) {
if (index > arraysPerRecord) {
throw new IndexOutOfBoundsException("Index out of bounds: " + index + " of " + arraysPerRecord);
}
return new RecordSubArray(arrayOffset + index);
return new SubArray(arrayOffset + index);
}
}
public class RecordSubArray {
public class SubArray {
private int offset;
public RecordSubArray(int offset) {
public SubArray(int offset) {
this.offset = offset;
}

View File

@ -267,15 +267,15 @@ public class DebugInformation {
private DebuggerCallSite getCallSite(int index) {
RecordArray.Record record = callSiteMapping.get(index);
int type = record.get(0);
int[] data = record.getArray(0);
int type = record.get(2);
int method = record.get(3);
switch (type) {
case DebuggerCallSite.NONE:
return null;
case DebuggerCallSite.STATIC:
return new DebuggerStaticCallSite(getExactMethod(data[0]));
return new DebuggerStaticCallSite(getExactMethod(method));
case DebuggerCallSite.VIRTUAL:
return new DebuggerVirtualCallSite(getExactMethod(data[0]));
return new DebuggerVirtualCallSite(getExactMethod(method));
default:
throw new AssertionError("Unrecognized call site type: " + type);
}
@ -426,7 +426,7 @@ public class DebugInformation {
builder.add();
}
GeneratedLocation loc = iter.getLocation();
RecordArrayBuilder.RecordSubArray array = builder.get(iter.getLine()).getArray(0);
RecordArrayBuilder.SubArray array = builder.get(iter.getLine()).getArray(0);
array.add(loc.getLine());
array.add(loc.getColumn());
}
@ -444,18 +444,19 @@ public class DebugInformation {
}
GeneratedLocation prevLocation = new GeneratedLocation(0, 0);
MethodReference prevMethod = null;
int prevMethodId = -1;
for (ExactMethodIterator iter = iterateOverExactMethods(); !iter.isEndReached(); iter.next()) {
int id = iter.getExactMethodId();
if (prevMethod != null) {
int lineIndex = Math.max(0, indexByKey(lineMapping, prevLocation));
while (lineIndex < 0) {
while (lineIndex < lineMapping.size()) {
if (key(lineMapping.get(lineIndex)).compareTo(iter.getLocation()) >= 0) {
break;
}
int line = lineMapping.get(0).get(2);
if (line >= 0) {
GeneratedLocation firstLineLoc = key(lineMapping.get(lineIndex));
RecordArrayBuilder.RecordSubArray array = builder.get(id).getArray(0);
RecordArrayBuilder.SubArray array = builder.get(prevMethodId).getArray(0);
array.add(firstLineLoc.getLine());
array.add(firstLineLoc.getColumn());
break;
@ -463,8 +464,10 @@ public class DebugInformation {
}
}
prevMethod = iter.getExactMethod();
prevMethodId = id;
prevLocation = iter.getLocation();
}
methodEntrances = builder.build();
}
void rebuildMethodTree() {

View File

@ -135,7 +135,7 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
}
RecordArrayBuilder.Record record = add(mapping);
RecordArrayBuilder.RecordSubArray array = record.getArray(0);
RecordArrayBuilder.SubArray array = record.getArray(0);
for (int sourceIndex : sourceIndexes) {
array.add(sourceIndex);
}
@ -202,11 +202,14 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
cfgs.add(new RecordArrayBuilder(1, 1));
}
RecordArrayBuilder cfg = cfgs.get(fileIndex);
while (cfg.size() <= location.getLine()) {
cfg.add();
}
RecordArrayBuilder.Record record = cfg.get(location.getLine());
if (record.get(0) == 0) {
record.set(0, 1);
}
RecordArrayBuilder.RecordSubArray array = record.getArray(0);
RecordArrayBuilder.SubArray array = record.getArray(0);
for (SourceLocation succ : successors) {
if (succ == null) {
record.set(0, 2);
@ -236,7 +239,7 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
for (int i = 0; i < builder.size(); ++i) {
RecordArrayBuilder.Record record = builder.get(i);
for (int j = 0; j < builder.getArraysPerRecord(); ++j) {
RecordArrayBuilder.RecordSubArray array = record.getArray(j);
RecordArrayBuilder.SubArray array = record.getArray(j);
int[] data = array.getData();
Arrays.sort(data);
array.clear();

View File

@ -20,8 +20,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.teavm.common.IntegerArray;
import org.teavm.common.RecordArray;
import org.teavm.common.RecordArrayBuilder;
/**
*
@ -47,7 +47,7 @@ class DebugInformationReader {
debugInfo.lineMapping = readMapping();
debugInfo.classMapping = readMapping();
debugInfo.methodMapping = readMapping();
debugInfo.callSiteMapping = readMapping();
debugInfo.callSiteMapping = readCallSiteMapping();
debugInfo.variableMappings = readVariableMappings(debugInfo.variableNames.length);
debugInfo.classesMetadata = readClassesMetadata(debugInfo.classNames.length);
debugInfo.controlFlowGraphs = readCFGs(debugInfo.fileNames.length);
@ -86,49 +86,55 @@ class DebugInformationReader {
return classes;
}
private DebugInformation.CFG[] readCFGs(int count) throws IOException {
DebugInformation.CFG[] cfgs = new DebugInformation.CFG[count];
private RecordArray[] readCFGs(int count) throws IOException {
RecordArray[] cfgs = new RecordArray[count];
for (int i = 0; i < count; ++i) {
cfgs[i] = readCFG(i);
cfgs[i] = readCFG();
}
return cfgs;
}
private DebugInformation.CFG readCFG(int index) throws IOException {
IntegerArray offsets = new IntegerArray(1);
int[] lines = new int[readUnsignedNumber()];
int[] files = new int[lines.length];
int i = 0;
int line = -1;
while (i < lines.length) {
int passedLines = readUnsignedNumber();
for (int j = 0; j < passedLines; ++j) {
offsets.add(i);
private RecordArray readCFG() throws IOException {
RecordArrayBuilder builder = new RecordArrayBuilder(1, 1);
int size = readUnsignedNumber();
for (int i = 0; i < size; ++i) {
builder.add();
}
line += passedLines;
int sz = readUnsignedNumber();
if (sz == 0) {
lines[i] = -1;
files[i++] = -1;
} else if (sz == 1) {
lines[i] = line + 1;
files[i++] = index;
} else {
sz -= 1;
int last = line;
for (int j = 0; j < sz; ++j) {
last += readNumber();
lines[i] = last;
files[i++] = index + readNumber();
int[] types = readRle(size);
int nonEmptyItems = 0;
for (int i = 0; i < size; ++i) {
int type = types[i];
builder.get(i).set(0, type);
if (type != 0) {
++nonEmptyItems;
}
}
int[] sizes = readRle(nonEmptyItems);
int j = 0;
int totalSize = 0;
for (int sz : sizes) {
totalSize += sz;
}
offsets.add(i);
DebugInformation.CFG cfg = new DebugInformation.CFG();
cfg.offsets = offsets.getAll();
cfg.lines = lines;
cfg.files = files;
return cfg;
int files[] = readRle(totalSize);
int lines[] = readRle(totalSize);
int lastFile = 0;
int lastLine = 0;
int index = 0;
for (int i = 0; i < sizes.length; ++i) {
while (types[j] == 0) {
++j;
}
size = sizes[i];
RecordArrayBuilder.SubArray array = builder.get(j++).getArray(0);
for (int k = 0; k < size; ++k) {
lastFile += processSign(files[index]);
lastLine += processSign(lines[index]);
array.add(lastFile);
array.add(lastLine);
++index;
}
}
return builder.build();
}
private int processSign(int number) {
@ -138,49 +144,108 @@ class DebugInformationReader {
}
private RecordArray readMultiMapping() throws IOException {
int[] lines = readRle();
RecordArrayBuilder builder = readLinesAndColumns(2, 1);
for (int i = 0; i < builder.size(); ++i) {
int count = readUnsignedNumber();
RecordArrayBuilder.SubArray array = builder.get(i).getArray(0);
int last = 0;
for (int i = 0; i < lines.length; ++i) {
last += lines[i];
lines[i] = last;
for (int j = 0; j < count; ++j) {
last += readUnsignedNumber();
array.add(last);
}
int[] columns = new int[lines.length];
resetRelativeNumber();
for (int i = 0; i < columns.length; ++i) {
columns[i] = readRelativeNumber();
}
int[] offsets = new int[lines.length + 1];
int lastOffset = 0;
for (int i = 1; i < offsets.length; ++i) {
lastOffset += readUnsignedNumber();
offsets[i] = lastOffset;
}
int[] data = new int[lastOffset];
resetRelativeNumber();
for (int i = 0; i < data.length; ++i) {
data[i] = readRelativeNumber();
}
return new DebugInformation.MultiMapping(lines, columns, offsets, data);
return builder.build();
}
private DebugInformation.Mapping readMapping() throws IOException {
int[] lines = readRle();
private RecordArray readMapping() throws IOException {
RecordArrayBuilder builder = readLinesAndColumns(3, 0);
readValues(builder);
return builder.build();
}
private RecordArray readCallSiteMapping() throws IOException {
RecordArrayBuilder builder = readLinesAndColumns(4, 0);
readValues(builder);
readCallSites(builder);
return builder.build();
}
private RecordArrayBuilder readLinesAndColumns(int fields, int arrays) throws IOException {
RecordArrayBuilder builder = new RecordArrayBuilder(fields, arrays);
int size = readUnsignedNumber();
for (int i = 0; i < size; ++i) {
builder.add();
}
int[] lines = extractLines(readRle(builder.size()));
int[] columns = extractColumns(readRle(builder.size()), lines);
for (int i = 0; i < builder.size(); ++i) {
RecordArrayBuilder.Record record = builder.get(i);
record.set(0, lines[i]);
record.set(1, columns[i]);
}
return builder;
}
private void readValues(RecordArrayBuilder builder) throws IOException {
int[] values = extractValues(readRle(builder.size()));
for (int i = 0; i < builder.size(); ++i) {
builder.get(i).set(2, values[i]);
}
}
private void readCallSites(RecordArrayBuilder builder) throws IOException {
int sz = 0;
for (int i = 0; i < builder.size(); ++i) {
if (builder.get(i).get(2) != 0) {
++sz;
}
}
int[] data = readRle(sz);
int j = 0;
int last = 0;
for (int i = 0; i < builder.size(); ++i) {
if (builder.get(i).get(2) != 0) {
last += processSign(data[j++]);
builder.get(i).set(3, last);
}
}
}
private int[] extractLines(int[] lines) {
int last = 0;
for (int i = 0; i < lines.length; ++i) {
last += lines[i];
lines[i] = last;
}
int[] columns = new int[lines.length];
resetRelativeNumber();
return lines;
}
private int[] extractColumns(int[] columns, int[] lines) {
int last = 0;
int lastLine = -1;
for (int i = 0; i < columns.length; ++i) {
columns[i] = readRelativeNumber();
if (lines[i] != lastLine) {
lastLine = lines[i];
last = 0;
}
int[] values = new int[lines.length];
resetRelativeNumber();
last += columns[i];
columns[i] = last;
}
return columns;
}
private int[] extractValues(int[] values) {
int last = 0;
for (int i = 0; i < values.length; ++i) {
values[i] = readRelativeNumber();
int value = values[i];
if (value == 0) {
values[i] = -1;
} else {
last += processSign(value - 1);
values[i] = last;
}
return new DebugInformation.Mapping(lines, columns, values);
}
return values;
}
private String[] readStrings() throws IOException {
@ -203,19 +268,23 @@ class DebugInformationReader {
return result;
}
private int[] readRle() throws IOException {
int[] array = new int[readUnsignedNumber()];
for (int i = 0; i < array.length;) {
int n = readUnsignedNumber();
int count = 1;
if ((n & 1) != 0) {
count = readUnsignedNumber();
private int[] readRle(int size) throws IOException {
int[] array = new int[size];
for (int i = 0; i < size;) {
int count = readUnsignedNumber();
boolean repeat = (count & 1) != 0;
count >>>= 1;
if (!repeat) {
while (count-- > 0) {
array[i++] = readUnsignedNumber();
}
n = processSign(n >>> 1);
} else {
int n = readUnsignedNumber();
while (count-- > 0) {
array[i++] = n;
}
}
}
return array;
}

View File

@ -131,22 +131,22 @@ class DebugInformationWriter {
private void writeMapping(RecordArray mapping) throws IOException {
writeLinesAndColumns(mapping);
writeRle(extractValues(mapping));
writeRle(packValues(mapping));
}
private void writeCallSiteMapping(RecordArray mapping) throws IOException {
writeLinesAndColumns(mapping);
writeRle(extractValues(mapping));
writeRle(extractCallSites(mapping));
writeRle(packValues(mapping));
writeRle(packCallSites(mapping));
}
private void writeLinesAndColumns(RecordArray mapping) throws IOException {
writeUnsignedNumber(mapping.size());
writeRle(extractLines(mapping));
writeRle(extractColumns(mapping));
writeRle(packLines(mapping));
writeRle(packColumns(mapping));
}
private int[] extractLines(RecordArray mapping) {
private int[] packLines(RecordArray mapping) {
int[] lines = mapping.cut(0);
int last = 0;
for (int i = 0; i < lines.length; ++i) {
@ -157,7 +157,7 @@ class DebugInformationWriter {
return lines;
}
private int[] extractColumns(RecordArray mapping) {
private int[] packColumns(RecordArray mapping) {
int[] columns = mapping.cut(1);
int lastLine = -1;
int lastColumn = 0;
@ -173,7 +173,7 @@ class DebugInformationWriter {
return columns;
}
private int[] extractValues(RecordArray mapping) {
private int[] packValues(RecordArray mapping) {
int[] values = mapping.cut(2);
int last = 0;
for (int i = 0; i < values.length; ++i) {
@ -188,7 +188,7 @@ class DebugInformationWriter {
return values;
}
private int[] extractCallSites(RecordArray mapping) {
private int[] packCallSites(RecordArray mapping) {
int[] callSites = mapping.cut(3);
int last = 0;
int j = 0;
@ -196,7 +196,7 @@ class DebugInformationWriter {
int type = mapping.get(i).get(2);
if (type != 0) {
int callSite = callSites[i];
callSites[j++] = 1 + convertToSigned(callSite - last);
callSites[j++] = convertToSigned(callSite - last);
last = callSite;
}
}
@ -212,6 +212,7 @@ class DebugInformationWriter {
private void writeCFG(RecordArray mapping) throws IOException {
writeUnsignedNumber(mapping.size());
writeRle(mapping.cut(0));
IntegerArray sizes = new IntegerArray(1);
IntegerArray files = new IntegerArray(1);
IntegerArray lines = new IntegerArray(1);
int lastFile = 0;
@ -222,15 +223,17 @@ class DebugInformationWriter {
continue;
}
int[] data = mapping.get(i).getArray(0);
sizes.add(data.length / 2);
for (int j = 0; j < data.length; j += 2) {
int file = data[j];
int line = data[j + 1];
files.add(file - lastFile);
lines.add(line - lastLine);
files.add(convertToSigned(file - lastFile));
lines.add(convertToSigned(line - lastLine));
lastFile = file;
lastLine = line;
}
}
writeRle(sizes.getAll());
writeRle(files.getAll());
writeRle(lines.getAll());
}
@ -267,16 +270,22 @@ class DebugInformationWriter {
}
if (count > 1) {
if (current > last) {
writeUnsignedNumber(convertToSigned(current - last) | 0);
writeUnsignedNumber(((current - last) << 1) | 0);
while (last < current) {
writeUnsignedNumber(array[last++]);
}
}
writeUnsignedNumber((convertToSigned(e) << 1) | 1);
writeUnsignedNumber(count);
writeUnsignedNumber((count << 1) | 1);
writeUnsignedNumber(e);
last = i;
}
}
if (array.length > last) {
writeUnsignedNumber(((array.length - last) << 1) | 0);
while (last < array.length) {
writeUnsignedNumber(array[last++]);
}
}
}
private void writeRelativeNumber(int number) throws IOException {

View File

@ -30,7 +30,6 @@ public class ExactMethodIterator {
private int methodIndex;
private int classId = -1;
private int methodId = -1;
private boolean endReached;
ExactMethodIterator(DebugInformation debugInformation) {
this.debugInformation = debugInformation;
@ -38,18 +37,15 @@ public class ExactMethodIterator {
}
public boolean isEndReached() {
return endReached;
return methodIndex >= debugInformation.methodMapping.size() &&
classIndex >= debugInformation.classMapping.size();
}
private void read() {
if (classIndex >= debugInformation.classMapping.size()) {
nextClassRecord();
} else if (methodIndex >= debugInformation.methodMapping.size()) {
nextMethodRecord();
} else if (classIndex < debugInformation.classMapping.size() &&
if (classIndex < debugInformation.classMapping.size() &&
methodIndex < debugInformation.methodMapping.size()) {
RecordArray.Record classRecord = debugInformation.classMapping.get(classIndex++);
RecordArray.Record methodRecord = debugInformation.methodMapping.get(methodIndex++);
RecordArray.Record classRecord = debugInformation.classMapping.get(classIndex);
RecordArray.Record methodRecord = debugInformation.methodMapping.get(methodIndex);
GeneratedLocation classLoc = DebugInformation.key(classRecord);
GeneratedLocation methodLoc = DebugInformation.key(methodRecord);
int cmp = classLoc.compareTo(methodLoc);
@ -61,8 +57,12 @@ public class ExactMethodIterator {
nextClassRecord();
nextMethodRecord();
}
} else if (classIndex < debugInformation.classMapping.size()) {
nextClassRecord();
} else if (methodIndex < debugInformation.methodMapping.size()) {
nextMethodRecord();
} else {
endReached = true;
throw new IllegalStateException("End already reached");
}
}
@ -110,11 +110,15 @@ public class ExactMethodIterator {
}
public int getExactMethodId() {
if (classId < 0 || methodId < 0) {
return -1;
}
return debugInformation.getExactMethodId(classId, methodId);
}
public MethodReference getExactMethod() {
return new MethodReference(getClassName(), getMethod());
int methodId = getExactMethodId();
return methodId >= 0 ? debugInformation.getExactMethod(getExactMethodId()) : null;
}
public GeneratedLocation getLocation() {

View File

@ -28,7 +28,6 @@ public class SourceLocationIterator {
private GeneratedLocation location;
private int fileId = -1;
private int line = -1;
private boolean endReached;
SourceLocationIterator(DebugInformation debugInformation) {
this.debugInformation = debugInformation;
@ -36,18 +35,15 @@ public class SourceLocationIterator {
}
public boolean isEndReached() {
return endReached;
return fileIndex >= debugInformation.fileMapping.size() &&
lineIndex >= debugInformation.lineMapping.size();
}
private void read() {
if (lineIndex >= debugInformation.lineMapping.size()) {
nextFileRecord();
} else if (fileIndex >= debugInformation.fileMapping.size()) {
nextLineRecord();
} else if (fileIndex < debugInformation.fileMapping.size() &&
if (fileIndex < debugInformation.fileMapping.size() &&
lineIndex < debugInformation.lineMapping.size()) {
RecordArray.Record fileRecord = debugInformation.fileMapping.get(fileIndex++);
RecordArray.Record lineRecord = debugInformation.lineMapping.get(lineIndex++);
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);
@ -59,8 +55,12 @@ public class SourceLocationIterator {
nextFileRecord();
nextLineRecord();
}
} else if (fileIndex < debugInformation.fileMapping.size()) {
nextFileRecord();
} else if (lineIndex < debugInformation.lineMapping.size()) {
nextLineRecord();
} else {
endReached = true;
throw new IllegalStateException("End already reached");
}
}