Prohibit from eliminating non-local temporary variables
This commit is contained in:
+5
@@ -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.*
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.synthetic
|
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.canHaveSideEffect
|
||||||
|
import org.jetbrains.kotlin.js.inline.util.collectDefinedNames
|
||||||
import org.jetbrains.kotlin.js.inline.util.collectFreeVariables
|
import org.jetbrains.kotlin.js.inline.util.collectFreeVariables
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ internal class TemporaryAssignmentElimination(private val root: JsBlock) {
|
|||||||
private val mappedUsages = mutableMapOf<JsName, Usage>()
|
private val mappedUsages = mutableMapOf<JsName, Usage>()
|
||||||
private val syntheticNames = mutableSetOf<JsName>()
|
private val syntheticNames = mutableSetOf<JsName>()
|
||||||
private var hasChanges = false
|
private var hasChanges = false
|
||||||
|
private val namesToProcess = mutableSetOf<JsName>()
|
||||||
|
|
||||||
fun apply(): Boolean {
|
fun apply(): Boolean {
|
||||||
analyze()
|
analyze()
|
||||||
@@ -39,6 +41,8 @@ internal class TemporaryAssignmentElimination(private val root: JsBlock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun analyze() {
|
private fun analyze() {
|
||||||
|
namesToProcess.addAll(collectDefinedNames(root))
|
||||||
|
|
||||||
object : JsVisitorWithContextImpl() {
|
object : JsVisitorWithContextImpl() {
|
||||||
override fun visit(x: JsReturn, ctx: JsContext<*>): Boolean {
|
override fun visit(x: JsReturn, ctx: JsContext<*>): Boolean {
|
||||||
val returnExpr = x.expression
|
val returnExpr = x.expression
|
||||||
@@ -253,6 +257,7 @@ internal class TemporaryAssignmentElimination(private val root: JsBlock) {
|
|||||||
private fun tryRecord(expr: JsExpression, usage: Usage): Boolean {
|
private fun tryRecord(expr: JsExpression, usage: Usage): Boolean {
|
||||||
if (expr !is JsNameRef) return false
|
if (expr !is JsNameRef) return false
|
||||||
val name = expr.name ?: return false
|
val name = expr.name ?: return false
|
||||||
|
if (name !in namesToProcess) return false
|
||||||
|
|
||||||
usages[name] = usage
|
usages[name] = usage
|
||||||
return true
|
return true
|
||||||
|
|||||||
+6
-2
@@ -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.*
|
||||||
import com.google.dart.compiler.backend.js.ast.metadata.synthetic
|
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.canHaveSideEffect
|
||||||
|
import org.jetbrains.kotlin.js.inline.util.collectDefinedNames
|
||||||
import org.jetbrains.kotlin.js.inline.util.collectFreeVariables
|
import org.jetbrains.kotlin.js.inline.util.collectFreeVariables
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
|
|
||||||
@@ -28,6 +29,7 @@ internal class TemporaryVariableElimination(private val root: JsStatement) {
|
|||||||
private val definedValues = mutableMapOf<JsName, JsExpression>()
|
private val definedValues = mutableMapOf<JsName, JsExpression>()
|
||||||
private val temporary = mutableSetOf<JsName>()
|
private val temporary = mutableSetOf<JsName>()
|
||||||
private var hasChanges = false
|
private var hasChanges = false
|
||||||
|
private val namesToProcess = mutableSetOf<JsName>()
|
||||||
|
|
||||||
fun apply(): Boolean {
|
fun apply(): Boolean {
|
||||||
analyze()
|
analyze()
|
||||||
@@ -36,6 +38,8 @@ internal class TemporaryVariableElimination(private val root: JsStatement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun analyze() {
|
private fun analyze() {
|
||||||
|
namesToProcess.addAll(collectDefinedNames(root))
|
||||||
|
|
||||||
object : JsVisitorWithContextImpl() {
|
object : JsVisitorWithContextImpl() {
|
||||||
val lastAssignedVars = mutableListOf<JsName>()
|
val lastAssignedVars = mutableListOf<JsName>()
|
||||||
|
|
||||||
@@ -44,7 +48,7 @@ internal class TemporaryVariableElimination(private val root: JsStatement) {
|
|||||||
if (name != null && x.qualifier == null) {
|
if (name != null && x.qualifier == null) {
|
||||||
val expr = definedValues[name]
|
val expr = definedValues[name]
|
||||||
useVariable(name)
|
useVariable(name)
|
||||||
if (lastAssignedVars.lastOrNull() == name) {
|
if (lastAssignedVars.lastOrNull() == name && name in namesToProcess) {
|
||||||
lastAssignedVars.removeAt(lastAssignedVars.lastIndex)
|
lastAssignedVars.removeAt(lastAssignedVars.lastIndex)
|
||||||
}
|
}
|
||||||
else if (expr == null || expr.canHaveSideEffect()) {
|
else if (expr == null || expr.canHaveSideEffect()) {
|
||||||
@@ -95,7 +99,7 @@ internal class TemporaryVariableElimination(private val root: JsStatement) {
|
|||||||
val (name, value) = assignment
|
val (name, value) = assignment
|
||||||
assignVariable(name, value)
|
assignVariable(name, value)
|
||||||
accept(value)
|
accept(value)
|
||||||
if (x.synthetic) {
|
if (x.synthetic && name in namesToProcess) {
|
||||||
temporary += name
|
temporary += name
|
||||||
}
|
}
|
||||||
else if (value.canHaveSideEffect()) {
|
else if (value.canHaveSideEffect()) {
|
||||||
|
|||||||
+2
@@ -24,4 +24,6 @@ class TemporaryAssignmentEliminationTest : BasicOptimizerTest("temporary-assignm
|
|||||||
@Test fun returnStatement() = box()
|
@Test fun returnStatement() = box()
|
||||||
|
|
||||||
@Test fun declaration() = box()
|
@Test fun declaration() = box()
|
||||||
|
|
||||||
|
@Test fun skipsGlobalDeclarations() = box()
|
||||||
}
|
}
|
||||||
+2
@@ -22,4 +22,6 @@ class TemporaryVariableEliminationTest : BasicOptimizerTest("temporary-variable"
|
|||||||
@Test fun declaration() = box()
|
@Test fun declaration() = box()
|
||||||
|
|
||||||
@Test fun assignment() = box()
|
@Test fun assignment() = box()
|
||||||
|
|
||||||
|
@Test fun skipsGlobalDeclarations() = box()
|
||||||
}
|
}
|
||||||
+2
-2
@@ -10,10 +10,10 @@ function test(n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function box() {
|
function box() {
|
||||||
var result = test(20)
|
var result = test(20);
|
||||||
if (result != 20) return "fail1: " + result;
|
if (result != 20) return "fail1: " + result;
|
||||||
|
|
||||||
result = test(-20)
|
result = test(-20);
|
||||||
if (result != 20) return "fail2: " + result;
|
if (result != 20) return "fail2: " + result;
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
|
|||||||
Vendored
+24
@@ -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"
|
||||||
|
}
|
||||||
Vendored
+24
@@ -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"
|
||||||
|
}
|
||||||
Vendored
+14
@@ -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"
|
||||||
|
}
|
||||||
Vendored
+14
@@ -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"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user