From 0aae760469a1dfda62fd0d57b94fcfe52116c501 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Sun, 5 May 2019 18:56:09 +0300 Subject: [PATCH] [JS IR BE] Fix block decomposition lowering for dynamic expressions --- .../js/lower/BlockDecomposerLowering.kt | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt index 72aedb8dc09..119cece156d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BlockDecomposerLowering.kt @@ -456,26 +456,30 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl private fun mapArguments( oldArguments: Collection, compositeCount: Int, - newStatements: MutableList + newStatements: MutableList, + dontDetachFirstArgument: Boolean = false ): List { var compositesLeft = compositeCount val arguments = mutableListOf() - for (arg in oldArguments) { + for ((index, arg) in oldArguments.withIndex()) { val value = if (arg is IrComposite) { compositesLeft-- newStatements += arg.statements.run { subList(0, lastIndex) } arg.statements.last() as IrExpression } else arg - val newArg = if (compositesLeft != 0) { - if (value != null) { + val newArg = when { + compositesLeft == 0 -> value + index == 0 && dontDetachFirstArgument -> value + value == null -> value + else -> { // TODO: do not wrap if value is pure (const, variable, etc) val irVar = makeTempVar(value.type, value) newStatements += irVar JsIrBuilder.buildGetValue(irVar.symbol) - } else value - } else value + } + } arguments += newArg } @@ -561,7 +565,12 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl if (compositeCount == 0) return expression val newStatements = mutableListOf() - val newArguments = mapArguments(oldArguments, compositeCount, newStatements) + val newArguments = mapArguments( + oldArguments, + compositeCount, + newStatements, + dontDetachFirstArgument = expression.isReceiverNonDetachable() + ) expression.receiver = newArguments[0] ?: error("No new receiver in destructured composite for:\n${expression.dump()}") @@ -576,6 +585,23 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl return expression.run { IrCompositeImpl(startOffset, endOffset, type, null, newStatements) } } + // Return if receiver expression cannot be detached from this expression + private fun IrDynamicOperatorExpression.isReceiverNonDetachable(): Boolean { + val receiver = when (val r = this.receiver) { + is IrComposite -> r.statements.lastOrNull() ?: return false + else -> r + } + + val receiverIsMemberAccess = + receiver is IrDynamicMemberExpression || + (receiver is IrDynamicOperatorExpression && receiver.operator == IrDynamicOperator.ARRAY_ACCESS) + + val operatorDependsOnMemberAccess = + operator.isAssignmentOperator || operator == IrDynamicOperator.INVOKE + + return receiverIsMemberAccess && operatorDependsOnMemberAccess + } + override fun visitContainerExpression(expression: IrContainerExpression): IrExpression { expression.run { if (statements.isEmpty()) return IrCompositeImpl(startOffset, endOffset, type, origin, listOf(unitValue)) }