JS/Inlining: in temporary variable elimination don't treat FQN without side effects as trivial, i.e. disable moving these vars freely across function body

This commit is contained in:
Alexey Andreev
2016-06-01 12:57:53 +03:00
parent 878e95e040
commit 57ac23a606
3 changed files with 11 additions and 23 deletions
@@ -22,7 +22,7 @@ class FunctionPostProcessor(root: JsFunction) {
val optimizations = listOf(
{ TemporaryAssignmentElimination(root.body).apply() },
{ RedundantLabelRemoval(root.body).apply() },
{ TemporaryVariableElimination(root.body).apply() },
{ TemporaryVariableElimination(root).apply() },
{ IfStatementReduction(root.body).apply() },
{ DeadCodeElimination(root.body).apply() },
{ RedundantVariableDeclarationElimination(root.body).apply() },
@@ -19,18 +19,19 @@ package org.jetbrains.kotlin.js.inline.clean
import com.google.dart.compiler.backend.js.ast.*
import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
import com.google.dart.compiler.backend.js.ast.metadata.synthetic
import org.jetbrains.kotlin.js.inline.util.collectDefinedNames
import org.jetbrains.kotlin.js.inline.util.collectFreeVariables
import org.jetbrains.kotlin.js.inline.util.collectLocalVariables
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
internal class TemporaryVariableElimination(private val root: JsStatement) {
internal class TemporaryVariableElimination(function: JsFunction) {
private val root = function.body
private val definitions = mutableMapOf<JsName, Int>()
private val usages = mutableMapOf<JsName, Int>()
private val inconsistent = mutableSetOf<JsName>()
private val definedValues = mutableMapOf<JsName, JsExpression>()
private val temporary = mutableSetOf<JsName>()
private var hasChanges = false
private val namesToProcess = mutableSetOf<JsName>()
private val namesToProcess = function.collectLocalVariables()
private val statementsToRemove = mutableSetOf<JsNode>()
private val namesToSubstitute = mutableSetOf<JsName>()
private val variablesToRemove = mutableSetOf<JsName>()
@@ -43,8 +44,6 @@ internal class TemporaryVariableElimination(private val root: JsStatement) {
}
private fun analyze() {
namesToProcess += collectDefinedNames(root)
object : RecursiveJsVisitor() {
val currentScope = mutableSetOf<JsName>()
var localVars = mutableSetOf<JsName>()
@@ -543,22 +542,11 @@ internal class TemporaryVariableElimination(private val root: JsStatement) {
private fun isTrivial(expr: JsExpression): Boolean = when (expr) {
is JsNameRef -> {
val qualifier = expr.qualifier
if (qualifier == null) {
if (!expr.sideEffects) {
true
}
else {
val name = expr.name
name != null && when (definitions[name] ?: 0) {
0 -> true
1 -> name !in namesToSubstitute || definedValues[name]?.let { isTrivial(it) } ?: false
else -> false
}
}
}
else {
!expr.sideEffects && isTrivial(qualifier)
val name = expr.name
name in namesToProcess && when (definitions[name]) {
null, 0 -> true
1 -> name !in namesToSubstitute || definedValues[name]?.let { isTrivial(it) } ?: false
else -> false
}
}
is JsLiteral.JsValueLiteral -> true
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test
// CHECK_VARS_COUNT: function=test count=0
// CHECK_VARS_COUNT: function=test count=1
object SumHolder {
var sum = 0