From 368ac362047e61024f70697de20b78c9cfa85f4e Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Mon, 29 Mar 2021 12:51:27 +0300 Subject: [PATCH] [IR] Remove IrExpressionWithCopy and replace with shallowCopy method --- .../kotlin/backend/common/ir/IrUtils.kt | 13 +---- .../lower/IfNullExpressionsFusionLowering.kt | 11 ++-- .../common/lower/RangeContainsLowering.kt | 17 +++--- .../common/lower/inline/FunctionInlining.kt | 4 -- .../common/lower/loops/HeaderProcessor.kt | 12 ++--- .../backend/common/lower/loops/Utils.kt | 12 +---- .../handlers/DefaultProgressionHandler.kt | 7 +-- .../lower/loops/handlers/StepHandler.kt | 38 +++++++------- .../backend/js/lower/TypeOperatorLowering.kt | 14 +++-- .../MoveCompanionObjectFieldsLowering.kt | 2 +- .../wasm/lower/WasmTypeOperatorLowering.kt | 30 +++++------ .../generators/ArgumentsGenerationUtils.kt | 3 +- .../intermediate/RematerializableValue.kt | 6 +-- .../kotlin/ir/expressions/IrConst.kt | 3 +- .../ir/expressions/IrDeclarationReference.kt | 2 +- .../kotlin/ir/expressions/IrExpression.kt | 6 +-- .../ir/expressions/IrValueAccessExpression.kt | 4 +- .../kotlin/ir/expressions/impl/IrConstImpl.kt | 3 -- .../expressions/impl/IrErrorExpressionImpl.kt | 6 +-- .../expressions/impl/IrGetObjectValueImpl.kt | 4 -- .../ir/expressions/impl/IrGetValueImpl.kt | 3 -- .../ir/util/DeepCopyIrTreeWithSymbols.kt | 2 +- .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 52 +++++++++++++++++-- 23 files changed, 126 insertions(+), 128 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt index 6ebdb686399..938e05b278f 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt @@ -18,10 +18,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.* import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol @@ -695,10 +692,4 @@ fun IrExpression?.isPure( } return false -} - -fun IrExpression.isTrivial() = - this is IrConst<*> || - this is IrGetValue || - this is IrGetObjectValue || - this is IrErrorExpressionImpl \ No newline at end of file +} \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/IfNullExpressionsFusionLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/IfNullExpressionsFusionLowering.kt index 0bf77f8637d..68f27aa6574 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/IfNullExpressionsFusionLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/IfNullExpressionsFusionLowering.kt @@ -7,8 +7,6 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.backend.common.ir.isTrivial -import org.jetbrains.kotlin.backend.common.lower.loops.canHaveSideEffects import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.ir.builders.createTmpVariable import org.jetbrains.kotlin.ir.builders.irBlock @@ -16,13 +14,13 @@ import org.jetbrains.kotlin.ir.builders.irGet import org.jetbrains.kotlin.ir.builders.irIfNull import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.isNullable import org.jetbrains.kotlin.ir.util.fileOrNull -import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.ir.util.isTrivial +import org.jetbrains.kotlin.ir.util.shallowCopy import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -195,10 +193,7 @@ class IfNullExpressionsFusionLowering(val context: CommonBackendContext) : FileL private fun IrExpression.copyIfTrivial() = if (isTrivial()) { - require(this is IrExpressionWithCopy) { - "Not a copyable expression: ${render()}" - } - copy() + shallowCopy() } else this private fun IrExpression.remap(from: IrVariable, to: Lazy): IrExpression = diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/RangeContainsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/RangeContainsLowering.kt index 77d55ef14f8..dd33986adf1 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/RangeContainsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/RangeContainsLowering.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.ir.util.shallowCopy import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.util.OperatorNameConventions @@ -262,20 +263,20 @@ private class Transformer( additionalStatements.addIfNotNull(lowerVar) additionalStatements.addIfNotNull(upperVar) } - lowerExpression = tmpLowerExpression.copy() - upperExpression = tmpUpperExpression.copy() + lowerExpression = tmpLowerExpression.shallowCopy() + upperExpression = tmpUpperExpression.shallowCopy() useLowerClauseOnLeftSide = true } else if (lower.canHaveSideEffects && upper.canHaveSideEffects) { if (shouldUpperComeFirst) { val (upperVar, tmpUpperExpression) = createTemporaryVariableIfNecessary(upper, "containsUpper") additionalStatements.add(upperVar!!) lowerExpression = lower - upperExpression = tmpUpperExpression.copy() + upperExpression = tmpUpperExpression.shallowCopy() useLowerClauseOnLeftSide = true } else { val (lowerVar, tmpLowerExpression) = createTemporaryVariableIfNecessary(lower, "containsLower") additionalStatements.add(lowerVar!!) - lowerExpression = tmpLowerExpression.copy() + lowerExpression = tmpLowerExpression.shallowCopy() upperExpression = upper useLowerClauseOnLeftSide = false } @@ -311,27 +312,27 @@ private class Transformer( irCall(lowerCompFun).apply { putValueArgument(0, irInt(0)) putValueArgument(1, irCall(compareToFun).apply { - dispatchReceiver = argExpression.copy() + dispatchReceiver = argExpression.shallowCopy() putValueArgument(0, lowerExpression) }) } } else { irCall(lowerCompFun).apply { putValueArgument(0, lowerExpression) - putValueArgument(1, argExpression.copy()) + putValueArgument(1, argExpression.shallowCopy()) } } val upperClause = if (useCompareTo) { irCall(upperCompFun).apply { putValueArgument(0, irCall(compareToFun).apply { - dispatchReceiver = argExpression.copy() + dispatchReceiver = argExpression.shallowCopy() putValueArgument(0, upperExpression) }) putValueArgument(1, irInt(0)) } } else { irCall(upperCompFun).apply { - putValueArgument(0, argExpression.copy()) + putValueArgument(0, argExpression.shallowCopy()) putValueArgument(1, upperExpression) } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt index 53e69482d6c..bacff4fc511 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt @@ -592,10 +592,6 @@ class FunctionInlining( override fun accept(visitor: IrElementVisitor, data: D) = visitor.visitGetValue(this, data) - override fun copy(): IrGetValue { - TODO("not implemented") - } - fun withLocation(startOffset: Int, endOffset: Int) = IrGetValueImpl(startOffset, endOffset, type, symbol, origin) } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt index 321b3429224..e426b197d04 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt @@ -66,13 +66,13 @@ internal abstract class NumericForLoopHeader( val inductionVariable: IrVariable protected val stepVariable: IrVariable? - val stepExpression: IrExpressionWithCopy + val stepExpression: IrExpression protected val lastVariableIfCanCacheLast: IrVariable? protected val lastExpression: IrExpression // If this is not `IrExpressionWithCopy`, then it is `.getSize()` built in `IndexedGetIterationHandler`. // It is therefore safe to deep-copy as it does not contain any functions or classes. - get() = if (field is IrExpressionWithCopy) field.copy() else field.deepCopyWithSymbols() + get() = field.shallowCopyOrNull() ?: field.deepCopyWithSymbols() protected val symbols = context.ir.symbols @@ -105,7 +105,7 @@ internal abstract class NumericForLoopHeader( if (headerInfo.canCacheLast) { val (variable, expression) = createTemporaryVariableIfNecessary(last, nameHint = "last") lastVariableIfCanCacheLast = variable - lastExpression = expression.copy() + lastExpression = expression.shallowCopy() } else { lastVariableIfCanCacheLast = null lastExpression = last @@ -146,7 +146,7 @@ internal abstract class NumericForLoopHeader( inductionVariable.symbol, irCallOp( plusFun.symbol, plusFun.returnType, irGet(inductionVariable), - stepExpression.copy(), IrStatementOrigin.PLUSEQ + stepExpression.shallowCopy(), IrStatementOrigin.PLUSEQ ), IrStatementOrigin.PLUSEQ ) } @@ -225,14 +225,14 @@ internal abstract class NumericForLoopHeader( context.oror( context.andand( irCall(builtIns.greaterFunByOperandType.getValue(stepClass.symbol)).apply { - putValueArgument(0, stepExpression.copy()) + putValueArgument(0, stepExpression.shallowCopy()) putValueArgument(1, zeroStepExpression()) }, conditionForIncreasing() ), context.andand( irCall(builtIns.lessFunByOperandType.getValue(stepClass.symbol)).apply { - putValueArgument(0, stepExpression.copy()) + putValueArgument(0, stepExpression.shallowCopy()) putValueArgument(1, zeroStepExpression()) }, conditionForDecreasing() diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/Utils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/Utils.kt index 97a4cef914e..226f0dfa5e8 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/Utils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/Utils.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.backend.common.lower.loops -import org.jetbrains.kotlin.backend.common.ir.isTrivial import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.ir.builders.createTmpVariable import org.jetbrains.kotlin.ir.builders.irGet @@ -14,13 +13,12 @@ import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.functions -import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.ir.util.isTrivial import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.util.OperatorNameConventions @@ -82,9 +80,6 @@ private fun Any?.toLong(): Long? = else -> null } -internal val IrExpressionWithCopy.constLongValue: Long? - get() = if (this is IrConst<*>) value.toLong() else null - internal val IrExpression.constLongValue: Long? get() = if (this is IrConst<*>) value.toLong() else null @@ -97,13 +92,10 @@ internal val IrExpression.constLongValue: Long? internal fun DeclarationIrBuilder.createTemporaryVariableIfNecessary( expression: IrExpression, nameHint: String? = null, irType: IrType? = null, isMutable: Boolean = false -): Pair = +): Pair = if (expression.canHaveSideEffects) { scope.createTmpVariable(expression, nameHint = nameHint, irType = irType, isMutable = isMutable).let { Pair(it, irGet(it)) } } else { - require(expression is IrExpressionWithCopy) { - "Not a copyable expression: ${expression.render()}" - } Pair(null, expression) } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultProgressionHandler.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultProgressionHandler.kt index fd39c8eff54..a07d4e13a35 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultProgressionHandler.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultProgressionHandler.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.util.getPropertyGetter +import org.jetbrains.kotlin.ir.util.shallowCopy /** Builds a [HeaderInfo] for progressions not handled by more specialized handlers. */ internal class DefaultProgressionHandler(private val context: CommonBackendContext, private val allowUnsignedBounds: Boolean = false) : @@ -35,10 +36,10 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte val (progressionVar, progressionExpression) = createTemporaryVariableIfNecessary(expression, nameHint = "progression") val progressionClass = expression.type.getClass()!! val first = irCall(progressionClass.symbol.getPropertyGetter("first")!!).apply { - dispatchReceiver = progressionExpression.copy() + dispatchReceiver = progressionExpression.shallowCopy() } val last = irCall(progressionClass.symbol.getPropertyGetter("last")!!).apply { - dispatchReceiver = progressionExpression.copy() + dispatchReceiver = progressionExpression.shallowCopy() } // *Ranges (e.g., IntRange) have step == 1 and is always increasing. @@ -47,7 +48,7 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte irInt(1) } else { irCall(progressionClass.symbol.getPropertyGetter("step")!!).apply { - dispatchReceiver = progressionExpression.copy() + dispatchReceiver = progressionExpression.shallowCopy() } } val direction = if (isRange) ProgressionDirection.INCREASING else ProgressionDirection.UNKNOWN diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/StepHandler.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/StepHandler.kt index c2cfbb494b6..033bb3c5d6e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/StepHandler.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/StepHandler.kt @@ -16,12 +16,12 @@ import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.isInt import org.jetbrains.kotlin.ir.types.isLong import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.shallowCopy import org.jetbrains.kotlin.name.FqName import kotlin.math.absoluteValue @@ -79,7 +79,7 @@ internal class StepHandler( irCall(context.irBuiltIns.illegalArgumentExceptionSymbol).apply { val exceptionMessage = irConcat() exceptionMessage.addArgument(irString("Step must be positive, was: ")) - exceptionMessage.addArgument(stepArgExpression.copy()) + exceptionMessage.addArgument(stepArgExpression.shallowCopy()) exceptionMessage.addArgument(irString(".")) putValueArgument(0, exceptionMessage) } @@ -89,7 +89,7 @@ internal class StepHandler( stepArgValueAsLong == null -> { // Step argument is not a constant. In this case, we check if step <= 0. val stepNonPositiveCheck = irCall(stepCompFun).apply { - putValueArgument(0, stepArgExpression.copy()) + putValueArgument(0, stepArgExpression.shallowCopy()) putValueArgument(1, data.run { zeroStepExpression() }) } irIfThen( @@ -118,7 +118,7 @@ internal class StepHandler( ProgressionDirection.INCREASING -> stepArgExpression ProgressionDirection.DECREASING -> { if (stepArgVar == null) { - stepNegation = scope.createTmpVariable(stepArgExpression.copy().negate()) + stepNegation = scope.createTmpVariable(stepArgExpression.shallowCopy().negate()) irGet(stepNegation) } else { // Step is already stored in a variable, just negate it. @@ -133,7 +133,7 @@ internal class StepHandler( val (tmpNestedStepVar, nestedStepExpression) = createTemporaryVariableIfNecessary(nestedStep, "nestedStep") nestedStepVar = tmpNestedStepVar val nestedStepNonPositiveCheck = irCall(stepCompFun).apply { - putValueArgument(0, nestedStepExpression.copy()) + putValueArgument(0, nestedStepExpression.shallowCopy()) putValueArgument(1, data.run { zeroStepExpression() }) } if (stepArgVar == null) { @@ -142,8 +142,8 @@ internal class StepHandler( irIfThenElse( stepType, nestedStepNonPositiveCheck, - stepArgExpression.copy().negate(), - stepArgExpression.copy() + stepArgExpression.shallowCopy().negate(), + stepArgExpression.shallowCopy() ), nameHint = "maybeNegatedStep" ) @@ -272,9 +272,9 @@ internal class StepHandler( return ProgressionHeaderInfo( data, - first = nestedFirstExpression.copy(), + first = nestedFirstExpression.shallowCopy(), last = recalculatedLast, - step = finalStepExpression.copy(), + step = finalStepExpression.shallowCopy(), isReversed = nestedInfo.isReversed, additionalStatements = additionalStatements, direction = nestedInfo.direction @@ -283,13 +283,13 @@ internal class StepHandler( private fun DeclarationIrBuilder.callGetProgressionLastElementIfNecessary( progressionType: ProgressionType, - first: IrExpressionWithCopy, - last: IrExpressionWithCopy, - step: IrExpressionWithCopy + first: IrExpression, + last: IrExpression, + step: IrExpression ): IrExpression { // Calling getProgressionLastElement() is not needed if step == 1 or -1; the "last" value is unchanged in such cases. if (step.constLongValue?.absoluteValue == 1L) { - return last.copy() + return last.shallowCopy() } // Call `getProgressionLastElement(first, last, step)`. The following overloads are present in the stdlib: @@ -304,17 +304,17 @@ internal class StepHandler( // Bounds are signed for unsigned progressions but `getProgressionLastElement` expects unsigned. // The return value is finally converted back to signed since it will be assigned back to `last`. irCall(getProgressionLastElementFun).apply { - putValueArgument(0, first.copy().asElementType().asUnsigned()) - putValueArgument(1, last.copy().asElementType().asUnsigned()) - putValueArgument(2, step.copy().asStepType()) + putValueArgument(0, first.shallowCopy().asElementType().asUnsigned()) + putValueArgument(1, last.shallowCopy().asElementType().asUnsigned()) + putValueArgument(2, step.shallowCopy().asStepType()) }.asSigned() } else { irCall(getProgressionLastElementFun).apply { // Step type is used for casting because it works for all signed progressions. In particular, // getProgressionLastElement(Int, Int, Int) is called for CharProgression, which uses an Int step. - putValueArgument(0, first.copy().asStepType()) - putValueArgument(1, last.copy().asStepType()) - putValueArgument(2, step.copy().asStepType()) + putValueArgument(0, first.shallowCopy().asStepType()) + putValueArgument(1, last.shallowCopy().asStepType()) + putValueArgument(2, step.shallowCopy().asStepType()) } } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt index a637274fa3e..f12d050e009 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt @@ -6,15 +6,15 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.BodyLoweringPass +import org.jetbrains.kotlin.backend.common.ir.isPure import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.backend.common.ir.isPure import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclaration -import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl @@ -47,6 +47,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass { private val isInterfaceSymbol get() = context.intrinsics.isInterfaceSymbol private val isArraySymbol get() = context.intrinsics.isArraySymbol private val isSuspendFunctionSymbol = context.intrinsics.isSuspendFunctionSymbol + // private val isCharSymbol get() = context.intrinsics.isCharSymbol private val isObjectSymbol get() = context.intrinsics.isObjectSymbol @@ -269,11 +270,8 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass { // assert(!typeParameter.isReified) { "reified parameters have to be lowered before" } return typeParameter.superTypes.fold(null) { r, t -> - val copy = if (argument is IrExpressionWithCopy) { - argument.copy() - } else { - argument.deepCopyWithSymbols() - } + val copy = argument.shallowCopyOrNull() + ?: argument.deepCopyWithSymbols() val check = generateTypeCheckNonNull(copy, t.makeNotNull()) if (r == null) { @@ -361,7 +359,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass { val toType = expression.typeOperand fun maskOp(arg: IrExpression, mask: IrExpression, shift: IrConst<*>) = calculator.run { - shr(shl(and(arg, mask), shift), shift.copy()) + shr(shl(and(arg, mask), shift), shift.shallowCopy()) } val newStatements = mutableListOf() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt index 9c143d7364c..8369657f151 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt @@ -122,7 +122,7 @@ private class MoveOrCopyCompanionObjectFieldsLowering(val context: JvmBackendCon correspondingPropertySymbol = property.symbol annotations += oldField.annotations initializer = with(oldField.initializer!!) { - IrExpressionBodyImpl(startOffset, endOffset, (expression as IrConst<*>).copy()) + IrExpressionBodyImpl(startOffset, endOffset, (expression as IrConst<*>).shallowCopy()) } if (oldProperty.parentAsClass.visibility == DescriptorVisibilities.PRIVATE) { diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt index 7a94da077ef..d66177f9ec1 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt @@ -69,8 +69,8 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme } } - private fun IrBlockBuilder.cacheValue(value: IrExpression): () -> IrExpressionWithCopy { - if (value.isPure(true) && value is IrExpressionWithCopy) { + private fun IrBlockBuilder.cacheValue(value: IrExpression): () -> IrExpression { + if (value.isPure(true) && value.isTrivial()) { return { value.deepCopyWithSymbols() } } val tmpVal = createTmpVariable(value) @@ -84,12 +84,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme get() = this.erasedUpperBound?.defaultType ?: builtIns.anyType private fun generateTypeCheck( - valueProvider: () -> IrExpressionWithCopy, + valueProvider: () -> IrExpression, toType: IrType ): IrExpression { val toNotNullable = toType.makeNotNull() - val valueInstance: IrExpressionWithCopy = valueProvider() - val fromType = (valueInstance as IrExpression).type + val valueInstance: IrExpression = valueProvider() + val fromType = valueInstance.type // Inlined values have no type information on runtime. // But since they are final we can compute type checks on compile time. @@ -108,7 +108,7 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme else -> builder.irIfThenElse( type = builtIns.booleanType, - condition = builder.irEqualsNull(valueProvider() as IrExpression), + condition = builder.irEqualsNull(valueProvider()), thenPart = builder.irBoolean(isToNullable), elsePart = instanceCheck ) @@ -129,16 +129,16 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme else -> error("Unreachable execution (coercion to non-Integer type") } - private fun generateTypeCheckNonNull(argument: IrExpressionWithCopy, toType: IrType): IrExpression { + private fun generateTypeCheckNonNull(argument: IrExpression, toType: IrType): IrExpression { assert(!toType.isMarkedNullable()) return when { toType.isNothing() -> builder.irComposite(resultType = builtIns.booleanType) { - +(argument as IrExpression) + +(argument) +builder.irFalse() } toType.isTypeParameter() -> generateTypeCheckWithTypeParameter(argument, toType) - toType.isInterface() -> generateIsInterface(argument as IrExpression, toType) - else -> generateIsSubClass(argument as IrExpression, toType) + toType.isInterface() -> generateIsInterface(argument, toType) + else -> generateIsSubClass(argument, toType) } } @@ -188,12 +188,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme val cachedValue = cacheValue(value) +builder.irIfNull( type = toType, - subject = cachedValue() as IrExpression, + subject = cachedValue(), thenPart = builder.irNull(toType), elsePart = builder.irCall(symbols.wasmRefCast, type = toType).apply { putTypeArgument(0, fromType) putTypeArgument(1, toType) - putValueArgument(0, cachedValue() as IrExpression) + putValueArgument(0, cachedValue()) } ) } @@ -225,7 +225,7 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme return builder.irComposite(resultType = expression.type) { val argument = cacheValue(expression.argument) - val narrowArg = narrowType(fromType, expression.type, argument() as IrExpression) + val narrowArg = narrowType(fromType, expression.type, argument()) val check = generateTypeCheck(argument, toType) if (check is IrConst<*>) { val value = check.value as Boolean @@ -252,12 +252,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme value = expression.argument ) - private fun generateTypeCheckWithTypeParameter(argument: IrExpressionWithCopy, toType: IrType): IrExpression { + private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: IrType): IrExpression { val typeParameter = toType.classifierOrNull?.owner as? IrTypeParameter ?: error("expected type parameter, but got $toType") return typeParameter.superTypes.fold(builder.irTrue() as IrExpression) { r, t -> - val check = generateTypeCheckNonNull(argument.copy() as IrExpressionWithCopy, t.makeNotNull()) + val check = generateTypeCheckNonNull(argument.shallowCopy(), t.makeNotNull()) builder.irCall(symbols.booleanAnd).apply { putValueArgument(0, r) putValueArgument(1, check) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index ffc989df5fb..694b4acc809 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.isTrivial import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtExpression @@ -109,7 +110,7 @@ fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffse TODO("Receiver: ${receiver::class.java.simpleName}") } - if (receiverExpression is IrExpressionWithCopy) + if (receiverExpression.isTrivial()) RematerializableValue(receiverExpression.type, receiverExpression) else OnceExpressionValue(receiverExpression) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/RematerializableValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/RematerializableValue.kt index 17c805aaa2f..289fd93658b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/RematerializableValue.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/RematerializableValue.kt @@ -19,12 +19,12 @@ package org.jetbrains.kotlin.psi2ir.intermediate import org.jetbrains.kotlin.ir.builders.IrGeneratorContext import org.jetbrains.kotlin.ir.builders.Scope import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy import org.jetbrains.kotlin.ir.expressions.IrStatementContainer import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.shallowCopy -class RematerializableValue(override val type: IrType, val irExpression: IrExpressionWithCopy) : IntermediateValue { - override fun load(): IrExpression = irExpression.copy() +class RematerializableValue(override val type: IrType, val irExpression: IrExpression) : IntermediateValue { + override fun load(): IrExpression = irExpression.shallowCopy() } fun Scope.createTemporaryVariableInBlock( diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt index 524c2860dcb..072dd40ea59 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt @@ -16,11 +16,10 @@ package org.jetbrains.kotlin.ir.expressions -abstract class IrConst : IrExpression(), IrExpressionWithCopy { +abstract class IrConst : IrExpression() { abstract val kind: IrConstKind abstract val value: T - abstract override fun copy(): IrConst abstract fun copyWithOffsets(startOffset: Int, endOffset: Int): IrConst } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt index 68db3f2622c..8536230156d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt @@ -27,7 +27,7 @@ abstract class IrDeclarationReference : IrExpression() { abstract class IrGetSingletonValue : IrDeclarationReference() -abstract class IrGetObjectValue : IrGetSingletonValue(), IrExpressionWithCopy { +abstract class IrGetObjectValue : IrGetSingletonValue() { abstract override val symbol: IrClassSymbol } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt index af934a864e2..a7f8bf4f4b7 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt @@ -39,8 +39,4 @@ abstract class IrExpression : IrElementBase(), IrStatement, IrVarargElement, IrA override fun transformChildren(transformer: IrElementTransformer, data: D) { // No children by default } -} - -interface IrExpressionWithCopy { - fun copy(): IrExpression -} +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrValueAccessExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrValueAccessExpression.kt index 1c165cc0ef7..b30f24dbad5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrValueAccessExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrValueAccessExpression.kt @@ -25,9 +25,7 @@ abstract class IrValueAccessExpression : IrDeclarationReference() { abstract val origin: IrStatementOrigin? } -abstract class IrGetValue : IrValueAccessExpression(), IrExpressionWithCopy { - abstract override fun copy(): IrGetValue -} +abstract class IrGetValue : IrValueAccessExpression() abstract class IrSetValue : IrValueAccessExpression() { abstract override val symbol: IrValueSymbol diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstImpl.kt index d5e49c4c706..64d54fc6755 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstImpl.kt @@ -32,9 +32,6 @@ class IrConstImpl( override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitConst(this, data) - override fun copy(): IrConst = - IrConstImpl(startOffset, endOffset, type, kind, value) - override fun copyWithOffsets(startOffset: Int, endOffset: Int) = IrConstImpl(startOffset, endOffset, type, kind, value) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrErrorExpressionImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrErrorExpressionImpl.kt index d161d55071c..d0efeb37b6f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrErrorExpressionImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrErrorExpressionImpl.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.ir.expressions.impl import org.jetbrains.kotlin.ir.expressions.IrErrorExpression -import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -26,10 +25,7 @@ class IrErrorExpressionImpl( override val endOffset: Int, override var type: IrType, override val description: String -) : IrErrorExpression(), IrExpressionWithCopy { +) : IrErrorExpression() { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitErrorExpression(this, data) - - override fun copy(): IrErrorExpressionImpl = - IrErrorExpressionImpl(startOffset, endOffset, type, description) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetObjectValueImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetObjectValueImpl.kt index 4d94a1aa808..4b2541cec62 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetObjectValueImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetObjectValueImpl.kt @@ -30,8 +30,4 @@ class IrGetObjectValueImpl( ) : IrGetObjectValue() { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetObjectValue(this, data) - - override fun copy(): IrExpression { - return IrGetObjectValueImpl(startOffset, endOffset, type, symbol) - } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetValueImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetValueImpl.kt index 775869939c0..e8c2b4c0bb4 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetValueImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrGetValueImpl.kt @@ -27,7 +27,4 @@ class IrGetValueImpl( override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetValue(this, data) - - override fun copy(): IrGetValue = - IrGetValueImpl(startOffset, endOffset, type, symbol, origin) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index daa081be8b6..a9d92a2d2a4 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -392,7 +392,7 @@ open class DeepCopyIrTreeWithSymbols( throw IllegalArgumentException("Unsupported expression type: $expression") override fun visitConst(expression: IrConst): IrConst = - expression.copy().copyAttributes(expression) + expression.shallowCopy().copyAttributes(expression) override fun visitVararg(expression: IrVararg): IrVararg = IrVarargImpl( diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index 81e8d7f41e3..652fcada961 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -12,9 +12,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.name.FqName @@ -558,4 +556,50 @@ val IrFunction.originalFunction: IrFunction get() = (this as? IrAttributeContainer)?.attributeOwnerId as? IrFunction ?: this val IrProperty.originalProperty: IrProperty - get() = attributeOwnerId as? IrProperty ?: this \ No newline at end of file + get() = attributeOwnerId as? IrProperty ?: this + +fun IrExpression.isTrivial() = + this is IrConst<*> || + this is IrGetValue || + this is IrGetObjectValue || + this is IrErrorExpressionImpl + +fun IrExpression.shallowCopy(): IrExpression = + shallowCopyOrNull() + ?: error("Not a copyable expression: ${render()}") + +fun IrExpression.shallowCopyOrNull(): IrExpression? = + when (this) { + is IrConst<*> -> shallowCopy() + is IrGetObjectValue -> + IrGetObjectValueImpl( + startOffset, + endOffset, + type, + symbol + ) + is IrGetValueImpl -> + IrGetValueImpl( + startOffset, + endOffset, + type, + symbol, + origin + ) + is IrErrorExpressionImpl -> + IrErrorExpressionImpl( + startOffset, + endOffset, + type, + description + ) + else -> null + } + +internal fun IrConst.shallowCopy() = IrConstImpl( + startOffset, + endOffset, + type, + kind, + value +) \ No newline at end of file