JS: don't treat return, break and continue as split points when possible

This commit is contained in:
Alexey Andreev
2016-11-14 14:40:21 +03:00
parent 14729b0f0e
commit 43525abda3
3 changed files with 48 additions and 13 deletions
@@ -107,7 +107,18 @@ public class JsFor extends SourceInfoAwareJsNode implements JsStatement {
if (initExpression != null) {
initExpression = v.accept(initExpression);
} else if (initVars != null) {
initVars = v.acceptStatement(initVars);
JsStatement newInitVars = v.<JsStatement>acceptStatement(initVars);
if (newInitVars instanceof JsVars) {
initVars = (JsVars) newInitVars;
}
else {
initVars = null;
if (newInitVars instanceof JsExpressionStatement) {
initExpression = ((JsExpressionStatement) newInitVars).getExpression();
} else if (newInitVars != null) {
ctx.addPrevious(newInitVars);
}
}
}
if (condition != null) {
@@ -51,7 +51,7 @@ class CoroutineBodyTransformer(
fun preProcess(node: JsNode) {
breakContinueTargetStatements += node.collectBreakContinueTargets()
nodesToSplit = node.collectNodesToSplit()
nodesToSplit = node.collectNodesToSplit(breakContinueTargetStatements)
}
fun postProcess(): List<CoroutineBlock> {
@@ -21,11 +21,13 @@ import com.google.dart.compiler.backend.js.ast.metadata.*
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.utils.singletonOrEmptyList
fun JsNode.collectNodesToSplit(): Set<JsNode> {
fun JsNode.collectNodesToSplit(breakContinueTargets: Map<JsContinue, JsStatement>): Set<JsNode> {
val root = this
val nodes = mutableSetOf<JsNode>()
val visitor = object : RecursiveJsVisitor() {
var childrenInSet = false
var finallyLevel = 0
override fun visitInvocation(invocation: JsInvocation) {
super.visitInvocation(invocation)
@@ -37,23 +39,41 @@ fun JsNode.collectNodesToSplit(): Set<JsNode> {
override fun visitReturn(x: JsReturn) {
super.visitReturn(x)
nodes += x
childrenInSet = true
if (root in nodes || finallyLevel > 0) {
nodes += x
childrenInSet = true
}
}
override fun visitBreak(x: JsBreak) {
super.visitBreak(x)
// It's a simplification
// TODO: don't split break and continue statements when possible
nodes += x
childrenInSet = true
val breakTarget = breakContinueTargets[x]!!
if (breakTarget in nodes) {
nodes += x
childrenInSet = true
}
}
override fun visitContinue(x: JsContinue) {
super.visitContinue(x)
nodes += x
childrenInSet = true
val continueTarget = breakContinueTargets[x]!!
if (continueTarget in nodes) {
nodes += x
childrenInSet = true
}
}
override fun visitTry(x: JsTry) {
if (x.finallyBlock != null) {
finallyLevel++
}
super.visitTry(x)
if (x.finallyBlock != null) {
finallyLevel--
}
}
override fun visitElement(node: JsNode) {
@@ -71,8 +91,12 @@ fun JsNode.collectNodesToSplit(): Set<JsNode> {
}
}
visitor.accept(this)
visitor.accept(this)
while (true) {
val countBefore = nodes.size
visitor.accept(this)
val countAfter = nodes.size
if (countAfter == countBefore) break
}
return nodes
}