diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt index b63dce302b6..19b255dbb76 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt @@ -60,6 +60,8 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV } } + private val boxUsageGenerated = mutableSetOf() + /** * The class is used to get replacing expression and MFVC instance if present for the given old value declaration. */ @@ -87,10 +89,14 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV oldValueSymbol2NewValueSymbol[expression.symbol]?.let { return irGet(it.owner) } val instance = oldSymbol2MfvcNodeInstance[expression.symbol] ?: return null val res = instance.makeGetterExpression(this) + boxUsageGenerated.add(irCurrentScope) expression2MfvcNodeInstanceAccessor[res] = MfvcNodeInstanceAccessor.Getter(instance) return res } + private val irCurrentScope + get() = currentScope!!.irElement as IrDeclaration + private fun splitExpressions(expressions: List): Pair, List> { val repeatable = expressions.takeLastWhile { it.isRepeatableGetter() } return expressions.subList(0, expressions.size - repeatable.size) to repeatable @@ -135,6 +141,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV val instance: ReceiverBasedMfvcNodeInstance = node.createInstanceFromBox(this, typeArguments, expression.receiver, AccessType.AlwaysPrivate, ::variablesSaver) val getterExpression = instance.makeGetterExpression(this) + boxUsageGenerated.add(irCurrentScope) expression2MfvcNodeInstanceAccessor[getterExpression] = MfvcNodeInstanceAccessor.Getter(instance) +getterExpression return getterExpression @@ -170,6 +177,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) expression2MfvcNodeInstanceAccessor[getterExpression] = MfvcNodeInstanceAccessor.Getter(instance) +getterExpression return getterExpression @@ -217,8 +225,10 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV fun IrExpression.get(scope: IrBuilderWithScope, name: Name): IrExpression? = scope.handleSavedExpression(this) { accessor -> val newAccessor = accessor[name] ?: return@handleSavedExpression null val expression = when (newAccessor) { - is MfvcNodeInstanceAccessor.Getter -> newAccessor.instance.makeGetterExpression(scope) is MfvcNodeInstanceAccessor.Setter -> newAccessor.instance.makeSetterExpressions(scope, newAccessor.values) + is MfvcNodeInstanceAccessor.Getter -> newAccessor.instance.makeGetterExpression(scope).also { + boxUsageGenerated.add(irCurrentScope) + } } expression2MfvcNodeInstanceAccessor[expression] = newAccessor expression @@ -279,11 +289,19 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV when (replacingDeclaration) { is IrFunction -> replacingDeclaration.body = replacingDeclaration.body?.makeBodyWithAddedVariables( context, variablesToAdd[replacingDeclaration] ?: emptySet(), replacingDeclaration.symbol - )?.apply { removeAllExtraBoxes() } + )?.apply { + if (replacingDeclaration in boxUsageGenerated) { + removeAllExtraBoxes() + } + } is IrAnonymousInitializer -> replacingDeclaration.body = replacingDeclaration.body.makeBodyWithAddedVariables( context, variablesToAdd[replacingDeclaration.parent] ?: emptySet(), replacingDeclaration.symbol - ).apply { removeAllExtraBoxes() } as IrBlockBody + ).apply { + if (replacingDeclaration in boxUsageGenerated) { + removeAllExtraBoxes() + } + } as IrBlockBody else -> Unit } @@ -726,6 +744,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV ) flattenExpressionTo(expression, instance) val getterExpression = instance.makeGetterExpression(this) + boxUsageGenerated.add(currentScope) valueDeclarationsRemapper.registerReplacement(getterExpression, instance) +getterExpression } diff --git a/compiler/testData/codegen/bytecodeText/valueClasses/passingMFVC2Functions.kt b/compiler/testData/codegen/bytecodeText/valueClasses/passingMFVC2Functions.kt index 065bd793e93..c1bee05c110 100644 --- a/compiler/testData/codegen/bytecodeText/valueClasses/passingMFVC2Functions.kt +++ b/compiler/testData/codegen/bytecodeText/valueClasses/passingMFVC2Functions.kt @@ -37,6 +37,13 @@ fun testIgnoredBoxed() { returnBoxed() } +object Init { + init { + DPoint(1.0, 2.0) + DPoint(1.0, 2.0) + } +} + // 1 testFlattened2Boxed\(\)V(\n {3}.*)*((\n {3}.*box-impl .*)(\n {3}.*)*){1} // 0 testFlattened2Boxed\(\)V(\n {3}.*)*((\n {3}.*box-impl.*)(\n {3}.*)*){2} // 0 testBoxed2Boxed\(\)V(\n {3}.*)*((\n {3}.*(box-impl|DSTORE|DLOAD).*)(\n {3}.*)*){1} @@ -48,3 +55,4 @@ fun testIgnoredBoxed() { // 0 testBoxed2Flattened\(\)V(\n {3}.*)*((\n {3}.*unbox-impl.*)(\n {3}.*)*){3} // 0 testIgnoredFlattened\(\)V(\n {3}.*)*((\n {3}.*box-impl.*)(\n {3}.*)*){1} // 0 testIgnoredBoxed\(\)V(\n {3}.*)*((\n {3}.*box-impl.*)(\n {3}.*)*){1} +// 0 Init.*((\n {1}.*)*(\n {1}.*box-impl.*)){1}