diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryAssignmentElimination.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryAssignmentElimination.kt index a071ca60935..2791440f1c1 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryAssignmentElimination.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryAssignmentElimination.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.inline.clean import com.google.dart.compiler.backend.js.ast.* import com.google.dart.compiler.backend.js.ast.metadata.synthetic import org.jetbrains.kotlin.js.inline.util.canHaveSideEffect +import org.jetbrains.kotlin.js.inline.util.collectDefinedNames import org.jetbrains.kotlin.js.inline.util.collectFreeVariables import org.jetbrains.kotlin.js.translate.utils.JsAstUtils @@ -29,6 +30,7 @@ internal class TemporaryAssignmentElimination(private val root: JsBlock) { private val mappedUsages = mutableMapOf() private val syntheticNames = mutableSetOf() private var hasChanges = false + private val namesToProcess = mutableSetOf() fun apply(): Boolean { analyze() @@ -39,6 +41,8 @@ internal class TemporaryAssignmentElimination(private val root: JsBlock) { } private fun analyze() { + namesToProcess.addAll(collectDefinedNames(root)) + object : JsVisitorWithContextImpl() { override fun visit(x: JsReturn, ctx: JsContext<*>): Boolean { val returnExpr = x.expression @@ -253,6 +257,7 @@ internal class TemporaryAssignmentElimination(private val root: JsBlock) { private fun tryRecord(expr: JsExpression, usage: Usage): Boolean { if (expr !is JsNameRef) return false val name = expr.name ?: return false + if (name !in namesToProcess) return false usages[name] = usage return true diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryVariableElimination.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryVariableElimination.kt index 2ee87fe5a65..6c2400e5f0e 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryVariableElimination.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryVariableElimination.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.inline.clean import com.google.dart.compiler.backend.js.ast.* import com.google.dart.compiler.backend.js.ast.metadata.synthetic import org.jetbrains.kotlin.js.inline.util.canHaveSideEffect +import org.jetbrains.kotlin.js.inline.util.collectDefinedNames import org.jetbrains.kotlin.js.inline.util.collectFreeVariables import org.jetbrains.kotlin.js.translate.utils.JsAstUtils @@ -28,6 +29,7 @@ internal class TemporaryVariableElimination(private val root: JsStatement) { private val definedValues = mutableMapOf() private val temporary = mutableSetOf() private var hasChanges = false + private val namesToProcess = mutableSetOf() fun apply(): Boolean { analyze() @@ -36,6 +38,8 @@ internal class TemporaryVariableElimination(private val root: JsStatement) { } private fun analyze() { + namesToProcess.addAll(collectDefinedNames(root)) + object : JsVisitorWithContextImpl() { val lastAssignedVars = mutableListOf() @@ -44,7 +48,7 @@ internal class TemporaryVariableElimination(private val root: JsStatement) { if (name != null && x.qualifier == null) { val expr = definedValues[name] useVariable(name) - if (lastAssignedVars.lastOrNull() == name) { + if (lastAssignedVars.lastOrNull() == name && name in namesToProcess) { lastAssignedVars.removeAt(lastAssignedVars.lastIndex) } else if (expr == null || expr.canHaveSideEffect()) { @@ -95,7 +99,7 @@ internal class TemporaryVariableElimination(private val root: JsStatement) { val (name, value) = assignment assignVariable(name, value) accept(value) - if (x.synthetic) { + if (x.synthetic && name in namesToProcess) { temporary += name } else if (value.canHaveSideEffect()) { diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryAssignmentEliminationTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryAssignmentEliminationTest.kt index 0a1bd233290..3dfc6a286c0 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryAssignmentEliminationTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryAssignmentEliminationTest.kt @@ -24,4 +24,6 @@ class TemporaryAssignmentEliminationTest : BasicOptimizerTest("temporary-assignm @Test fun returnStatement() = box() @Test fun declaration() = box() + + @Test fun skipsGlobalDeclarations() = box() } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryVariableEliminationTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryVariableEliminationTest.kt index 504ea43355f..4a8d69c03c1 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryVariableEliminationTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryVariableEliminationTest.kt @@ -22,4 +22,6 @@ class TemporaryVariableEliminationTest : BasicOptimizerTest("temporary-variable" @Test fun declaration() = box() @Test fun assignment() = box() + + @Test fun skipsGlobalDeclarations() = box() } \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.optimized.js b/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.optimized.js index c6993a1c74c..b86d64e43d8 100644 --- a/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.optimized.js +++ b/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.optimized.js @@ -10,10 +10,10 @@ function test(n) { } function box() { - var result = test(20) + var result = test(20); if (result != 20) return "fail1: " + result; - result = test(-20) + result = test(-20); if (result != 20) return "fail2: " + result; return "OK" diff --git a/js/js.translator/testData/js-optimizer/temporary-assignment/skipsGlobalDeclarations.optimized.js b/js/js.translator/testData/js-optimizer/temporary-assignment/skipsGlobalDeclarations.optimized.js new file mode 100644 index 00000000000..d694a633b94 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-assignment/skipsGlobalDeclarations.optimized.js @@ -0,0 +1,24 @@ +var $tmp; + +function test(n) { + if (n >= 0) { + $tmp = n; + } + else { + $tmp = -n; + } + var result = $tmp; + return result; +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + if ($tmp != 20) return "fail3: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-assignment/skipsGlobalDeclarations.original.js b/js/js.translator/testData/js-optimizer/temporary-assignment/skipsGlobalDeclarations.original.js new file mode 100644 index 00000000000..d694a633b94 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-assignment/skipsGlobalDeclarations.original.js @@ -0,0 +1,24 @@ +var $tmp; + +function test(n) { + if (n >= 0) { + $tmp = n; + } + else { + $tmp = -n; + } + var result = $tmp; + return result; +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + if ($tmp != 20) return "fail3: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-variable/skipsGlobalDeclarations.optimized.js b/js/js.translator/testData/js-optimizer/temporary-variable/skipsGlobalDeclarations.optimized.js new file mode 100644 index 00000000000..6640e1d11cd --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-variable/skipsGlobalDeclarations.optimized.js @@ -0,0 +1,14 @@ +var $tmp; + +function test(a, b, c) { + $tmp = a + b; + return $tmp + c; +} + +function box() { + var result = test(2, 3, 4); + if (result != 9) return "fail1: " + result; + if ($tmp != 5) return "fail2: " + $tmp; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-variable/skipsGlobalDeclarations.original.js b/js/js.translator/testData/js-optimizer/temporary-variable/skipsGlobalDeclarations.original.js new file mode 100644 index 00000000000..6640e1d11cd --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-variable/skipsGlobalDeclarations.original.js @@ -0,0 +1,14 @@ +var $tmp; + +function test(a, b, c) { + $tmp = a + b; + return $tmp + c; +} + +function box() { + var result = test(2, 3, 4); + if (result != 9) return "fail1: " + result; + if ($tmp != 5) return "fail2: " + $tmp; + + return "OK" +} \ No newline at end of file