[IR] Refactor optimization of eliminating removing extra boxes

Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com>

#KT-1179
This commit is contained in:
Evgeniy.Zhelenskiy
2022-10-20 03:06:42 +02:00
committed by Space Team
parent f2d98eac5e
commit 1660dc21b9
6 changed files with 57 additions and 42 deletions
@@ -697,7 +697,7 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
irCastIfNeeded(irGet(bridgeParameter), targetParameterType),
getOptimizedPublicAccess(target, targetRemappedParameter.rootMfvcNode.mfvc)
) { error("Not applicable") }
val newArguments = instance.makeFlattenedGetterExpressions(this)
val newArguments = instance.makeFlattenedGetterExpressions(this, registerPossibleExtraBoxCreation = {})
for (newArgument in newArguments) {
irCall.putArgument(targetExplicitParameters[targetIndex++], newArgument)
}
@@ -712,7 +712,7 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
irGet(bridgeExplicitParameters[bridgeIndex++])
}
val boxCall = bridgeRemappedParameter.rootMfvcNode.makeBoxedExpression(
this, bridgeRemappedParameter.typeArguments, valueArguments
this, bridgeRemappedParameter.typeArguments, valueArguments, registerPossibleExtraBoxCreation = {}
)
irCall.putArgument(targetParameter, irCastIfNeeded(boxCall, targetParameter.type.upperBound))
}
@@ -140,7 +140,7 @@ private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendCo
irGet(sourceFullValueParameterList[flattenedIndex++])
}
val boxedExpression = remappedParameter.rootMfvcNode.makeBoxedExpression(
this@irBlockBody, remappedParameter.typeArguments, valueArguments
this@irBlockBody, remappedParameter.typeArguments, valueArguments, registerPossibleExtraBoxCreation = {}
)
putValueArgument(i, boxedExpression)
}
@@ -61,7 +61,14 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
}
}
private val boxUsageGenerated = mutableSetOf<IrDeclaration>()
private val possibleExtraBoxUsageGenerated = mutableSetOf<IrDeclaration>()
private val irCurrentScope
get() = currentScope!!.irElement as IrDeclaration
private fun registerPossibleExtraBoxUsage() {
possibleExtraBoxUsageGenerated.add(irCurrentScope)
}
/**
* The class is used to get replacing expression and MFVC instance if present for the given old value declaration.
@@ -89,15 +96,11 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
fun IrBuilderWithScope.makeReplacement(expression: IrGetValue): IrExpression? {
oldValueSymbol2NewValueSymbol[expression.symbol]?.let { return irGet(it.owner) }
val instance = oldSymbol2MfvcNodeInstance[expression.symbol] ?: return null
val res = instance.makeGetterExpression(this)
boxUsageGenerated.add(irCurrentScope)
val res = instance.makeGetterExpression(this, ::registerPossibleExtraBoxUsage)
expression2MfvcNodeInstanceAccessor[res] = MfvcNodeInstanceAccessor.Getter(instance)
return res
}
private val irCurrentScope
get() = currentScope!!.irElement as IrDeclaration
private fun splitExpressions(expressions: List<IrExpression>): Pair<List<IrExpression>, List<IrExpression>> {
val repeatable = expressions.takeLastWhile { it.isRepeatableGetter() }
return expressions.subList(0, expressions.size - repeatable.size) to repeatable
@@ -141,8 +144,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
val typeArguments = makeTypeArgumentsFromField(expression)
val instance: ReceiverBasedMfvcNodeInstance =
node.createInstanceFromBox(this, typeArguments, expression.receiver, AccessType.AlwaysPrivate, ::variablesSaver)
val getterExpression = instance.makeGetterExpression(this)
boxUsageGenerated.add(irCurrentScope)
val getterExpression = instance.makeGetterExpression(this, ::registerPossibleExtraBoxUsage)
expression2MfvcNodeInstanceAccessor[getterExpression] = MfvcNodeInstanceAccessor.Getter(instance)
+getterExpression
return getterExpression
@@ -177,8 +179,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
}
val instance: ReceiverBasedMfvcNodeInstance =
node.createInstanceFromBox(this, typeArguments, dispatchReceiver, accessType, ::variablesSaver)
val getterExpression = instance.makeGetterExpression(this)
boxUsageGenerated.add(irCurrentScope)
val getterExpression = instance.makeGetterExpression(this, ::registerPossibleExtraBoxUsage)
expression2MfvcNodeInstanceAccessor[getterExpression] = MfvcNodeInstanceAccessor.Getter(instance)
+getterExpression
return getterExpression
@@ -227,9 +228,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
val newAccessor = accessor[name] ?: return@handleSavedExpression null
val expression = when (newAccessor) {
is MfvcNodeInstanceAccessor.Setter -> newAccessor.instance.makeSetterExpressions(scope, newAccessor.values)
is MfvcNodeInstanceAccessor.Getter -> newAccessor.instance.makeGetterExpression(scope).also {
boxUsageGenerated.add(irCurrentScope)
}
is MfvcNodeInstanceAccessor.Getter -> newAccessor.instance.makeGetterExpression(scope, ::registerPossibleExtraBoxUsage)
}
expression2MfvcNodeInstanceAccessor[expression] = newAccessor
expression
@@ -239,8 +238,9 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
scope: IrBuilderWithScope,
expression: IrExpression,
handler: IrBlockBuilder.(values: List<IrExpression>) -> IrExpression
): IrExpression? =
scope.handleSavedExpression(expression) { irBlock { +handler(it.instance.makeFlattenedGetterExpressions(this)) }.unwrapBlock() }
): IrExpression? = scope.handleSavedExpression(expression) {
irBlock { +handler(it.instance.makeFlattenedGetterExpressions(this, ::registerPossibleExtraBoxUsage)) }.unwrapBlock()
}
fun registerReplacement(expression: IrExpression, instance: MfvcNodeInstance) {
expression2MfvcNodeInstanceAccessor[expression] = MfvcNodeInstanceAccessor.Getter(instance)
@@ -291,7 +291,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
is IrFunction -> replacingDeclaration.body = replacingDeclaration.body?.makeBodyWithAddedVariables(
context, variablesToAdd[replacingDeclaration] ?: emptySet(), replacingDeclaration.symbol
)?.apply {
if (replacingDeclaration in boxUsageGenerated) {
if (replacingDeclaration in possibleExtraBoxUsageGenerated) {
removeAllExtraBoxes()
}
}
@@ -299,7 +299,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
is IrAnonymousInitializer -> replacingDeclaration.body = replacingDeclaration.body.makeBodyWithAddedVariables(
context, variablesToAdd[replacingDeclaration.parent] ?: emptySet(), replacingDeclaration.symbol
).apply {
if (replacingDeclaration in boxUsageGenerated) {
if (replacingDeclaration in possibleExtraBoxUsageGenerated) {
removeAllExtraBoxes()
}
} as IrBlockBody
@@ -554,7 +554,10 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
.map { irGet(it) }
val targetParameter = targetExplicitParameters[flattenedTargetIndex++]
val boxedExpression = remappedSourceParameter.rootMfvcNode.makeBoxedExpression(
this@irBlock, remappedSourceParameter.typeArguments, valueArguments
this@irBlock,
remappedSourceParameter.typeArguments,
valueArguments,
::registerPossibleExtraBoxUsage
)
putArgument(targetParameter, boxedExpression)
.also { flattenedSourceIndex += remappedSourceParameter.valueParameters.size }
@@ -569,7 +572,8 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
val instance = rootNode.createInstanceFromBox(
this@irBlock, irGet(receiver), getOptimizedPublicAccess(rootNode.mfvc), ::variablesSaver,
)
val flattenedExpressions = instance.makeFlattenedGetterExpressions(this@irBlock)
val flattenedExpressions =
instance.makeFlattenedGetterExpressions(this@irBlock, ::registerPossibleExtraBoxUsage)
for (expression in flattenedExpressions) {
putArgument(targetExplicitParameters[flattenedTargetIndex++], expression)
}
@@ -747,8 +751,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
this, function.constructedClassType as IrSimpleType, Name.identifier("constructor_tmp"), ::variablesSaver
)
flattenExpressionTo(expression, instance)
val getterExpression = instance.makeGetterExpression(this)
boxUsageGenerated.add(currentScope)
val getterExpression = instance.makeGetterExpression(this, ::registerPossibleExtraBoxUsage)
valueDeclarationsRemapper.registerReplacement(getterExpression, instance)
+getterExpression
}
@@ -1117,7 +1120,9 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
}
+irCall(rootNode.primaryConstructorImpl).apply {
copyTypeArgumentsFrom(expression)
for ((index, leafExpression) in instance.makeFlattenedGetterExpressions(this@flattenExpressionTo).withIndex()) {
val flattenedGetterExpressions =
instance.makeFlattenedGetterExpressions(this@flattenExpressionTo, ::registerPossibleExtraBoxUsage)
for ((index, leafExpression) in flattenedGetterExpressions.withIndex()) {
putValueArgument(index, leafExpression)
}
}
@@ -1137,7 +1142,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
this, transformedExpression, getOptimizedPublicAccess(rootNode.mfvc), ::variablesSaver,
)
require(expressionInstance.size == instance.size) { "Incompatible assignment sizes: ${expressionInstance.size}, ${instance.size}" }
instance.addSetterStatements(this, expressionInstance.makeFlattenedGetterExpressions(this))
instance.addSetterStatements(this, expressionInstance.makeFlattenedGetterExpressions(this, ::registerPossibleExtraBoxUsage))
}
private fun getOptimizedPublicAccess(parent: IrClass): AccessType =
@@ -142,7 +142,10 @@ sealed interface MfvcNodeWithSubnodes : MfvcNode {
}
fun MfvcNodeWithSubnodes.makeBoxedExpression(
scope: IrBuilderWithScope, typeArguments: TypeArguments, valueArguments: List<IrExpression>
scope: IrBuilderWithScope,
typeArguments: TypeArguments,
valueArguments: List<IrExpression>,
registerPossibleExtraBoxCreation: () -> Unit,
): IrExpression = scope.irCall(boxMethod).apply {
val resultType = type.substitute(typeArguments) as IrSimpleType
require(resultType.erasedUpperBound == type.erasedUpperBound) { "Substitution of $type led to $resultType" }
@@ -152,6 +155,7 @@ fun MfvcNodeWithSubnodes.makeBoxedExpression(
for ((index, valueArgument) in valueArguments.withIndex()) {
putValueArgument(index, valueArgument)
}
registerPossibleExtraBoxCreation()
}
operator fun MfvcNodeWithSubnodes.get(names: List<Name>): MfvcNode? {
@@ -234,7 +234,7 @@ fun createIntermediateMfvcNode(
) { receiver ->
val valueArguments = subnodes.flatMap { it.fields!! }
.map { field -> irGetField(if (field.isStatic) null else irGet(receiver!!), field) }
rootNode.makeBoxedExpression(this, typeArguments, valueArguments)
rootNode.makeBoxedExpression(this, typeArguments, valueArguments, registerPossibleExtraBoxCreation = {})
}
val hasPureUnboxMethod = defaultMethodsImplementationSourceNode.isPure() && subnodes.all { it.hasPureUnboxMethod }
@@ -23,8 +23,8 @@ interface MfvcNodeInstance {
val typeArguments: TypeArguments
val type: IrSimpleType
fun makeFlattenedGetterExpressions(scope: IrBlockBuilder): List<IrExpression>
fun makeGetterExpression(scope: IrBuilderWithScope): IrExpression
fun makeFlattenedGetterExpressions(scope: IrBlockBuilder, registerPossibleExtraBoxCreation: () -> Unit): List<IrExpression>
fun makeGetterExpression(scope: IrBuilderWithScope, registerPossibleExtraBoxCreation: () -> Unit): IrExpression
operator fun get(name: Name): MfvcNodeInstance?
fun makeStatements(scope: IrBuilderWithScope, values: List<IrExpression>): List<IrStatement>
}
@@ -57,13 +57,16 @@ class ValueDeclarationMfvcNodeInstance(
override val type: IrSimpleType = makeTypeFromMfvcNodeAndTypeArguments(node, typeArguments)
override fun makeFlattenedGetterExpressions(scope: IrBlockBuilder): List<IrExpression> =
override fun makeFlattenedGetterExpressions(scope: IrBlockBuilder, registerPossibleExtraBoxCreation: () -> Unit): List<IrExpression> =
makeFlattenedGetterExpressions(scope as IrBuilderWithScope)
private fun makeFlattenedGetterExpressions(scope: IrBuilderWithScope): List<IrExpression> = valueDeclarations.map { scope.irGet(it) }
override fun makeGetterExpression(scope: IrBuilderWithScope): IrExpression = when (node) {
override fun makeGetterExpression(scope: IrBuilderWithScope, registerPossibleExtraBoxCreation: () -> Unit): IrExpression = when (node) {
is LeafMfvcNode -> makeFlattenedGetterExpressions(scope).single()
is MfvcNodeWithSubnodes -> node.makeBoxedExpression(scope, typeArguments, makeFlattenedGetterExpressions(scope))
is MfvcNodeWithSubnodes -> node.makeBoxedExpression(
scope, typeArguments, makeFlattenedGetterExpressions(scope), registerPossibleExtraBoxCreation
)
}
override fun get(name: Name): ValueDeclarationMfvcNodeInstance? {
@@ -158,19 +161,21 @@ class ReceiverBasedMfvcNodeInstance(
require(node is RootMfvcNode == (unboxMethod == null)) { "Only root node has node getter" }
}
override fun makeFlattenedGetterExpressions(scope: IrBlockBuilder): List<IrExpression> = when (node) {
is LeafMfvcNode -> listOf(makeGetterExpression(scope))
override fun makeFlattenedGetterExpressions(
scope: IrBlockBuilder, registerPossibleExtraBoxCreation: () -> Unit
): List<IrExpression> = when (node) {
is LeafMfvcNode -> listOf(makeGetterExpression(scope, registerPossibleExtraBoxCreation))
is MfvcNodeWithSubnodes -> when {
node is IntermediateMfvcNode && canUsePrivateAccessFor(node) && fields != null ->
fields.map { scope.irGetField(makeReceiverCopy(), it) }
node !is IntermediateMfvcNode || node.hasPureUnboxMethod && (canUsePrivateAccessFor(node) || node.unboxMethod.parentAsClass.isMultiFieldValueClass) ->
// We cannot relay on purity of non-mfvc class getter because the incremental compiler will not recompile the code
// We cannot rely on purity of non-mfvc class getter because the incremental compiler will not recompile the code
// that relayed after the change of purity if it is not local for the class.
node.subnodes.flatMap { get(it.name)!!.makeFlattenedGetterExpressions(scope) }
node.subnodes.flatMap { get(it.name)!!.makeFlattenedGetterExpressions(scope, registerPossibleExtraBoxCreation) }
else -> {
val value = makeGetterExpression(scope)
val value = makeGetterExpression(scope, registerPossibleExtraBoxCreation = { /* The box is definitely useful */ })
val asVariable = scope.savableStandaloneVariableWithSetter(
value,
origin = IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_PARAMETER,
@@ -180,16 +185,17 @@ class ReceiverBasedMfvcNodeInstance(
val root = node.rootNode
val variableInstance =
root.createInstanceFromBox(scope, typeArguments, scope.irGet(asVariable), accessType, saveVariable)
variableInstance.makeFlattenedGetterExpressions(scope)
variableInstance.makeFlattenedGetterExpressions(scope, registerPossibleExtraBoxCreation)
}
}
}
override fun makeGetterExpression(scope: IrBuilderWithScope): IrExpression = with(scope) {
override fun makeGetterExpression(scope: IrBuilderWithScope, registerPossibleExtraBoxCreation: () -> Unit): IrExpression = with(scope) {
when {
node is LeafMfvcNode && canUsePrivateAccessFor(node) && fields != null -> irGetField(makeReceiverCopy(), fields.single())
node is IntermediateMfvcNode && accessType == AccessType.AlwaysPrivate && fields != null ->
node.makeBoxedExpression(this, typeArguments, fields.map { irGetField(makeReceiverCopy(), it) })
node is IntermediateMfvcNode && accessType == AccessType.AlwaysPrivate && fields != null -> node.makeBoxedExpression(
this, typeArguments, fields.map { irGetField(makeReceiverCopy(), it) }, registerPossibleExtraBoxCreation
)
unboxMethod != null -> irCall(unboxMethod).apply {
val dispatchReceiverParameter = unboxMethod.dispatchReceiverParameter