From 31b589564041af6028ed36ecdb604d255458f111 Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Sat, 30 Aug 2014 19:13:14 +0400 Subject: [PATCH] Refactoring of debug information reader/writer --- .../org/teavm/common/RecordArrayBuilder.java | 8 +- .../information/DebugInformation.java | 17 +- .../information/DebugInformationBuilder.java | 9 +- .../information/DebugInformationReader.java | 229 ++++++++++++------ .../information/DebugInformationWriter.java | 39 +-- .../information/ExactMethodIterator.java | 26 +- .../information/SourceLocationIterator.java | 20 +- 7 files changed, 218 insertions(+), 130 deletions(-) diff --git a/teavm-core/src/main/java/org/teavm/common/RecordArrayBuilder.java b/teavm-core/src/main/java/org/teavm/common/RecordArrayBuilder.java index 6173375f6..c8fb07a77 100644 --- a/teavm-core/src/main/java/org/teavm/common/RecordArrayBuilder.java +++ b/teavm-core/src/main/java/org/teavm/common/RecordArrayBuilder.java @@ -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; } diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformation.java b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformation.java index ae3a801f5..da71b8112 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformation.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformation.java @@ -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() { diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationBuilder.java b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationBuilder.java index 87f7bbef1..0d125f4aa 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationBuilder.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationBuilder.java @@ -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(); diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationReader.java b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationReader.java index cfcbb2543..084f41582 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationReader.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationReader.java @@ -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); - } - 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(); - } + private RecordArray readCFG() throws IOException { + RecordArrayBuilder builder = new RecordArrayBuilder(1, 1); + int size = readUnsignedNumber(); + for (int i = 0; i < size; ++i) { + builder.add(); + } + 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; } } - offsets.add(i); - DebugInformation.CFG cfg = new DebugInformation.CFG(); - cfg.offsets = offsets.getAll(); - cfg.lines = lines; - cfg.files = files; - return cfg; + int[] sizes = readRle(nonEmptyItems); + int j = 0; + int totalSize = 0; + for (int sz : sizes) { + totalSize += sz; + } + 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(); - int last = 0; - for (int i = 0; i < lines.length; ++i) { - last += lines[i]; - lines[i] = last; + 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 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; + } + last += columns[i]; + columns[i] = last; } - int[] values = new int[lines.length]; - resetRelativeNumber(); + 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,17 +268,21 @@ 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(); - } - n = processSign(n >>> 1); - while (count-- > 0) { - array[i++] = n; + 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(); + } + } else { + int n = readUnsignedNumber(); + while (count-- > 0) { + array[i++] = n; + } } } return array; diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationWriter.java b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationWriter.java index 6e6758667..cffc1c58c 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationWriter.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationWriter.java @@ -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 { diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/ExactMethodIterator.java b/teavm-core/src/main/java/org/teavm/debugging/information/ExactMethodIterator.java index e957840b7..18a6e1e21 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/ExactMethodIterator.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/ExactMethodIterator.java @@ -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() { diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/SourceLocationIterator.java b/teavm-core/src/main/java/org/teavm/debugging/information/SourceLocationIterator.java index 32451f187..db1af520a 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/SourceLocationIterator.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/SourceLocationIterator.java @@ -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"); } }