diff --git a/teavm-core/src/main/java/org/teavm/debugging/Debugger.java b/teavm-core/src/main/java/org/teavm/debugging/Debugger.java index a6e757e77..39ebd672e 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/Debugger.java +++ b/teavm-core/src/main/java/org/teavm/debugging/Debugger.java @@ -146,6 +146,7 @@ public class Debugger { public void visit(DebuggerVirtualCallSite callSite) { for (MethodReference potentialMethod : debugInfo.getOverridingMethods(callSite.getMethod())) { for (GeneratedLocation loc : debugInfo.getMethodEntrances(potentialMethod)) { + loc = debugInfo.getStatementLocation(loc); locations.add(new JavaScriptLocation(script, loc.getLine(), loc.getColumn())); } } @@ -154,6 +155,7 @@ public class Debugger { @Override public void visit(DebuggerStaticCallSite callSite) { for (GeneratedLocation loc : debugInfo.getMethodEntrances(callSite.getMethod())) { + loc = debugInfo.getStatementLocation(loc); locations.add(new JavaScriptLocation(script, loc.getLine(), loc.getColumn())); } } @@ -174,6 +176,7 @@ public class Debugger { Collection genLocations = debugInfo.getGeneratedLocations(successor); if (!genLocations.isEmpty()) { for (GeneratedLocation loc : genLocations) { + loc = debugInfo.getStatementLocation(loc); successors.add(new JavaScriptLocation(script, loc.getLine(), loc.getColumn())); } } else { 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 11c5e9723..91cd5dada 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 @@ -46,6 +46,7 @@ public class DebugInformation { RecordArray methodMapping; RecordArray lineMapping; RecordArray callSiteMapping; + RecordArray statementStartMapping; RecordArray[] variableMappings; RecordArray[] lineCallSites; RecordArray[] controlFlowGraphs; @@ -356,6 +357,28 @@ public class DebugInformation { return callSites; } + public List getStatementStartLocations() { + return new LocationList(statementStartMapping); + } + + public GeneratedLocation getStatementLocation(GeneratedLocation location) { + int index = indexByKey(statementStartMapping, location); + if (index < 0) { + return new GeneratedLocation(0, 0); + } + RecordArray.Record record = statementStartMapping.get(index); + return new GeneratedLocation(record.get(0), record.get(1)); + } + + public GeneratedLocation getNextStatementLocation(GeneratedLocation location) { + int index = indexByKey(statementStartMapping, location); + if (index >= statementStartMapping.size()) { + return new GeneratedLocation(0, 0); + } + RecordArray.Record record = statementStartMapping.get(index + 1); + return new GeneratedLocation(record.get(0), record.get(1)); + } + private T componentByKey(RecordArray mapping, T[] values, GeneratedLocation location) { int keyIndex = indexByKey(mapping, location); int valueIndex = keyIndex >= 0 ? mapping.get(keyIndex).get(2) : -1; 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 c43d0835a..64c77931d 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 @@ -36,6 +36,7 @@ public class DebugInformationBuilder implements DebugInformationEmitter { private MappedList variableNames = new MappedList(); private List exactMethods = new ArrayList<>(); private Map 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); @@ -120,6 +121,13 @@ public class DebugInformationBuilder implements DebugInformationEmitter { } } + @Override + public void emitStatementStart() { + RecordArrayBuilder.Record record = statementStartMapping.add(); + record.set(0, locationProvider.getLine()); + record.set(1, locationProvider.getColumn()); + } + @Override public void emitVariable(String[] sourceNames, String generatedName) { int[] sourceIndexes = new int[sourceNames.length]; @@ -273,6 +281,7 @@ 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(); diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationEmitter.java b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationEmitter.java index e6796c862..02698e039 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationEmitter.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/DebugInformationEmitter.java @@ -27,6 +27,8 @@ public interface DebugInformationEmitter { void emitLocation(String fileName, int line); + void emitStatementStart(); + void emitMethod(MethodDescriptor method); void emitClass(String className); 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 5610cfaa5..238f2f2df 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 @@ -47,6 +47,7 @@ class DebugInformationReader { debugInfo.lineMapping = readMapping(); debugInfo.classMapping = readMapping(); debugInfo.methodMapping = readMapping(); + debugInfo.statementStartMapping = readBooleanMapping(); debugInfo.callSiteMapping = readCallSiteMapping(); debugInfo.variableMappings = readVariableMappings(debugInfo.variableNames.length); debugInfo.classesMetadata = readClassesMetadata(debugInfo.classNames.length); @@ -157,6 +158,11 @@ class DebugInformationReader { return builder.build(); } + private RecordArray readBooleanMapping() throws IOException { + RecordArrayBuilder builder = readLinesAndColumns(2, 0); + return builder.build(); + } + private RecordArray readMapping() throws IOException { RecordArrayBuilder builder = readLinesAndColumns(3, 0); readValues(builder); 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 7f840a5a3..680fdf179 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 @@ -49,6 +49,7 @@ class DebugInformationWriter { writeMapping(debugInfo.lineMapping); writeMapping(debugInfo.classMapping); writeMapping(debugInfo.methodMapping); + writeLinesAndColumns(debugInfo.statementStartMapping); writeCallSiteMapping(debugInfo.callSiteMapping); writeVariableMappings(debugInfo); writeClassMetadata(debugInfo.classesMetadata); diff --git a/teavm-core/src/main/java/org/teavm/debugging/information/DummyDebugInformationEmitter.java b/teavm-core/src/main/java/org/teavm/debugging/information/DummyDebugInformationEmitter.java index 5d624b6f9..c06f955b2 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/information/DummyDebugInformationEmitter.java +++ b/teavm-core/src/main/java/org/teavm/debugging/information/DummyDebugInformationEmitter.java @@ -40,6 +40,10 @@ public class DummyDebugInformationEmitter implements DebugInformationEmitter { public void emitVariable(String[] sourceName, String generatedName) { } + @Override + public void emitStatementStart() { + } + @Override public DeferredCallSite emitCallSite() { return new DeferredCallSite() { diff --git a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java index 08622b55e..61fd9345b 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java @@ -380,7 +380,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { cond.getConsequent().clear(); cond.getConsequent().addAll(innerCond.getConsequent()); cond.setCondition(Expr.binary(BinaryOperation.AND, cond.getCondition(), - innerCond.getCondition())); + innerCond.getCondition(), cond.getCondition().getLocation())); --i; } else if (cond.getAlternative().size() != 1 || !(cond.getAlternative().get(0) instanceof ConditionalStatement)) { @@ -409,6 +409,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { } } + private void normalizeConditional(ConditionalStatement stmt) { if (stmt.getConsequent().isEmpty()) { stmt.getConsequent().addAll(stmt.getAlternative()); @@ -502,8 +503,10 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { if (breakStmt.getTarget() == statement) { statement.getBody().remove(0); if (statement.getCondition() != null) { - statement.setCondition(Expr.binary(BinaryOperation.AND, statement.getCondition(), - ExprOptimizer.invert(cond.getCondition()))); + Expr newCondition = Expr.binary(BinaryOperation.AND, statement.getCondition(), + ExprOptimizer.invert(cond.getCondition())); + newCondition.setLocation(statement.getCondition().getLocation()); + statement.setCondition(newCondition); } else { statement.setCondition(ExprOptimizer.invert(cond.getCondition())); } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index 1bfee5a37..eebdb2261 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -617,6 +617,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(AssignmentStatement statement) throws RenderingException { try { + debugEmitter.emitStatementStart(); if (statement.getLocation() != null) { pushLocation(statement.getLocation()); } @@ -652,6 +653,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext public void visit(ConditionalStatement statement) { try { while (true) { + debugEmitter.emitStatementStart(); if (statement.getCondition().getLocation() != null) { pushLocation(statement.getCondition().getLocation()); } @@ -690,6 +692,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(SwitchStatement statement) { try { + debugEmitter.emitStatementStart(); if (statement.getValue().getLocation() != null) { pushLocation(statement.getValue().getLocation()); } @@ -730,6 +733,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(WhileStatement statement) { try { + debugEmitter.emitStatementStart(); if (statement.getCondition() != null && statement.getCondition().getLocation() != null) { pushLocation(statement.getCondition().getLocation()); } @@ -773,6 +777,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(BreakStatement statement) { try { + debugEmitter.emitStatementStart(); if (statement.getLocation() != null) { pushLocation(statement.getLocation()); } @@ -792,6 +797,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(ContinueStatement statement) { try { + debugEmitter.emitStatementStart(); if (statement.getLocation() != null) { pushLocation(statement.getLocation()); } @@ -811,6 +817,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(ReturnStatement statement) { try { + debugEmitter.emitStatementStart(); if (statement.getLocation() != null) { pushLocation(statement.getLocation()); } @@ -833,6 +840,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(ThrowStatement statement) { try { + debugEmitter.emitStatementStart(); if (statement.getLocation() != null) { pushLocation(statement.getLocation()); } @@ -852,6 +860,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(InitClassStatement statement) { try { + debugEmitter.emitStatementStart(); if (statement.getLocation() != null) { pushLocation(statement.getLocation()); } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/Expr.java b/teavm-core/src/main/java/org/teavm/javascript/ast/Expr.java index 02f137cb4..9be6e91d1 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/Expr.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/Expr.java @@ -73,6 +73,7 @@ public abstract class Expr implements Cloneable { UnaryExpr result = new UnaryExpr(); result.setOperand(expr); result.setOperation(UnaryOperation.NOT); + result.setLocation(expr.getLocation()); return result; }