diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java index 19cc94c4596..489758229de 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java @@ -33,7 +33,9 @@ import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedLocalFunctionDeclaration import org.jetbrains.kotlin.js.inline.context.FunctionContext; import org.jetbrains.kotlin.js.inline.context.InliningContext; import org.jetbrains.kotlin.js.inline.context.NamingContext; -import org.jetbrains.kotlin.js.inline.util.*; +import org.jetbrains.kotlin.js.inline.util.CollectUtilsKt; +import org.jetbrains.kotlin.js.inline.util.CollectionUtilsKt; +import org.jetbrains.kotlin.js.inline.util.NamingUtilsKt; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.resolve.inline.InlineStrategy; @@ -268,7 +270,9 @@ public class JsInliner extends JsVisitorWithContextImpl { return; } - context.replaceMe(accept(resultExpression)); + resultExpression = accept(resultExpression); + MetadataProperties.setSynthetic(resultExpression, true); + context.replaceMe(resultExpression); } @NotNull diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantStatementElimination.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantStatementElimination.kt index 92194ad22c2..2afa65f7f0e 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantStatementElimination.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantStatementElimination.kt @@ -35,7 +35,7 @@ class RedundantStatementElimination(private val root: JsFunction) { private fun process() { object : JsVisitorWithContextImpl() { override fun visit(x: JsExpressionStatement, ctx: JsContext): Boolean { - if (x.synthetic) { + if (x.synthetic || x.expression.synthetic) { val replacement = replace(x.expression) if (replacement.size != 1 || replacement[0] != x.expression) { hasChanges = 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 ded4e3b3e99..eff73272ee3 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 @@ -18,6 +18,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.SideEffectKind +import com.google.dart.compiler.backend.js.ast.metadata.imported 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.collectFreeVariables @@ -116,36 +117,44 @@ internal class TemporaryVariableElimination(private val function: JsFunction) { var localVars = mutableSetOf() override fun visitExpressionStatement(x: JsExpressionStatement) { - val assignment = JsAstUtils.decomposeAssignmentToVariable(x.expression) + (x.expression as? JsBinaryOperation)?.let { expression -> + return processBinaryExpression(expression, x.synthetic) { super.visitExpressionStatement(x) } + } + super.visitExpressionStatement(x) + } + + override fun visitBinaryExpression(x: JsBinaryOperation) = processBinaryExpression(x, false) { super.visitBinaryExpression(x) } + + private fun processBinaryExpression(expression: JsBinaryOperation, synthetic: Boolean, orElse: () -> Unit) { + val assignment = JsAstUtils.decomposeAssignmentToVariable(expression) if (assignment != null) { val (name, value) = assignment if (name in localVariables) { assignVariable(name, value) addVar(name) accept(value) - if (x.synthetic) { + if (synthetic) { temporary += name } + return } - else { - super.visitExpressionStatement(x) - } - return } - super.visitExpressionStatement(x) + orElse() } override fun visitVars(x: JsVars) { for (v in x.vars) { val name = v.name val value = v.initExpression - if (value != null && name in localVariables) { - assignVariable(name, value) - addVar(name) - accept(value) + if (name in localVariables) { if (x.synthetic) { temporary += name } + if (value != null) { + assignVariable(name, value) + addVar(name) + accept(value) + } } } } @@ -507,11 +516,11 @@ internal class TemporaryVariableElimination(private val function: JsFunction) { initializers.forEach { accept(it) } if (isRemoved) { for (initializer in initializers) { - ctx.addPrevious(JsExpressionStatement(accept(initializer)).apply { synthetic = x.synthetic }) + ctx.addPrevious(JsExpressionStatement(accept(initializer)).apply { synthetic = true }) } } else { - ctx.addPrevious(JsVars(*subList.toTypedArray()).apply { synthetic = x.synthetic }) + ctx.addPrevious(JsVars(*subList.toTypedArray()).apply { synthetic = true }) } } ctx.removeMe() @@ -525,7 +534,12 @@ internal class TemporaryVariableElimination(private val function: JsFunction) { return false } - val assignment = JsAstUtils.decomposeAssignmentToVariable(x.expression) + val expression = x.expression + if (expression is JsNameRef && expression.qualifier == null && expression.name in localVariables) { + x.synthetic = true + } + + val assignment = JsAstUtils.decomposeAssignmentToVariable(expression) if (assignment != null) { val (name, value) = assignment if (shouldConsiderUnused(name)) { @@ -583,7 +597,8 @@ internal class TemporaryVariableElimination(private val function: JsFunction) { usages[name] = (usages[name] ?: 0) + 1 } - private fun shouldConsiderUnused(name: JsName) = definitions[name] == 1 && (usages[name] ?: 0) == 0 && name in temporary + private fun shouldConsiderUnused(name: JsName) = + (definitions[name] ?: 0) > 0 && (usages[name] ?: 0) == 0 && name in temporary && !name.imported private fun shouldConsiderTemporary(name: JsName): Boolean { if (definitions[name] != 1 || name !in temporary) return false diff --git a/js/js.translator/testData/js-optimizer/temporary-variable/removeUnusedAndSubstitute.optimized.js b/js/js.translator/testData/js-optimizer/temporary-variable/removeUnusedAndSubstitute.optimized.js index 451457763dd..b00d913d179 100644 --- a/js/js.translator/testData/js-optimizer/temporary-variable/removeUnusedAndSubstitute.optimized.js +++ b/js/js.translator/testData/js-optimizer/temporary-variable/removeUnusedAndSubstitute.optimized.js @@ -1,8 +1,7 @@ var log = ""; function test(a) { - var $tmp1; - log += $tmp1 = 1; + log += 1; return a; }