Introduces another approach for setting temporary breakpoints at

methods' start lines when stepping in, due to bug in google chrome:
http://code.google.com/p/chromium/issues/detail?id=407105
This commit is contained in:
konsoletyper 2014-08-27 18:05:38 +04:00
parent 7cb3ce70c3
commit 7e1ff76c5d
4 changed files with 76 additions and 13 deletions

View File

@ -27,21 +27,26 @@ public class RecordArray {
private int[] data;
private int[] substart;
private int[] subdata;
private int size;
RecordArray(int recordSize, int arraysPerRecord, int[] data, int[] substart, int[] subdata) {
RecordArray(int recordSize, int arraysPerRecord, int size, int[] data, int[] substart, int[] subdata) {
this.recordSize = recordSize;
this.arraysPerRecord = arraysPerRecord;
this.size = size;
this.data = data;
this.substart = substart;
this.subdata = subdata;
}
public Record get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index " + index + " is outside of [0; " + size + ")");
}
return new Record(index * recordSize, index * arraysPerRecord);
}
public int size() {
return data.length / recordSize;
return size;
}
public int getRecordSize() {

View File

@ -22,6 +22,7 @@ package org.teavm.common;
public class RecordArrayBuilder {
private int recordSize;
private int arraysPerRecord;
private int size;
private IntegerArray data = new IntegerArray(1);
private IntegerArray substart = new IntegerArray(1);
private IntegerArray subdata = new IntegerArray(1);
@ -33,6 +34,9 @@ public class RecordArrayBuilder {
}
public Record get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index " + index + " is outside of [0; " + size + ")");
}
return new Record(index * recordSize, index * arraysPerRecord);
}
@ -45,11 +49,12 @@ public class RecordArrayBuilder {
for (int i = 0; i < arraysPerRecord; ++i) {
substart.add(-1);
}
++size;
return new Record(offset, arrayOffset);
}
public int size() {
return data.size() / recordSize;
return size;
}
public int getRecordSize() {
@ -71,7 +76,7 @@ public class RecordArrayBuilder {
}
builtSubstart[i + 1] = builtSubdata.size();
}
return new RecordArray(recordSize, arraysPerRecord, data.getAll(), builtSubstart, builtSubdata.getAll());
return new RecordArray(recordSize, arraysPerRecord, size, data.getAll(), builtSubstart, builtSubdata.getAll());
}
public class Record {

View File

@ -18,6 +18,8 @@ package org.teavm.debugging;
import java.io.*;
import java.util.*;
import org.teavm.common.IntegerArray;
import org.teavm.common.RecordArray;
import org.teavm.common.RecordArrayBuilder;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference;
@ -45,6 +47,7 @@ public class DebugInformation {
Mapping lineMapping;
Mapping callSiteMapping;
MultiMapping[] variableMappings;
RecordArray[] lineCallSites;
CFG[] controlFlowGraphs;
List<ClassMetadata> classesMetadata;
MethodEntrances methodEntrances;
@ -258,6 +261,24 @@ public class DebugInformation {
}
}
public MethodReference[] getCallSites(SourceLocation location) {
Integer fileIndex = fileNameMap.get(location.getFileName());
if (fileIndex == null) {
return new MethodReference[0];
}
RecordArray mapping = lineCallSites[fileIndex];
if (location.getLine() >= mapping.size()) {
return new MethodReference[0];
}
int[] callSiteIds = mapping.get(location.getLine()).getArray(0);
MethodReference[] methods = new MethodReference[callSiteIds.length];
for (int i = 0; i < callSiteIds.length; ++i) {
int exactMethodId = callSiteMapping.values[callSiteIds[i]];
methods[i] = getExactMethod(exactMethodId);
}
return methods;
}
private <T> T componentByKey(Mapping mapping, T[] values, GeneratedLocation location) {
int keyIndex = indexByKey(mapping, location);
int valueIndex = keyIndex >= 0 ? mapping.values[keyIndex] : -1;
@ -283,6 +304,11 @@ public class DebugInformation {
return index >= 0 ? index : -index - 2;
}
private int valueByKey(Mapping mapping, GeneratedLocation location) {
int index = indexByKey(mapping, location);
return index >= 0 ? mapping.values[index] : -1;
}
private int indexByKey(MultiMapping mapping, GeneratedLocation location) {
int index = Collections.binarySearch(mapping.keyList(), location);
return index >= 0 ? index : -index - 2;
@ -307,6 +333,7 @@ public class DebugInformation {
rebuildFileDescriptions();
rebuildEntrances();
rebuildMethodTree();
rebuildLineCallSites();
}
void rebuildMaps() {
@ -439,6 +466,32 @@ public class DebugInformation {
return exactMethodMap.get(entry);
}
private void rebuildLineCallSites() {
lineCallSites = new RecordArray[fileNames.length];
RecordArrayBuilder[] builders = new RecordArrayBuilder[fileNames.length];
for (int i = 0; i < lineCallSites.length; ++i) {
builders[i] = new RecordArrayBuilder(0, 1);
}
for (int i = 0; i < callSiteMapping.lines.length; ++i) {
GeneratedLocation loc = callSiteMapping.key(i);
int methodId = callSiteMapping.values[i];
if (methodId >= 0) {
int line = valueByKey(lineMapping, loc);
int fileId = valueByKey(fileMapping, loc);
if (fileId >= 0 && line >= 0) {
RecordArrayBuilder builder = builders[fileId];
while (builder.size() <= line) {
builder.add();
}
builder.get(line).getArray(0).add(i);
}
}
}
for (int i = 0; i < lineCallSites.length; ++i) {
lineCallSites[i] = builders[i].build();
}
}
class MethodEntrancesBuilder {
int[] start;
IntegerArray data;

View File

@ -98,18 +98,18 @@ public class Debugger {
for (CallFrame frame : callStack) {
boolean exits;
String script = frame.originalLocation.getScript();
GeneratedLocation genLoc = new GeneratedLocation(frame.originalLocation.getLine(),
frame.originalLocation.getColumn());
DebugInformation debugInfo = debugInformationMap.get(script);
if (frame.getLocation() != null && debugInfo != null) {
exits = false;
MethodReference callMethod = debugInfo.getCallSite(genLoc);
if (frame.getLocation() != null && frame.getLocation().getFileName() != null &&
frame.getLocation().getLine() >= 0 && debugInfo != null) {
MethodReference[] callMethods = debugInfo.getCallSites(frame.getLocation());
exits = addFollowing(debugInfo, frame.getLocation(), script, new HashSet<SourceLocation>(),
successors);
if (enterMethod && callMethod != null) {
for (MethodReference potentialMethod : debugInfo.getOverridingMethods(callMethod)) {
for (GeneratedLocation loc : debugInfo.getMethodEntrances(potentialMethod)) {
successors.add(new JavaScriptLocation(script, loc.getLine(), loc.getColumn()));
if (enterMethod) {
for (MethodReference callMethod : callMethods) {
for (MethodReference potentialMethod : debugInfo.getOverridingMethods(callMethod)) {
for (GeneratedLocation loc : debugInfo.getMethodEntrances(potentialMethod)) {
successors.add(new JavaScriptLocation(script, loc.getLine(), loc.getColumn()));
}
}
}
}