JS/Inlining: refactor IneffectiveStatementElimination
This commit is contained in:
+57
-26
@@ -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) }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user