mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
JS: preserve stack trace items when agressive inlining enabled
This commit is contained in:
parent
abf90e8b5f
commit
4ef231c7fa
|
@ -497,6 +497,7 @@ class StatementGenerator implements InstructionVisitor {
|
|||
} else {
|
||||
stmt = Statement.assign(null, invocationExpr);
|
||||
}
|
||||
invocationExpr.setLocation(currentLocation);
|
||||
stmt.setLocation(currentLocation);
|
||||
stmt.setAsync(async);
|
||||
async = false;
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Deque;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Predicate;
|
||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
||||
|
@ -38,6 +39,7 @@ import org.teavm.interop.PlatformMarker;
|
|||
import org.teavm.model.AnnotationReader;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.InliningInfo;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
@ -62,6 +64,7 @@ public class RenderingContext {
|
|||
private final Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
|
||||
private boolean minifying;
|
||||
private ClassInitializerInfo classInitializerInfo;
|
||||
private TextLocation lastEmittedLocation = TextLocation.EMPTY;
|
||||
|
||||
public RenderingContext(DebugInformationEmitter debugEmitter,
|
||||
ClassReaderSource initialClassSource, ListableClassReaderSource classSource,
|
||||
|
@ -128,11 +131,11 @@ public class RenderingContext {
|
|||
LocationStackEntry prevEntry = locationStack.peek();
|
||||
if (location != null) {
|
||||
if (prevEntry == null || !location.equals(prevEntry.location)) {
|
||||
debugEmitter.emitLocation(location.getFileName(), location.getLine());
|
||||
emitLocation(location);
|
||||
}
|
||||
} else {
|
||||
if (prevEntry != null) {
|
||||
debugEmitter.emitLocation(null, -1);
|
||||
emitLocation(TextLocation.EMPTY);
|
||||
}
|
||||
}
|
||||
locationStack.push(new LocationStackEntry(location));
|
||||
|
@ -143,13 +146,64 @@ public class RenderingContext {
|
|||
LocationStackEntry entry = locationStack.peek();
|
||||
if (entry != null) {
|
||||
if (!entry.location.equals(prevEntry.location)) {
|
||||
debugEmitter.emitLocation(entry.location.getFileName(), entry.location.getLine());
|
||||
emitLocation(entry.location);
|
||||
}
|
||||
} else {
|
||||
debugEmitter.emitLocation(null, -1);
|
||||
emitLocation(TextLocation.EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
private void emitLocation(TextLocation location) {
|
||||
if (lastEmittedLocation.equals(location)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fileName = lastEmittedLocation.getFileName();
|
||||
int lineNumber = lastEmittedLocation.getLine();
|
||||
if (lastEmittedLocation.getInlining() != location.getInlining()) {
|
||||
InliningInfo[] newPath = location.getInliningPath();
|
||||
InliningInfo[] prevPath = lastEmittedLocation.getInliningPath();
|
||||
|
||||
InliningInfo lastCommonInlining = null;
|
||||
int pathIndex = 0;
|
||||
while (pathIndex < prevPath.length && pathIndex < newPath.length
|
||||
&& prevPath[pathIndex].equals(newPath[pathIndex])) {
|
||||
lastCommonInlining = prevPath[pathIndex++];
|
||||
}
|
||||
|
||||
InliningInfo prevInlining = lastEmittedLocation.getInlining();
|
||||
while (prevInlining != lastCommonInlining) {
|
||||
debugEmitter.exitLocation();
|
||||
fileName = prevInlining.getFileName();
|
||||
lineNumber = prevInlining.getLine();
|
||||
prevInlining = prevInlining.getParent();
|
||||
}
|
||||
|
||||
while (pathIndex < newPath.length) {
|
||||
InliningInfo inlining = newPath[pathIndex++];
|
||||
emitSimpleLocation(fileName, lineNumber, inlining.getFileName(), inlining.getLine());
|
||||
fileName = null;
|
||||
lineNumber = -1;
|
||||
|
||||
debugEmitter.enterLocation();
|
||||
debugEmitter.emitClass(inlining.getMethod().getClassName());
|
||||
debugEmitter.emitMethod(inlining.getMethod().getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
emitSimpleLocation(fileName, lineNumber, location.getFileName(), location.getLine());
|
||||
lastEmittedLocation = location;
|
||||
}
|
||||
|
||||
|
||||
private void emitSimpleLocation(String fileName, int lineNumber, String newFileName, int newLineNumber) {
|
||||
if (Objects.equals(fileName, newFileName) && lineNumber == newLineNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
debugEmitter.emitLocation(newFileName, newLineNumber);
|
||||
}
|
||||
|
||||
public boolean isMinifying() {
|
||||
return minifying;
|
||||
}
|
||||
|
|
98
core/src/main/java/org/teavm/cache/AstIO.java
vendored
98
core/src/main/java/org/teavm/cache/AstIO.java
vendored
|
@ -250,47 +250,63 @@ public class AstIO {
|
|||
return;
|
||||
}
|
||||
|
||||
InliningInfo lastCommonInlining = null;
|
||||
InliningInfo[] prevPath = lastLocation.getInliningPath();
|
||||
InliningInfo[] newPath = location.getInliningPath();
|
||||
int pathIndex = 0;
|
||||
while (pathIndex < prevPath.length && pathIndex < newPath.length
|
||||
&& prevPath[pathIndex].equals(newPath[pathIndex])) {
|
||||
lastCommonInlining = prevPath[pathIndex++];
|
||||
}
|
||||
String fileName = lastLocation.getFileName();
|
||||
int lineNumber = lastLocation.getLine();
|
||||
|
||||
InliningInfo prevInlining = lastLocation.getInlining();
|
||||
while (prevInlining != lastCommonInlining) {
|
||||
output.writeUnsigned(124);
|
||||
prevInlining = prevInlining.getParent();
|
||||
}
|
||||
if (location.getInlining() != lastLocation.getInlining()) {
|
||||
InliningInfo lastCommonInlining = null;
|
||||
InliningInfo[] prevPath = lastLocation.getInliningPath();
|
||||
InliningInfo[] newPath = location.getInliningPath();
|
||||
int pathIndex = 0;
|
||||
while (pathIndex < prevPath.length && pathIndex < newPath.length
|
||||
&& prevPath[pathIndex].equals(newPath[pathIndex])) {
|
||||
lastCommonInlining = prevPath[pathIndex++];
|
||||
}
|
||||
|
||||
while (pathIndex < newPath.length) {
|
||||
InliningInfo inlining = newPath[pathIndex++];
|
||||
MethodReference method = inlining.getMethod();
|
||||
output.writeUnsigned(inlining.isEmpty() ? 122 : 123);
|
||||
output.writeUnsigned(symbolTable.lookup(method.getClassName()));
|
||||
output.writeUnsigned(symbolTable.lookup(method.getDescriptor().toString()));
|
||||
if (!inlining.isEmpty()) {
|
||||
output.writeUnsigned(fileTable.lookup(inlining.getFileName()));
|
||||
output.writeUnsigned(inlining.getLine());
|
||||
InliningInfo prevInlining = location.getInlining();
|
||||
while (prevInlining != lastCommonInlining) {
|
||||
output.writeUnsigned(123);
|
||||
fileName = prevInlining.getFileName();
|
||||
lineNumber = prevInlining.getLine();
|
||||
prevInlining = prevInlining.getParent();
|
||||
}
|
||||
|
||||
while (pathIndex < newPath.length) {
|
||||
InliningInfo inlining = newPath[pathIndex++];
|
||||
writeSimpleLocation(fileName, lineNumber, inlining.getFileName(), inlining.getLine());
|
||||
fileName = null;
|
||||
lineNumber = -1;
|
||||
|
||||
output.writeUnsigned(124);
|
||||
MethodReference method = inlining.getMethod();
|
||||
output.writeUnsigned(symbolTable.lookup(method.getClassName()));
|
||||
output.writeUnsigned(symbolTable.lookup(method.getDescriptor().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (location.isEmpty()) {
|
||||
output.writeUnsigned(127);
|
||||
} else if (!lastLocation.isEmpty() && lastLocation.getFileName().equals(location.getFileName())) {
|
||||
output.writeUnsigned(126);
|
||||
output.writeSigned(location.getLine() - lastLocation.getLine());
|
||||
} else {
|
||||
output.writeUnsigned(125);
|
||||
output.writeUnsigned(fileTable.lookup(location.getFileName()));
|
||||
output.writeUnsigned(location.getLine());
|
||||
}
|
||||
writeSimpleLocation(fileName, lineNumber, location.getFileName(), location.getLine());
|
||||
|
||||
lastLocation = location;
|
||||
}
|
||||
|
||||
private void writeSimpleLocation(String fileName, int lineNumber, String newFileName, int newLineNumber)
|
||||
throws IOException {
|
||||
if (Objects.equals(fileName, newFileName) && lineNumber == newLineNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newFileName == null) {
|
||||
output.writeUnsigned(127);
|
||||
} else if (fileName != null && fileName.equals(newFileName)) {
|
||||
output.writeUnsigned(126);
|
||||
output.writeSigned(newLineNumber - lineNumber);
|
||||
} else {
|
||||
output.writeUnsigned(125);
|
||||
output.writeUnsigned(fileTable.lookup(newFileName));
|
||||
output.writeUnsigned(newLineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSequence(List<Statement> sequence) throws IOException {
|
||||
output.writeUnsigned(sequence.size());
|
||||
for (Statement part : sequence) {
|
||||
|
@ -741,25 +757,17 @@ public class AstIO {
|
|||
lastReadLocation = new TextLocation(fileTable.at(input.readUnsigned()), input.readUnsigned(),
|
||||
lastReadInlining);
|
||||
break;
|
||||
case 122:
|
||||
case 123: {
|
||||
case 124: {
|
||||
String className = symbolTable.at(input.readUnsigned());
|
||||
MethodDescriptor methodDescriptor = MethodDescriptor.parse(symbolTable.at(input.readUnsigned()));
|
||||
methodDescriptor = referenceCache.getCached(methodDescriptor);
|
||||
String fileName;
|
||||
int lineNumber;
|
||||
if (type == 122) {
|
||||
fileName = fileTable.at(input.readUnsigned());
|
||||
lineNumber = input.readUnsigned();
|
||||
} else {
|
||||
fileName = null;
|
||||
lineNumber = -1;
|
||||
}
|
||||
lastReadInlining = new InliningInfo(referenceCache.getCached(className, methodDescriptor),
|
||||
fileName, lineNumber, lastReadInlining);
|
||||
lastReadLocation.getFileName(), lastReadLocation.getLine(), lastReadInlining);
|
||||
lastReadLocation = new TextLocation(null, -1, lastReadInlining);
|
||||
break;
|
||||
}
|
||||
case 124:
|
||||
case 123:
|
||||
lastReadLocation = new TextLocation(lastReadInlining.getFileName(), lastReadInlining.getLine());
|
||||
lastReadInlining = lastReadInlining.getParent();
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.BasicBlockReader;
|
||||
import org.teavm.model.FieldReference;
|
||||
|
@ -208,7 +209,7 @@ public class ProgramIO {
|
|||
}
|
||||
|
||||
InliningInfo inliningInfo = null;
|
||||
TextLocation location = null;
|
||||
TextLocation location = TextLocation.EMPTY;
|
||||
insnLoop: while (true) {
|
||||
int insnType = data.readUnsigned();
|
||||
switch (insnType) {
|
||||
|
@ -228,24 +229,16 @@ public class ProgramIO {
|
|||
location = new TextLocation(location.getFileName(), line, inliningInfo);
|
||||
break;
|
||||
}
|
||||
case 124:
|
||||
case 125: {
|
||||
String className = symbolTable.at(data.readUnsigned());
|
||||
MethodDescriptor methodDescriptor = parseMethodDescriptor(symbolTable.at(data.readUnsigned()));
|
||||
String fileName;
|
||||
int lineNumber;
|
||||
if (insnType == 125) {
|
||||
fileName = fileTable.at(data.readUnsigned());
|
||||
lineNumber = data.readUnsigned();
|
||||
} else {
|
||||
fileName = null;
|
||||
lineNumber = -1;
|
||||
}
|
||||
inliningInfo = new InliningInfo(createMethodReference(className, methodDescriptor),
|
||||
fileName, lineNumber, inliningInfo);
|
||||
location.getFileName(), location.getLine(), inliningInfo);
|
||||
location = new TextLocation(null, -1, inliningInfo);
|
||||
break;
|
||||
}
|
||||
case 126:
|
||||
location = new TextLocation(inliningInfo.getFileName(), inliningInfo.getLine());
|
||||
inliningInfo = inliningInfo.getParent();
|
||||
break;
|
||||
default: {
|
||||
|
@ -276,51 +269,65 @@ public class ProgramIO {
|
|||
newLocation = TextLocation.EMPTY;
|
||||
}
|
||||
|
||||
InliningInfo lastCommonInlining = null;
|
||||
InliningInfo[] prevPath = location.getInliningPath();
|
||||
InliningInfo[] newPath = newLocation.getInliningPath();
|
||||
int pathIndex = 0;
|
||||
while (pathIndex < prevPath.length && pathIndex < newPath.length
|
||||
&& prevPath[pathIndex].equals(newPath[pathIndex])) {
|
||||
lastCommonInlining = prevPath[pathIndex++];
|
||||
}
|
||||
String fileName = location.getFileName();
|
||||
int lineNumber = location.getLine();
|
||||
|
||||
InliningInfo prevInlining = location.getInlining();
|
||||
while (prevInlining != lastCommonInlining) {
|
||||
output.writeUnsigned(126);
|
||||
prevInlining = prevInlining.getParent();
|
||||
}
|
||||
if (newLocation.getInlining() != location.getInlining()) {
|
||||
InliningInfo lastCommonInlining = null;
|
||||
InliningInfo[] prevPath = location.getInliningPath();
|
||||
InliningInfo[] newPath = newLocation.getInliningPath();
|
||||
int pathIndex = 0;
|
||||
while (pathIndex < prevPath.length && pathIndex < newPath.length
|
||||
&& prevPath[pathIndex].equals(newPath[pathIndex])) {
|
||||
lastCommonInlining = prevPath[pathIndex++];
|
||||
}
|
||||
|
||||
while (pathIndex < newPath.length) {
|
||||
InliningInfo inlining = newPath[pathIndex++];
|
||||
MethodReference method = inlining.getMethod();
|
||||
output.writeUnsigned(inlining.isEmpty() ? 124 : 125);
|
||||
output.writeUnsigned(symbolTable.lookup(method.getClassName()));
|
||||
output.writeUnsigned(symbolTable.lookup(method.getDescriptor().toString()));
|
||||
if (!inlining.isEmpty()) {
|
||||
output.writeUnsigned(fileTable.lookup(inlining.getFileName()));
|
||||
output.writeUnsigned(inlining.getLine());
|
||||
InliningInfo prevInlining = location.getInlining();
|
||||
while (prevInlining != lastCommonInlining) {
|
||||
output.writeUnsigned(126);
|
||||
fileName = prevInlining.getFileName();
|
||||
lineNumber = prevInlining.getLine();
|
||||
prevInlining = prevInlining.getParent();
|
||||
}
|
||||
|
||||
while (pathIndex < newPath.length) {
|
||||
InliningInfo inlining = newPath[pathIndex++];
|
||||
writeSimpleLocation(fileName, lineNumber, inlining.getFileName(), inlining.getLine());
|
||||
fileName = null;
|
||||
lineNumber = -1;
|
||||
|
||||
output.writeUnsigned(125);
|
||||
MethodReference method = inlining.getMethod();
|
||||
output.writeUnsigned(symbolTable.lookup(method.getClassName()));
|
||||
output.writeUnsigned(symbolTable.lookup(method.getDescriptor().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (newLocation.isEmpty()) {
|
||||
output.writeUnsigned(1);
|
||||
} else {
|
||||
if (!location.isEmpty() && location.getFileName().equals(newLocation.getFileName())) {
|
||||
output.writeUnsigned(127);
|
||||
output.writeSigned(newLocation.getLine() - location.getLine());
|
||||
} else {
|
||||
output.writeUnsigned(2);
|
||||
output.writeUnsigned(fileTable.lookup(newLocation.getFileName()));
|
||||
output.writeUnsigned(newLocation.getLine());
|
||||
}
|
||||
}
|
||||
writeSimpleLocation(fileName, lineNumber, newLocation.getFileName(), newLocation.getLine());
|
||||
location = newLocation;
|
||||
} catch (IOException e) {
|
||||
throw new IOExceptionWrapper(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSimpleLocation(String fileName, int lineNumber, String newFileName, int newLineNumber)
|
||||
throws IOException {
|
||||
if (Objects.equals(fileName, newFileName) && lineNumber == newLineNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newFileName == null) {
|
||||
output.writeUnsigned(1);
|
||||
} else if (fileName != null && fileName.equals(newFileName)) {
|
||||
output.writeUnsigned(127);
|
||||
output.writeSigned(newLineNumber - lineNumber);
|
||||
} else {
|
||||
output.writeUnsigned(2);
|
||||
output.writeUnsigned(fileTable.lookup(newFileName));
|
||||
output.writeUnsigned(newLineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nop() {
|
||||
try {
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.debugging.information;
|
||||
|
||||
public class ClassNameIterator {
|
||||
private DebugInformation debugInformation;
|
||||
private int index;
|
||||
|
||||
ClassNameIterator(DebugInformation debugInformation) {
|
||||
this.debugInformation = debugInformation;
|
||||
}
|
||||
|
||||
public boolean isEndReached() {
|
||||
return index < debugInformation.classMapping.size();
|
||||
}
|
||||
|
||||
public GeneratedLocation getLocation() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
}
|
||||
return DebugInformation.key(debugInformation.classMapping.get(index));
|
||||
}
|
||||
|
||||
public int getClassNameId() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
}
|
||||
return debugInformation.classMapping.get(index).get(2);
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
int classNameId = getClassNameId();
|
||||
return classNameId >= 0 ? debugInformation.getClassName(classNameId) : null;
|
||||
}
|
||||
|
||||
public void next() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
}
|
||||
++index;
|
||||
}
|
||||
}
|
|
@ -38,10 +38,7 @@ public class DebugInformation {
|
|||
long[] exactMethods;
|
||||
Map<Long, Integer> exactMethodMap;
|
||||
RecordArray[] fileDescriptions;
|
||||
RecordArray fileMapping;
|
||||
RecordArray classMapping;
|
||||
RecordArray methodMapping;
|
||||
RecordArray lineMapping;
|
||||
Layer[] layers;
|
||||
RecordArray callSiteMapping;
|
||||
RecordArray statementStartMapping;
|
||||
RecordArray[] variableMappings;
|
||||
|
@ -69,14 +66,6 @@ public class DebugInformation {
|
|||
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];
|
||||
}
|
||||
|
@ -135,16 +124,12 @@ public class DebugInformation {
|
|||
return id != null ? id : -1;
|
||||
}
|
||||
|
||||
public ClassNameIterator iterateOverClassNames() {
|
||||
return new ClassNameIterator(this);
|
||||
public int layerCount() {
|
||||
return layers.length;
|
||||
}
|
||||
|
||||
public MethodIterator iterateOverMethods() {
|
||||
return new MethodIterator(this);
|
||||
}
|
||||
|
||||
public ExactMethodIterator iterateOverExactMethods() {
|
||||
return new ExactMethodIterator(this);
|
||||
public ExactMethodIterator iterateOverExactMethods(int layerIndex) {
|
||||
return new ExactMethodIterator(this, layers[layerIndex]);
|
||||
}
|
||||
|
||||
public Collection<GeneratedLocation> getGeneratedLocations(String fileName, int line) {
|
||||
|
@ -177,29 +162,67 @@ public class DebugInformation {
|
|||
return new SourceLocationIterator(this);
|
||||
}
|
||||
|
||||
private LayerSourceLocationIterator iterateOverSourceLocations(int layer) {
|
||||
return new LayerSourceLocationIterator(this, layers[layer]);
|
||||
}
|
||||
|
||||
public SourceLocation getSourceLocation(int line, int column) {
|
||||
return getSourceLocation(new GeneratedLocation(line, column));
|
||||
}
|
||||
|
||||
public SourceLocation getSourceLocation(int line, int column, int layerIndex) {
|
||||
return getSourceLocation(new GeneratedLocation(line, column), layerIndex);
|
||||
}
|
||||
|
||||
public SourceLocation getSourceLocation(GeneratedLocation generatedLocation) {
|
||||
String fileName = componentByKey(fileMapping, fileNames, generatedLocation);
|
||||
int lineNumberIndex = indexByKey(lineMapping, generatedLocation);
|
||||
int lineNumber = lineNumberIndex >= 0 ? lineMapping.get(lineNumberIndex).get(2) : -1;
|
||||
return getSourceLocation(generatedLocation, autodetectLayer(generatedLocation));
|
||||
}
|
||||
|
||||
public SourceLocation getSourceLocation(GeneratedLocation generatedLocation, int layerIndex) {
|
||||
if (layerIndex < 0 || layerIndex >= layers.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Layer layer = layers[layerIndex];
|
||||
String fileName = componentByKey(layer.fileMapping, fileNames, generatedLocation);
|
||||
int lineNumberIndex = indexByKey(layer.lineMapping, generatedLocation);
|
||||
int lineNumber = lineNumberIndex >= 0 ? layer.lineMapping.get(lineNumberIndex).get(2) : -1;
|
||||
return new SourceLocation(fileName, lineNumber);
|
||||
}
|
||||
|
||||
public MethodReference getMethodAt(GeneratedLocation generatedLocation) {
|
||||
String className = componentByKey(classMapping, classNames, generatedLocation);
|
||||
return getMethodAt(generatedLocation, autodetectLayer(generatedLocation));
|
||||
}
|
||||
|
||||
public MethodReference getMethodAt(GeneratedLocation generatedLocation, int layerIndex) {
|
||||
if (layerIndex < 0 || layerIndex >= layers.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Layer layer = layers[layerIndex];
|
||||
|
||||
String className = componentByKey(layer.classMapping, classNames, generatedLocation);
|
||||
if (className == null) {
|
||||
return null;
|
||||
}
|
||||
String method = componentByKey(methodMapping, methods, generatedLocation);
|
||||
String method = componentByKey(layer.methodMapping, methods, generatedLocation);
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
return referenceCache.getCached(className, referenceCache.parseDescriptorCached(method));
|
||||
}
|
||||
|
||||
private int autodetectLayer(GeneratedLocation generatedLocation) {
|
||||
int layerIndex = 0;
|
||||
for (int i = 1; i < layers.length; ++i) {
|
||||
if (componentByKey(layers[i].classMapping, classNames, generatedLocation) == null) {
|
||||
break;
|
||||
}
|
||||
layerIndex = i;
|
||||
}
|
||||
return layerIndex;
|
||||
}
|
||||
|
||||
public MethodReference getMethodAt(int line, int column) {
|
||||
return getMethodAt(new GeneratedLocation(line, column));
|
||||
}
|
||||
|
@ -460,16 +483,19 @@ public class DebugInformation {
|
|||
for (int i = 0; i < builders.length; ++i) {
|
||||
builders[i] = new RecordArrayBuilder(0, 1);
|
||||
}
|
||||
for (SourceLocationIterator iter = iterateOverSourceLocations(); !iter.isEndReached(); iter.next()) {
|
||||
if (iter.getFileNameId() >= 0 && iter.getLine() >= 0) {
|
||||
RecordArrayBuilder builder = builders[iter.getFileNameId()];
|
||||
while (builder.size() <= iter.getLine()) {
|
||||
builder.add();
|
||||
for (int layer = 0; layer < layers.length; ++layer) {
|
||||
for (LayerSourceLocationIterator iter = iterateOverSourceLocations(layer);
|
||||
!iter.isEndReached(); iter.next()) {
|
||||
if (iter.getFileNameId() >= 0 && iter.getLine() >= 0) {
|
||||
RecordArrayBuilder builder = builders[iter.getFileNameId()];
|
||||
while (builder.size() <= iter.getLine()) {
|
||||
builder.add();
|
||||
}
|
||||
GeneratedLocation loc = iter.getLocation();
|
||||
RecordArrayBuilder.SubArray array = builder.get(iter.getLine()).getArray(0);
|
||||
array.add(loc.getLine());
|
||||
array.add(loc.getColumn());
|
||||
}
|
||||
GeneratedLocation loc = iter.getLocation();
|
||||
RecordArrayBuilder.SubArray array = builder.get(iter.getLine()).getArray(0);
|
||||
array.add(loc.getLine());
|
||||
array.add(loc.getColumn());
|
||||
}
|
||||
}
|
||||
fileDescriptions = new RecordArray[builders.length];
|
||||
|
@ -486,7 +512,8 @@ public class DebugInformation {
|
|||
GeneratedLocation prevLocation = new GeneratedLocation(0, 0);
|
||||
MethodReference prevMethod = null;
|
||||
int prevMethodId = -1;
|
||||
for (ExactMethodIterator iter = iterateOverExactMethods(); !iter.isEndReached(); iter.next()) {
|
||||
RecordArray lineMapping = layers[0].lineMapping;
|
||||
for (ExactMethodIterator iter = iterateOverExactMethods(0); !iter.isEndReached(); iter.next()) {
|
||||
int id = iter.getExactMethodId();
|
||||
if (prevMethod != null) {
|
||||
int lineIndex = Math.max(0, indexByKey(lineMapping, prevLocation));
|
||||
|
@ -596,8 +623,9 @@ public class DebugInformation {
|
|||
GeneratedLocation loc = key(callSiteRec);
|
||||
int callSiteType = callSiteRec.get(2);
|
||||
if (callSiteType != DebuggerCallSite.NONE) {
|
||||
int line = valueByKey(lineMapping, loc);
|
||||
int fileId = valueByKey(fileMapping, loc);
|
||||
int layerIndex = autodetectLayer(loc);
|
||||
int line = valueByKey(layers[layerIndex].lineMapping, loc);
|
||||
int fileId = valueByKey(layers[layerIndex].fileMapping, loc);
|
||||
if (fileId >= 0 && line >= 0) {
|
||||
RecordArrayBuilder builder = builders[fileId];
|
||||
while (builder.size() <= line) {
|
||||
|
@ -699,4 +727,11 @@ public class DebugInformation {
|
|||
return references;
|
||||
}
|
||||
}
|
||||
|
||||
static class Layer {
|
||||
RecordArray fileMapping;
|
||||
RecordArray classMapping;
|
||||
RecordArray methodMapping;
|
||||
RecordArray lineMapping;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,23 +34,20 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
private List<Long> exactMethods = new ArrayList<>();
|
||||
private Map<Long, Integer> exactMethodMap = new HashMap<>();
|
||||
private RecordArrayBuilder statementStartMapping = new RecordArrayBuilder(2, 0);
|
||||
private RecordArrayBuilder fileMapping = new RecordArrayBuilder(3, 0);
|
||||
private RecordArrayBuilder lineMapping = new RecordArrayBuilder(3, 0);
|
||||
private RecordArrayBuilder classMapping = new RecordArrayBuilder(3, 0);
|
||||
private RecordArrayBuilder methodMapping = new RecordArrayBuilder(3, 0);
|
||||
private List<LayerBuilder> layers = new ArrayList<>();
|
||||
private LayerBuilder currentLayer;
|
||||
private int currentLayerIndex;
|
||||
private RecordArrayBuilder callSiteMapping = new RecordArrayBuilder(4, 0);
|
||||
private Map<Integer, RecordArrayBuilder> variableMappings = new HashMap<>();
|
||||
private MethodDescriptor currentMethod;
|
||||
private String currentClass;
|
||||
private String currentFileName;
|
||||
private int currentClassMetadata = -1;
|
||||
private List<ClassMetadata> classesMetadata = new ArrayList<>();
|
||||
private List<RecordArrayBuilder> cfgs = new ArrayList<>();
|
||||
private int currentLine;
|
||||
private ReferenceCache referenceCache;
|
||||
|
||||
public DebugInformationBuilder(ReferenceCache referenceCache) {
|
||||
this.referenceCache = referenceCache;
|
||||
currentLayer = new LayerBuilder();
|
||||
layers.add(currentLayer);
|
||||
}
|
||||
|
||||
public LocationProvider getLocationProvider() {
|
||||
|
@ -66,16 +63,32 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
public void emitLocation(String fileName, int line) {
|
||||
debugInformation = null;
|
||||
int fileIndex = files.index(fileName);
|
||||
if (!Objects.equals(currentFileName, fileName)) {
|
||||
add(fileMapping, fileIndex);
|
||||
currentFileName = fileName;
|
||||
if (!Objects.equals(currentLayer.currentFileName, fileName)) {
|
||||
add(currentLayer.fileMapping, fileIndex);
|
||||
currentLayer.currentFileName = fileName;
|
||||
}
|
||||
if (currentLine != line) {
|
||||
add(lineMapping, line);
|
||||
currentLine = line;
|
||||
if (currentLayer.currentLine != line) {
|
||||
add(currentLayer.lineMapping, line);
|
||||
currentLayer.currentLine = line;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterLocation() {
|
||||
if (++currentLayerIndex >= layers.size()) {
|
||||
layers.add(new LayerBuilder());
|
||||
}
|
||||
currentLayer = layers.get(currentLayerIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitLocation() {
|
||||
emitClass(null);
|
||||
emitMethod(null);
|
||||
emitLocation(null, -1);
|
||||
currentLayer = layers.get(--currentLayerIndex);
|
||||
}
|
||||
|
||||
private RecordArrayBuilder.Record add(RecordArrayBuilder builder) {
|
||||
if (builder.size() > 1) {
|
||||
RecordArrayBuilder.Record lastRecord = builder.get(builder.size() - 1);
|
||||
|
@ -99,9 +112,9 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
public void emitClass(String className) {
|
||||
debugInformation = null;
|
||||
int classIndex = classes.index(className);
|
||||
if (!Objects.equals(className, currentClass)) {
|
||||
add(classMapping, classIndex);
|
||||
currentClass = className;
|
||||
if (!Objects.equals(className, currentLayer.currentClass)) {
|
||||
add(currentLayer.classMapping, classIndex);
|
||||
currentLayer.currentClass = className;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,12 +122,12 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
public void emitMethod(MethodDescriptor method) {
|
||||
debugInformation = null;
|
||||
int methodIndex = methods.index(method != null ? method.toString() : null);
|
||||
if (!Objects.equals(method, currentMethod)) {
|
||||
add(methodMapping, methodIndex);
|
||||
currentMethod = method;
|
||||
if (!Objects.equals(method, currentLayer.currentMethod)) {
|
||||
add(currentLayer.methodMapping, methodIndex);
|
||||
currentLayer.currentMethod = method;
|
||||
}
|
||||
if (currentClass != null) {
|
||||
int classIndex = classes.index(currentClass);
|
||||
if (currentLayer.currentClass != null) {
|
||||
int classIndex = classes.index(currentLayer.currentClass);
|
||||
long fullIndex = ((long) classIndex << 32) | methodIndex;
|
||||
if (!exactMethodMap.containsKey(fullIndex)) {
|
||||
exactMethodMap.put(fullIndex, exactMethods.size());
|
||||
|
@ -283,10 +296,19 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
debugInformation.exactMethodMap = new HashMap<>(exactMethodMap);
|
||||
|
||||
debugInformation.statementStartMapping = statementStartMapping.build();
|
||||
debugInformation.fileMapping = compress(fileMapping).build();
|
||||
debugInformation.lineMapping = compress(lineMapping).build();
|
||||
debugInformation.classMapping = compress(classMapping).build();
|
||||
debugInformation.methodMapping = compress(methodMapping).build();
|
||||
|
||||
DebugInformation.Layer[] builtLayers = new DebugInformation.Layer[layers.size()];
|
||||
for (int i = 0; i < builtLayers.length; ++i) {
|
||||
LayerBuilder layerBuilder = layers.get(i);
|
||||
DebugInformation.Layer builtLayer = new DebugInformation.Layer();
|
||||
builtLayer.fileMapping = compress(layerBuilder.fileMapping).build();
|
||||
builtLayer.lineMapping = compress(layerBuilder.lineMapping).build();
|
||||
builtLayer.classMapping = compress(layerBuilder.classMapping).build();
|
||||
builtLayer.methodMapping = compress(layerBuilder.methodMapping).build();
|
||||
builtLayers[i] = builtLayer;
|
||||
}
|
||||
debugInformation.layers = builtLayers;
|
||||
|
||||
debugInformation.callSiteMapping = callSiteMapping.build();
|
||||
debugInformation.variableMappings = new RecordArray[variableNames.list.size()];
|
||||
for (int var : variableMappings.keySet()) {
|
||||
|
@ -339,7 +361,7 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
}
|
||||
|
||||
public String[] getItems() {
|
||||
return list.toArray(new String[list.size()]);
|
||||
return list.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public Map<String, Integer> getIndexes() {
|
||||
|
@ -352,4 +374,15 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
String jsName;
|
||||
Map<Integer, Integer> fieldMap = new HashMap<>();
|
||||
}
|
||||
|
||||
static class LayerBuilder {
|
||||
private RecordArrayBuilder fileMapping = new RecordArrayBuilder(3, 0);
|
||||
private RecordArrayBuilder lineMapping = new RecordArrayBuilder(3, 0);
|
||||
private RecordArrayBuilder classMapping = new RecordArrayBuilder(3, 0);
|
||||
private RecordArrayBuilder methodMapping = new RecordArrayBuilder(3, 0);
|
||||
private MethodDescriptor currentMethod;
|
||||
private String currentClass;
|
||||
private String currentFileName;
|
||||
private int currentLine;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,10 @@ public interface DebugInformationEmitter {
|
|||
|
||||
void emitLocation(String fileName, int line);
|
||||
|
||||
void enterLocation();
|
||||
|
||||
void exitLocation();
|
||||
|
||||
void emitStatementStart();
|
||||
|
||||
void emitMethod(MethodDescriptor method);
|
||||
|
|
|
@ -43,10 +43,15 @@ class DebugInformationReader {
|
|||
debugInfo.methods = readStrings();
|
||||
debugInfo.variableNames = readStrings();
|
||||
debugInfo.exactMethods = readExactMethods();
|
||||
debugInfo.fileMapping = readMapping();
|
||||
debugInfo.lineMapping = readMapping();
|
||||
debugInfo.classMapping = readMapping();
|
||||
debugInfo.methodMapping = readMapping();
|
||||
debugInfo.layers = new DebugInformation.Layer[input.read()];
|
||||
for (int i = 0; i < debugInfo.layers.length; ++i) {
|
||||
DebugInformation.Layer layer = new DebugInformation.Layer();
|
||||
layer.fileMapping = readMapping();
|
||||
layer.lineMapping = readMapping();
|
||||
layer.classMapping = readMapping();
|
||||
layer.methodMapping = readMapping();
|
||||
debugInfo.layers[i] = layer;
|
||||
}
|
||||
debugInfo.statementStartMapping = readBooleanMapping();
|
||||
debugInfo.callSiteMapping = readCallSiteMapping();
|
||||
debugInfo.variableMappings = readVariableMappings(debugInfo.variableNames.length);
|
||||
|
|
|
@ -42,10 +42,13 @@ class DebugInformationWriter {
|
|||
writeStringArray(debugInfo.variableNames);
|
||||
writeExactMethods(debugInfo.exactMethods);
|
||||
|
||||
writeMapping(debugInfo.fileMapping);
|
||||
writeMapping(debugInfo.lineMapping);
|
||||
writeMapping(debugInfo.classMapping);
|
||||
writeMapping(debugInfo.methodMapping);
|
||||
output.write(debugInfo.layers.length);
|
||||
for (DebugInformation.Layer layer : debugInfo.layers) {
|
||||
writeMapping(layer.fileMapping);
|
||||
writeMapping(layer.lineMapping);
|
||||
writeMapping(layer.classMapping);
|
||||
writeMapping(layer.methodMapping);
|
||||
}
|
||||
writeLinesAndColumns(debugInfo.statementStartMapping);
|
||||
writeCallSiteMapping(debugInfo.callSiteMapping);
|
||||
writeVariableMappings(debugInfo);
|
||||
|
|
|
@ -24,6 +24,16 @@ public class DummyDebugInformationEmitter implements DebugInformationEmitter {
|
|||
public void emitLocation(String fileName, int line) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterLocation() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitLocation() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitMethod(MethodDescriptor method) {
|
||||
}
|
||||
|
|
|
@ -21,29 +21,30 @@ import org.teavm.model.MethodReference;
|
|||
|
||||
public class ExactMethodIterator {
|
||||
private DebugInformation debugInformation;
|
||||
private DebugInformation.Layer layer;
|
||||
private GeneratedLocation location;
|
||||
private int classIndex;
|
||||
private int methodIndex;
|
||||
private int classId = -1;
|
||||
private int methodId = -1;
|
||||
|
||||
ExactMethodIterator(DebugInformation debugInformation) {
|
||||
ExactMethodIterator(DebugInformation debugInformation, DebugInformation.Layer layer) {
|
||||
this.debugInformation = debugInformation;
|
||||
this.layer = layer;
|
||||
if (!isEndReached()) {
|
||||
read();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEndReached() {
|
||||
return methodIndex >= debugInformation.methodMapping.size()
|
||||
&& classIndex >= debugInformation.classMapping.size();
|
||||
return methodIndex >= layer.methodMapping.size() && classIndex >= layer.classMapping.size();
|
||||
}
|
||||
|
||||
private void read() {
|
||||
if (classIndex < debugInformation.classMapping.size()
|
||||
&& methodIndex < debugInformation.methodMapping.size()) {
|
||||
RecordArray.Record classRecord = debugInformation.classMapping.get(classIndex);
|
||||
RecordArray.Record methodRecord = debugInformation.methodMapping.get(methodIndex);
|
||||
if (classIndex < layer.classMapping.size()
|
||||
&& methodIndex < layer.methodMapping.size()) {
|
||||
RecordArray.Record classRecord = layer.classMapping.get(classIndex);
|
||||
RecordArray.Record methodRecord = layer.methodMapping.get(methodIndex);
|
||||
GeneratedLocation classLoc = DebugInformation.key(classRecord);
|
||||
GeneratedLocation methodLoc = DebugInformation.key(methodRecord);
|
||||
int cmp = classLoc.compareTo(methodLoc);
|
||||
|
@ -55,9 +56,9 @@ public class ExactMethodIterator {
|
|||
nextClassRecord();
|
||||
nextMethodRecord();
|
||||
}
|
||||
} else if (classIndex < debugInformation.classMapping.size()) {
|
||||
} else if (classIndex < layer.classMapping.size()) {
|
||||
nextClassRecord();
|
||||
} else if (methodIndex < debugInformation.methodMapping.size()) {
|
||||
} else if (methodIndex < layer.methodMapping.size()) {
|
||||
nextMethodRecord();
|
||||
} else {
|
||||
throw new IllegalStateException("End already reached");
|
||||
|
@ -65,13 +66,13 @@ public class ExactMethodIterator {
|
|||
}
|
||||
|
||||
private void nextClassRecord() {
|
||||
RecordArray.Record record = debugInformation.classMapping.get(classIndex++);
|
||||
RecordArray.Record record = layer.classMapping.get(classIndex++);
|
||||
classId = record.get(2);
|
||||
location = DebugInformation.key(record);
|
||||
}
|
||||
|
||||
private void nextMethodRecord() {
|
||||
RecordArray.Record record = debugInformation.methodMapping.get(methodIndex++);
|
||||
RecordArray.Record record = layer.methodMapping.get(methodIndex++);
|
||||
methodId = record.get(2);
|
||||
location = DebugInformation.key(record);
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.debugging.information;
|
||||
|
||||
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,125 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.debugging.information;
|
||||
|
||||
class LayerIterator {
|
||||
private int currentLayer;
|
||||
private MethodIterator[] methodIterators;
|
||||
private GeneratedLocation currentLocation;
|
||||
|
||||
LayerIterator(DebugInformation debugInformation) {
|
||||
methodIterators = new MethodIterator[debugInformation.layerCount()];
|
||||
for (int i = 0; i < methodIterators.length; ++i) {
|
||||
methodIterators[i] = new MethodIterator(debugInformation.layers[i]);
|
||||
}
|
||||
|
||||
nextImpl();
|
||||
}
|
||||
|
||||
public boolean isEndReached() {
|
||||
return currentLayer == 0 && methodIterators[currentLayer].isEndReached();
|
||||
}
|
||||
|
||||
public int getLayer() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return currentLayer;
|
||||
}
|
||||
|
||||
public GeneratedLocation getLocation() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return currentLocation;
|
||||
}
|
||||
|
||||
public void next() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
int previous = currentLayer;
|
||||
do {
|
||||
nextImpl();
|
||||
} while (!isEndReached() && previous == currentLayer);
|
||||
}
|
||||
|
||||
private void nextImpl() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
}
|
||||
|
||||
if (canEnterLayer()) {
|
||||
++currentLayer;
|
||||
while (canEnterLayer()) {
|
||||
++currentLayer;
|
||||
}
|
||||
currentLocation = methodIterators[currentLayer].getLocation();
|
||||
methodIterators[currentLayer].next();
|
||||
} else if (canExitLayer()) {
|
||||
GeneratedLocation limitLocation = methodIterators[currentLayer].getLocation();
|
||||
moveToNextNotEmpty();
|
||||
while (true) {
|
||||
--currentLayer;
|
||||
moveToLocation(limitLocation);
|
||||
if (currentLayer <= 0 || methodIterators[currentLayer].getMethodId() >= 0
|
||||
|| !methodIterators[currentLayer].getLocation().equals(limitLocation)) {
|
||||
break;
|
||||
}
|
||||
moveToNextNotEmpty();
|
||||
}
|
||||
currentLocation = limitLocation;
|
||||
} else {
|
||||
currentLocation = methodIterators[currentLayer].getLocation();
|
||||
methodIterators[currentLayer].next();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canEnterLayer() {
|
||||
return currentLayer < methodIterators.length - 1
|
||||
&& !methodIterators[currentLayer + 1].isEndReached()
|
||||
&& !methodIterators[currentLayer].isEndReached()
|
||||
&& isLocationLessOrEqual(currentLayer + 1, currentLayer);
|
||||
}
|
||||
|
||||
private boolean canExitLayer() {
|
||||
if (currentLayer == 0) {
|
||||
return false;
|
||||
}
|
||||
return methodIterators[currentLayer].getMethodId() < 0;
|
||||
}
|
||||
|
||||
private void moveToNextNotEmpty() {
|
||||
while (!methodIterators[currentLayer].isEndReached() && methodIterators[currentLayer].getMethodId() < 0) {
|
||||
methodIterators[currentLayer].next();
|
||||
}
|
||||
}
|
||||
|
||||
private void moveToLocation(GeneratedLocation location) {
|
||||
while (true) {
|
||||
GeneratedLocation nextLocation = methodIterators[currentLayer].getLocation();
|
||||
if (nextLocation.compareTo(location) >= 0) {
|
||||
break;
|
||||
}
|
||||
currentLocation = location;
|
||||
methodIterators[currentLayer].next();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLocationLessOrEqual(int firstLayer, int secondLayer) {
|
||||
return methodIterators[firstLayer].getLocation().compareTo(methodIterators[secondLayer].getLocation()) <= 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.debugging.information;
|
||||
|
||||
import org.teavm.common.RecordArray;
|
||||
|
||||
class LayerSourceLocationIterator {
|
||||
private DebugInformation debugInformation;
|
||||
private int lineIndex;
|
||||
private int fileIndex;
|
||||
private GeneratedLocation location;
|
||||
private int fileId = -1;
|
||||
private int line = -1;
|
||||
private boolean endReached;
|
||||
private DebugInformation.Layer layer;
|
||||
|
||||
LayerSourceLocationIterator(DebugInformation debugInformation, DebugInformation.Layer layer) {
|
||||
this.debugInformation = debugInformation;
|
||||
this.layer = layer;
|
||||
read();
|
||||
}
|
||||
|
||||
public boolean isEndReached() {
|
||||
return endReached;
|
||||
}
|
||||
|
||||
private void read() {
|
||||
if (fileIndex < layer.fileMapping.size() && lineIndex < layer.lineMapping.size()) {
|
||||
RecordArray.Record fileRecord = layer.fileMapping.get(fileIndex);
|
||||
RecordArray.Record lineRecord = layer.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 if (fileIndex < layer.fileMapping.size()) {
|
||||
nextFileRecord();
|
||||
} else if (lineIndex < layer.lineMapping.size()) {
|
||||
nextLineRecord();
|
||||
} else if (endReached) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
} else {
|
||||
endReached = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void nextFileRecord() {
|
||||
RecordArray.Record record = layer.fileMapping.get(fileIndex++);
|
||||
location = DebugInformation.key(record);
|
||||
fileId = record.get(2);
|
||||
}
|
||||
|
||||
private void nextLineRecord() {
|
||||
RecordArray.Record record = layer.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;
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.debugging.information;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -15,37 +15,30 @@
|
|||
*/
|
||||
package org.teavm.debugging.information;
|
||||
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
|
||||
public class MethodIterator {
|
||||
private DebugInformation debugInformation;
|
||||
class MethodIterator {
|
||||
private DebugInformation.Layer layer;
|
||||
private int index;
|
||||
|
||||
MethodIterator(DebugInformation debugInformation) {
|
||||
this.debugInformation = debugInformation;
|
||||
MethodIterator(DebugInformation.Layer layer) {
|
||||
this.layer = layer;
|
||||
}
|
||||
|
||||
public boolean isEndReached() {
|
||||
return index < debugInformation.methodMapping.size();
|
||||
return index >= layer.methodMapping.size();
|
||||
}
|
||||
|
||||
public GeneratedLocation getLocation() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
}
|
||||
return DebugInformation.key(debugInformation.methodMapping.get(index));
|
||||
return DebugInformation.key(layer.methodMapping.get(index));
|
||||
}
|
||||
|
||||
public int getMethodId() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
}
|
||||
return debugInformation.methodMapping.get(index).get(2);
|
||||
}
|
||||
|
||||
public MethodDescriptor getMethod() {
|
||||
int methodId = getMethodId();
|
||||
return methodId >= 0 ? debugInformation.getMethod(methodId) : null;
|
||||
return layer.methodMapping.get(index).get(2);
|
||||
}
|
||||
|
||||
public void next() {
|
||||
|
|
|
@ -15,85 +15,77 @@
|
|||
*/
|
||||
package org.teavm.debugging.information;
|
||||
|
||||
import org.teavm.common.RecordArray;
|
||||
|
||||
public class SourceLocationIterator {
|
||||
private DebugInformation debugInformation;
|
||||
private int lineIndex;
|
||||
private int fileIndex;
|
||||
private GeneratedLocation location;
|
||||
private int fileId = -1;
|
||||
private int line = -1;
|
||||
private LayerIterator layerIterator;
|
||||
private LayerInfo[] layerSourceIterators;
|
||||
private boolean endReached;
|
||||
private int currentLayer;
|
||||
private GeneratedLocation lastLocation;
|
||||
|
||||
SourceLocationIterator(DebugInformation debugInformation) {
|
||||
public SourceLocationIterator(DebugInformation debugInformation) {
|
||||
this.debugInformation = debugInformation;
|
||||
if (!isEndReached()) {
|
||||
read();
|
||||
layerIterator = new LayerIterator(debugInformation);
|
||||
layerSourceIterators = new LayerInfo[debugInformation.layerCount()];
|
||||
for (int i = 0; i < layerSourceIterators.length; ++i) {
|
||||
layerSourceIterators[i] = new LayerInfo(new LayerSourceLocationIterator(
|
||||
debugInformation, debugInformation.layers[i]));
|
||||
}
|
||||
|
||||
if (!layerIterator.isEndReached()) {
|
||||
currentLayer = layerIterator.getLayer();
|
||||
layerIterator.next();
|
||||
} else {
|
||||
currentLayer = 0;
|
||||
}
|
||||
|
||||
lastLocation = layerSourceIterators[currentLayer].lastLocation;
|
||||
if (lastLocation == null) {
|
||||
endReached = true;
|
||||
}
|
||||
}
|
||||
|
||||
public GeneratedLocation getLocation() {
|
||||
return lastLocation;
|
||||
}
|
||||
|
||||
public boolean isEndReached() {
|
||||
return endReached;
|
||||
}
|
||||
|
||||
private void read() {
|
||||
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 if (fileIndex < debugInformation.fileMapping.size()) {
|
||||
nextFileRecord();
|
||||
} else if (lineIndex < debugInformation.lineMapping.size()) {
|
||||
nextLineRecord();
|
||||
} else if (endReached) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
} 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");
|
||||
if (endReached) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
read();
|
||||
}
|
||||
|
||||
public GeneratedLocation getLocation() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
LayerInfo currentIterator = layerSourceIterators[currentLayer];
|
||||
if (currentLayer == 0 && currentIterator.iterator.isEndReached()) {
|
||||
endReached = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentIterator.iterator.isEndReached() || (!layerIterator.isEndReached()
|
||||
&& currentIterator.iterator.getLocation().compareTo(layerIterator.getLocation()) >= 0)) {
|
||||
currentLayer = layerIterator.getLayer();
|
||||
lastLocation = layerIterator.getLocation();
|
||||
layerIterator.next();
|
||||
|
||||
currentIterator = layerSourceIterators[currentLayer];
|
||||
while (!currentIterator.iterator.isEndReached()
|
||||
&& currentIterator.iterator.getLocation().compareTo(lastLocation) <= 0) {
|
||||
currentIterator.next();
|
||||
}
|
||||
} else {
|
||||
currentIterator.next();
|
||||
lastLocation = currentIterator.lastLocation;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
public int getFileNameId() {
|
||||
if (isEndReached()) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
}
|
||||
return fileId;
|
||||
return layerSourceIterators[currentLayer].lastFileId;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
|
@ -105,6 +97,27 @@ public class SourceLocationIterator {
|
|||
if (isEndReached()) {
|
||||
throw new IllegalStateException("End already reached");
|
||||
}
|
||||
return line;
|
||||
return layerSourceIterators[currentLayer].lastLine;
|
||||
}
|
||||
|
||||
static class LayerInfo {
|
||||
LayerSourceLocationIterator iterator;
|
||||
int lastFileId;
|
||||
int lastLine;
|
||||
GeneratedLocation lastLocation;
|
||||
|
||||
LayerInfo(LayerSourceLocationIterator iterator) {
|
||||
this.iterator = iterator;
|
||||
if (!iterator.isEndReached()) {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
void next() {
|
||||
this.lastFileId = iterator.getFileNameId();
|
||||
this.lastLine = iterator.getLine();
|
||||
this.lastLocation = iterator.getLocation();
|
||||
iterator.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,8 @@ class SourceMapsWriter {
|
|||
output.write("\"}");
|
||||
}
|
||||
|
||||
private void writeSegment(GeneratedLocation loc, int sourceFile, int sourceLine) throws IOException {
|
||||
private void writeSegment(GeneratedLocation loc, int sourceFile, int sourceLine)
|
||||
throws IOException {
|
||||
while (loc.getLine() > lastLine) {
|
||||
output.write(';');
|
||||
++lastLine;
|
||||
|
|
|
@ -398,7 +398,7 @@ public class Inlining {
|
|||
entry.targetInstruction = insn;
|
||||
entry.program = invokedProgram;
|
||||
entry.innerPlan.addAll(buildPlan(invokedProgram, depth + 1, innerStep, invokedMethod.getReference(),
|
||||
inliningInfo));
|
||||
innerInliningInfo));
|
||||
entry.depth = depth;
|
||||
entry.method = invokedMethod.getReference();
|
||||
entry.locationInfo = innerInliningInfo;
|
||||
|
|
|
@ -61,7 +61,7 @@ class LocationGraphBuilder {
|
|||
while (!stack.isEmpty()) {
|
||||
Step step = stack.pop();
|
||||
if (visited[step.block]) {
|
||||
if (step.location != null) {
|
||||
if (step.location != null && !step.location.isEmpty()) {
|
||||
additionalConnections.add(new AdditionalConnection(step.location, startLocations.get(step.block)));
|
||||
}
|
||||
continue;
|
||||
|
@ -83,14 +83,14 @@ class LocationGraphBuilder {
|
|||
if (blockLocations[step.block] == null) {
|
||||
blockLocations[step.block] = insn.getLocation();
|
||||
}
|
||||
if (location != null && !Objects.equals(location, insn.getLocation())) {
|
||||
if (location != null && !location.isEmpty() && !Objects.equals(location, insn.getLocation())) {
|
||||
addEdge(location, insn.getLocation());
|
||||
}
|
||||
location = insn.getLocation();
|
||||
}
|
||||
}
|
||||
if (graph.outgoingEdgesCount(step.block) == 0) {
|
||||
if (location != null) {
|
||||
if (location != null && !location.isEmpty()) {
|
||||
addEdge(location, new TextLocation(null, -1));
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -17,8 +17,11 @@ package org.teavm.devserver.deobfuscate;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.teavm.debugging.information.DebugInformation;
|
||||
import org.teavm.debugging.information.GeneratedLocation;
|
||||
import org.teavm.debugging.information.SourceLocation;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.ajax.XMLHttpRequest;
|
||||
|
@ -71,11 +74,12 @@ public final class Deobfuscator {
|
|||
String fileName = groups.get(2).stringValue();
|
||||
int lineNumber = Integer.parseInt(groups.get(3).stringValue());
|
||||
int columnNumber = Integer.parseInt(groups.get(4).stringValue());
|
||||
Frame frame = deobfuscateFrame(debugInformation, classesFileName, fileName, lineNumber, columnNumber);
|
||||
if (frame == null) {
|
||||
frame = createDefaultFrame(fileName, functionName, lineNumber);
|
||||
List<Frame> framesPerLine = deobfuscateFrames(debugInformation, classesFileName, fileName,
|
||||
lineNumber, columnNumber);
|
||||
if (framesPerLine == null) {
|
||||
framesPerLine = Arrays.asList(createDefaultFrame(fileName, functionName, lineNumber));
|
||||
}
|
||||
frames.add(frame);
|
||||
frames.addAll(framesPerLine);
|
||||
}
|
||||
return frames.toArray(new Frame[0]);
|
||||
});
|
||||
|
@ -85,32 +89,42 @@ public final class Deobfuscator {
|
|||
}
|
||||
}
|
||||
|
||||
private static Frame deobfuscateFrame(DebugInformation debugInformation, String classesFileName,
|
||||
private static List<Frame> deobfuscateFrames(DebugInformation debugInformation, String classesFileName,
|
||||
String fileName, int lineNumber, int columnNumber) {
|
||||
if (!fileName.equals(classesFileName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MethodReference method = debugInformation.getMethodAt(lineNumber - 1, columnNumber - 1);
|
||||
if (method == null) {
|
||||
List<Frame> result = new ArrayList<>();
|
||||
|
||||
for (int layer = 0; layer < debugInformation.layerCount(); ++layer) {
|
||||
GeneratedLocation jsLocation = new GeneratedLocation(lineNumber - 1, columnNumber - 1);
|
||||
MethodReference method = debugInformation.getMethodAt(jsLocation, layer);
|
||||
if (method == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
SourceLocation location = debugInformation.getSourceLocation(jsLocation, layer);
|
||||
|
||||
String decodedFileName = location != null ? location.getFileName() : null;
|
||||
if (decodedFileName != null) {
|
||||
decodedFileName = decodedFileName.substring(decodedFileName.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
Frame frame = createEmptyFrame();
|
||||
frame.setClassName(method.getClassName());
|
||||
frame.setMethodName(method.getName());
|
||||
frame.setFileName(decodedFileName);
|
||||
if (location != null) {
|
||||
frame.setLineNumber(location.getLine());
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SourceLocation location = debugInformation.getSourceLocation(lineNumber - 1, columnNumber - 1);
|
||||
|
||||
String decodedFileName = location != null ? location.getFileName() : null;
|
||||
if (decodedFileName != null) {
|
||||
decodedFileName = decodedFileName.substring(decodedFileName.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
Frame frame = createEmptyFrame();
|
||||
frame.setClassName(method.getClassName());
|
||||
frame.setMethodName(method.getName());
|
||||
frame.setFileName(decodedFileName);
|
||||
if (location != null) {
|
||||
frame.setLineNumber(location.getLine());
|
||||
}
|
||||
return frame;
|
||||
Collections.reverse(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Frame createDefaultFrame(String fileName, String functionName, int lineNumber) {
|
||||
|
|
|
@ -25,16 +25,18 @@ import java.io.InputStreamReader;
|
|||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import net.sourceforge.htmlunit.corejs.javascript.Scriptable;
|
||||
import org.teavm.debugging.information.DebugInformation;
|
||||
import org.teavm.debugging.information.GeneratedLocation;
|
||||
import org.teavm.debugging.information.SourceLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
final class RhinoResultParser {
|
||||
private static Pattern pattern = Pattern.compile("(([A-Za-z_$]+)\\(\\))?@.+:([0-9]+)");
|
||||
private static Pattern pattern = Pattern.compile("(([A-Za-z_$][A-Za-z0-9_$]*)\\(\\))?@.+:([0-9]+)");
|
||||
private static Pattern lineSeparator = Pattern.compile("\\r\\n|\r|\n");
|
||||
private DebugInformation debugInformation;
|
||||
private String[] script;
|
||||
|
@ -70,8 +72,7 @@ final class RhinoResultParser {
|
|||
String stack = result.get("stack", result).toString();
|
||||
StackTraceElement[] decodedStack = null;
|
||||
if (debugInformation != null) {
|
||||
List<StackTraceElement> elements = new ArrayList<>();
|
||||
elements.addAll(Arrays.asList(decodeStack(stack)));
|
||||
List<StackTraceElement> elements = new ArrayList<>(Arrays.asList(decodeStack(stack)));
|
||||
List<StackTraceElement> currentElements = Arrays.asList(Thread.currentThread().getStackTrace());
|
||||
elements.addAll(currentElements.subList(2, currentElements.size()));
|
||||
decodedStack = elements.toArray(new StackTraceElement[0]);
|
||||
|
@ -104,34 +105,49 @@ final class RhinoResultParser {
|
|||
}
|
||||
|
||||
String functionName = matcher.group(2);
|
||||
int lineNumber = Integer.parseInt(matcher.group(3)) - 1;
|
||||
int jsLineNumber = Integer.parseInt(matcher.group(3)) - 1;
|
||||
|
||||
String scriptLine = script[lineNumber];
|
||||
int column = firstNonSpace(scriptLine);
|
||||
MethodReference method = debugInformation.getMethodAt(lineNumber, column);
|
||||
String className;
|
||||
String methodName;
|
||||
String scriptLine = script[jsLineNumber];
|
||||
int jsColumn = firstNonSpace(scriptLine);
|
||||
|
||||
if (method != null) {
|
||||
className = method.getClassName();
|
||||
methodName = method.getName();
|
||||
} else {
|
||||
className = "<JS>";
|
||||
methodName = functionName != null ? functionName : "<unknown_function>";
|
||||
int layer = 0;
|
||||
List<StackTraceElement> elementsByLine = new ArrayList<>();
|
||||
GeneratedLocation jsLocation = new GeneratedLocation(jsLineNumber, jsColumn);
|
||||
while (true) {
|
||||
int lineNumber = jsLineNumber;
|
||||
|
||||
MethodReference method = debugInformation.getMethodAt(jsLocation, layer);
|
||||
String className;
|
||||
String methodName;
|
||||
|
||||
if (method != null) {
|
||||
className = method.getClassName();
|
||||
methodName = method.getName();
|
||||
} else if (layer > 0) {
|
||||
break;
|
||||
} else {
|
||||
className = "<JS>";
|
||||
methodName = functionName != null ? functionName : "<unknown_function>";
|
||||
}
|
||||
|
||||
String fileName;
|
||||
SourceLocation location = debugInformation.getSourceLocation(jsLocation, layer);
|
||||
if (location != null && location.getFileName() != null) {
|
||||
fileName = location.getFileName();
|
||||
fileName = fileName.substring(fileName.lastIndexOf('/') + 1);
|
||||
lineNumber = location.getLine();
|
||||
} else {
|
||||
fileName = "test.js";
|
||||
lineNumber++;
|
||||
}
|
||||
|
||||
elementsByLine.add(new StackTraceElement(className, methodName, fileName, lineNumber));
|
||||
|
||||
++layer;
|
||||
}
|
||||
|
||||
String fileName;
|
||||
SourceLocation location = debugInformation.getSourceLocation(lineNumber, column);
|
||||
if (location != null && location.getFileName() != null) {
|
||||
fileName = location.getFileName();
|
||||
fileName = fileName.substring(fileName.lastIndexOf('/') + 1);
|
||||
lineNumber = location.getLine();
|
||||
} else {
|
||||
fileName = "test.js";
|
||||
lineNumber++;
|
||||
}
|
||||
|
||||
elements.add(new StackTraceElement(className, methodName, fileName, lineNumber));
|
||||
Collections.reverse(elementsByLine);
|
||||
elements.addAll(elementsByLine);
|
||||
}
|
||||
|
||||
return elements.toArray(new StackTraceElement[0]);
|
||||
|
|
|
@ -37,7 +37,7 @@ interface TeaVMTestConfiguration<T extends TeaVMTarget> {
|
|||
|
||||
@Override
|
||||
public void apply(TeaVM vm) {
|
||||
vm.setOptimizationLevel(TeaVMOptimizationLevel.FULL);
|
||||
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue
Block a user