JS/Inlining: refactor IneffectiveStatementElimination

This commit is contained in:
Alexey Andreev
2016-06-01 14:05:29 +03:00
parent d829bf4914
commit 0c0fc81e5f
@@ -23,19 +23,14 @@ import org.jetbrains.kotlin.js.inline.util.collectLocalVariables
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
class IneffectiveStatementElimination(private val root: JsFunction) { class IneffectiveStatementElimination(private val root: JsFunction) {
private val localVars = mutableSetOf<JsName>() private val localVars = root.collectLocalVariables()
private var hasChanges = false private var hasChanges = false
fun apply(): Boolean { fun apply(): Boolean {
analyze()
process() process()
return hasChanges return hasChanges
} }
private fun analyze() {
localVars += root.collectLocalVariables()
}
private fun process() { private fun process() {
object : JsVisitorWithContextImpl() { object : JsVisitorWithContextImpl() {
override fun visit(x: JsExpressionStatement, ctx: JsContext<JsNode>): Boolean { override fun visit(x: JsExpressionStatement, ctx: JsContext<JsNode>): Boolean {
@@ -43,7 +38,7 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
val replacement = replace(x.expression) val replacement = replace(x.expression)
if (replacement.size != 1 || replacement[0] != x.expression) { if (replacement.size != 1 || replacement[0] != x.expression) {
hasChanges = true hasChanges = true
ctx.addPrevious(replacement.map { JsExpressionStatement(it).apply { synthetic = true } }.toList()) ctx.addPrevious(replacement.map { JsExpressionStatement(it).apply { synthetic = true } })
ctx.removeMe() ctx.removeMe()
} }
} }
@@ -55,11 +50,11 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
private fun replace(expression: JsExpression): List<JsExpression> { private fun replace(expression: JsExpression): List<JsExpression> {
return when (expression) { return when (expression) {
is JsNameRef -> { is JsNameRef -> {
val qualifier = expression.qualifier if (expression.name in localVars) {
if (qualifier == null && expression.name in localVars) {
listOf() listOf()
} }
else if (!expression.sideEffects) { else if (!expression.sideEffects) {
val qualifier = expression.qualifier
if (qualifier != null) replace(qualifier) else listOf() if (qualifier != null) replace(qualifier) else listOf()
} }
else { else {
@@ -68,28 +63,65 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
} }
is JsUnaryOperation -> { is JsUnaryOperation -> {
when (expression.operator) { when (expression.operator!!) {
JsUnaryOperator.DEC, JsUnaryOperator.INC, JsUnaryOperator.DELETE -> listOf(expression) JsUnaryOperator.BIT_NOT,
else -> replace(expression.arg) JsUnaryOperator.NOT,
JsUnaryOperator.TYPEOF,
JsUnaryOperator.VOID,
JsUnaryOperator.POS,
JsUnaryOperator.NEG -> replace(expression.arg)
JsUnaryOperator.DEC,
JsUnaryOperator.INC,
JsUnaryOperator.DELETE -> listOf(expression)
} }
} }
is JsBinaryOperation -> { is JsBinaryOperation -> {
if (expression.sideEffects) { if (expression.sideEffects) {
when (expression.operator) { when (expression.operator) {
JsBinaryOperator.AND, JsBinaryOperator.OR -> { JsBinaryOperator.BIT_AND,
JsBinaryOperator.BIT_OR,
JsBinaryOperator.BIT_XOR,
JsBinaryOperator.COMMA,
JsBinaryOperator.ADD,
JsBinaryOperator.SUB,
JsBinaryOperator.MUL,
JsBinaryOperator.DIV,
JsBinaryOperator.MOD,
JsBinaryOperator.EQ,
JsBinaryOperator.NEQ,
JsBinaryOperator.REF_EQ,
JsBinaryOperator.REF_NEQ,
JsBinaryOperator.GT,
JsBinaryOperator.GTE,
JsBinaryOperator.LT,
JsBinaryOperator.LTE,
JsBinaryOperator.SHL,
JsBinaryOperator.SHR,
JsBinaryOperator.SHRU -> replace(expression.arg1) + replace(expression.arg2)
JsBinaryOperator.AND,
JsBinaryOperator.OR -> {
val right = replace(expression.arg2) val right = replace(expression.arg2)
if (right.isEmpty()) replace(expression.arg1) else listOf(expression) if (right.isEmpty()) replace(expression.arg1) else listOf(expression)
} }
JsBinaryOperator.INOP, JsBinaryOperator.INSTANCEOF -> listOf(expression)
else -> { JsBinaryOperator.INOP,
if (!expression.operator.isAssignment) { JsBinaryOperator.INSTANCEOF -> listOf(expression)
replace(expression.arg1) + replace(expression.arg2)
} JsBinaryOperator.ASG,
else { JsBinaryOperator.ASG_ADD,
listOf(expression) JsBinaryOperator.ASG_SUB,
} JsBinaryOperator.ASG_MUL,
} JsBinaryOperator.ASG_DIV,
JsBinaryOperator.ASG_MOD,
JsBinaryOperator.ASG_BIT_AND,
JsBinaryOperator.ASG_BIT_OR,
JsBinaryOperator.ASG_BIT_XOR,
JsBinaryOperator.ASG_SHL,
JsBinaryOperator.ASG_SHR,
JsBinaryOperator.ASG_SHRU -> listOf(expression)
} }
} }
else { else {
@@ -118,6 +150,7 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
is JsConditional -> { is JsConditional -> {
val thenExpr = replace(expression.thenExpression) val thenExpr = replace(expression.thenExpression)
val elseExpr = replace(expression.elseExpression) val elseExpr = replace(expression.elseExpression)
// TODO: consider case like this one: cond ? se() + 1 : se() + 2
when { when {
thenExpr.isEmpty() && elseExpr.isEmpty() -> replace(expression.testExpression) thenExpr.isEmpty() && elseExpr.isEmpty() -> replace(expression.testExpression)
thenExpr.isEmpty() -> listOf(JsAstUtils.or(expression.testExpression, expression.elseExpression)) thenExpr.isEmpty() -> listOf(JsAstUtils.or(expression.testExpression, expression.elseExpression))
@@ -145,13 +178,11 @@ class IneffectiveStatementElimination(private val root: JsFunction) {
is JsArrayLiteral -> replaceMany(expression.expressions) is JsArrayLiteral -> replaceMany(expression.expressions)
is JsObjectLiteral -> expression.propertyInitializers.map { replace(it.labelExpr) + replace(it.valueExpr) }.flatten() is JsObjectLiteral -> expression.propertyInitializers.flatMap { replace(it.labelExpr) + replace(it.valueExpr) }
is JsFunction -> if (expression.name == null) listOf() else listOf(expression)
else -> listOf(expression) else -> listOf(expression)
} }
} }
private fun replaceMany(expressions: List<JsExpression>) = expressions.map { replace(it) }.flatten() private fun replaceMany(expressions: List<JsExpression>) = expressions.flatMap { replace(it) }
} }