diff --git a/teavm-core/src/main/java/org/teavm/javascript/AllBlocksCountVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/AllBlocksCountVisitor.java index 7f0d0fd0e..6b4536197 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/AllBlocksCountVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/AllBlocksCountVisitor.java @@ -27,14 +27,24 @@ import org.teavm.javascript.ast.*; class AllBlocksCountVisitor implements StatementVisitor { private Map blocksCount = new HashMap<>(); private IdentifiedStatement currentBlock; + private boolean last = true; public void visit(List statements) { if (statements == null) { return; } - for (Statement part : statements) { - part.acceptVisitor(this); + if (statements.isEmpty()) { + incrementCurrentBlock(); + return; } + boolean oldLast = last; + for (int i = 0; i < statements.size() - 1; ++i) { + last = false; + statements.get(i).acceptVisitor(this); + } + last = true; + statements.get(statements.size() - 1).acceptVisitor(this); + last = oldLast; } public int getCount(IdentifiedStatement statement) { @@ -44,6 +54,9 @@ class AllBlocksCountVisitor implements StatementVisitor { @Override public void visit(AssignmentStatement statement) { + if (last) { + incrementCurrentBlock(); + } } @Override @@ -66,6 +79,9 @@ class AllBlocksCountVisitor implements StatementVisitor { } visit(statement.getDefaultClause()); currentBlock = oldCurrentBlock; + if (last && blocksCount.containsKey(statement)) { + incrementCurrentBlock(); + } } @Override @@ -74,6 +90,9 @@ class AllBlocksCountVisitor implements StatementVisitor { currentBlock = statement; visit(statement.getBody()); currentBlock = oldCurrentBlock; + if (last && (statement.getCondition() != null || blocksCount.containsKey(statement))) { + incrementCurrentBlock(); + } } @Override @@ -82,6 +101,9 @@ class AllBlocksCountVisitor implements StatementVisitor { currentBlock = statement; visit(statement.getBody()); currentBlock = oldCurrentBlock; + if (last && blocksCount.containsKey(statement)) { + incrementCurrentBlock(); + } } @Override @@ -90,7 +112,7 @@ class AllBlocksCountVisitor implements StatementVisitor { if (target == null) { target = currentBlock; } - blocksCount.put(target, getCount(target) + 1); + incrementBlock(target); } @Override @@ -99,7 +121,17 @@ class AllBlocksCountVisitor implements StatementVisitor { if (target == null) { target = currentBlock; } - blocksCount.put(target, getCount(target) + 1); + incrementBlock(target); + } + + private void incrementBlock(IdentifiedStatement statement) { + blocksCount.put(statement, getCount(statement) + 1); + } + + private void incrementCurrentBlock() { + if (currentBlock != null) { + incrementBlock(currentBlock); + } } @Override @@ -126,9 +158,15 @@ class AllBlocksCountVisitor implements StatementVisitor { @Override public void visit(MonitorEnterStatement statement) { + if (last) { + incrementCurrentBlock(); + } } @Override public void visit(MonitorExitStatement statement) { + if (last) { + incrementCurrentBlock(); + } } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/BreakEliminator.java b/teavm-core/src/main/java/org/teavm/javascript/BreakEliminator.java index 7115f06e4..bff4928d8 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/BreakEliminator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/BreakEliminator.java @@ -26,7 +26,6 @@ class BreakEliminator implements StatementVisitor { private Map> blockSuccessors = new HashMap<>(); private Set outerStatements = new HashSet<>(); private List currentSequence; - private boolean sequenceEscapes; private int currentIndex; private AllBlocksCountVisitor usageCounter; @@ -39,15 +38,12 @@ class BreakEliminator implements StatementVisitor { private void processSequence(List statements) { List oldSequence = currentSequence; int oldIndex = currentIndex; - boolean oldEscapes = sequenceEscapes; - sequenceEscapes = escapes(statements); currentSequence = statements; for (currentIndex = 0; currentIndex < currentSequence.size(); ++currentIndex) { statements.get(currentIndex).acceptVisitor(this); } - sequenceEscapes = oldEscapes; currentIndex = oldIndex; currentSequence = oldSequence; } @@ -93,7 +89,7 @@ class BreakEliminator implements StatementVisitor { @Override public void visit(BlockStatement statement) { outerStatements.add(statement); - if (!sequenceEscapes && !escapes(statement.getBody())) { + if (!escapes(currentSequence.subList(currentIndex + 1, currentSequence.size()))) { blockSuccessors.put(statement, currentSequence.subList(currentIndex + 1, currentSequence.size())); } processSequence(statement.getBody()); @@ -110,7 +106,6 @@ class BreakEliminator implements StatementVisitor { currentSequence.addAll(successors); successors.clear(); --currentIndex; - sequenceEscapes = escapes(currentSequence); return; } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/EscapingStatementFinder.java b/teavm-core/src/main/java/org/teavm/javascript/EscapingStatementFinder.java index 8698cf20a..921ac1142 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/EscapingStatementFinder.java +++ b/teavm-core/src/main/java/org/teavm/javascript/EscapingStatementFinder.java @@ -28,6 +28,8 @@ class EscapingStatementFinder implements StatementVisitor { public boolean escaping; private boolean last = true; private Set outerStatements = new HashSet<>(); + private Set breakTargets = new HashSet<>(); + private IdentifiedStatement currentBlock; public boolean check(List statements) { if (escaping) { @@ -72,6 +74,8 @@ class EscapingStatementFinder implements StatementVisitor { @Override public void visit(SwitchStatement statement) { + IdentifiedStatement oldCurrentBlock = currentBlock; + currentBlock = statement; outerStatements.add(statement); for (SwitchClause clause : statement.getClauses()) { if (check(clause.getBody())) { @@ -80,32 +84,50 @@ class EscapingStatementFinder implements StatementVisitor { } check(statement.getDefaultClause()); outerStatements.remove(statement); + currentBlock = oldCurrentBlock; + if (breakTargets.contains(statement)) { + escaping |= last; + } } @Override public void visit(WhileStatement statement) { + IdentifiedStatement oldCurrentBlock = currentBlock; + currentBlock = statement; outerStatements.add(statement); if (!check(statement.getBody()) && statement.getCondition() != null) { escaping |= last; } outerStatements.remove(statement); + currentBlock = oldCurrentBlock; + if (breakTargets.contains(statement)) { + escaping |= last; + } } @Override public void visit(BlockStatement statement) { + IdentifiedStatement oldCurrentBlock = currentBlock; + currentBlock = statement; outerStatements.add(statement); check(statement.getBody()); outerStatements.remove(statement); + currentBlock = oldCurrentBlock; + if (breakTargets.contains(statement)) { + escaping |= last; + } } @Override public void visit(BreakStatement statement) { - escaping |= !outerStatements.contains(statement.getTarget()); + IdentifiedStatement target = statement.getTarget() != null ? statement.getTarget() : currentBlock; + if (target != null) { + breakTargets.add(target); + } } @Override public void visit(ContinueStatement statement) { - escaping |= !outerStatements.contains(statement.getTarget()); } @Override