From bd7bce9f9716d05fb0c5224bbaeecdf14cd292fa Mon Sep 17 00:00:00 2001 From: Vladislav Grechko Date: Mon, 3 Apr 2023 15:26:47 +0200 Subject: [PATCH] [JVM IR] Get rid of `MfvcNodeWithSubnodesImpl` class `MfvcNodeWithSubnodesImpl` has two problems: - Naming: its name makes one think that the class is inherited from `MfvcNode` and implements `MfvcNodeWithSubnodes`.However, both statements are false. - Semantics: the class only makes unnecessary indirection between its properties and code of `MfvcNodeWithSubnodes` class --- .../jetbrains/kotlin/backend/jvm/MfvcNode.kt | 108 ++++++++---------- .../kotlin/backend/jvm/MfvcNodeFactory.kt | 14 +-- 2 files changed, 56 insertions(+), 66 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt index eb288e49eff..c5abecdc808 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNode.kt @@ -139,11 +139,43 @@ fun MfvcNode.getSubnodeAndIndices(name: Name): Pair? return node to indices } -sealed interface MfvcNodeWithSubnodes : MfvcNode { +sealed class MfvcNodeWithSubnodes(val subnodes: List) : MfvcNode { abstract override val type: IrSimpleType - val boxMethod: IrSimpleFunction - val leavesUnboxMethods: List? - val subnodesImpl: MfvcNodeWithSubnodesImpl + abstract val boxMethod: IrSimpleFunction + abstract val leavesUnboxMethods: List? + abstract val allUnboxMethods: List + + init { + require(subnodes.isNotEmpty()) + require(subnodes.map { it.nameParts.dropLast(1) }.allEqual()) + } + + private val mapping = subnodes.associateBy { it.name }.also { mapping -> + require(mapping.size == subnodes.size) { + subnodes + .groupBy { it.name } + .filterValues { it.size > 1 } + .entries.joinToString(prefix = "Repeating node names found: ") { (name, nodes) -> "${nodes.size} nodes with name '$name'" } + } + } + + operator fun get(name: Name): NameableMfvcNode? = mapping[name] + + val leaves: List = subnodes.leaves + + val fields: List? = subnodes.fields + + val allInnerUnboxMethods: List = subnodes.flatMap { subnode -> + when (subnode) { + is MfvcNodeWithSubnodes -> subnode.allUnboxMethods + is LeafMfvcNode -> listOf(subnode.unboxMethod) + } + } + + val indices: IntRange = leaves.indices + + val subnodeIndices = subnodes.subnodeIndices + } fun MfvcNodeWithSubnodes.makeBoxedExpression( @@ -173,24 +205,10 @@ operator fun MfvcNodeWithSubnodes.get(names: List): MfvcNode? { private fun List.allEqual() = all { it == first() } -class MfvcNodeWithSubnodesImpl(val subnodes: List, unboxMethod: IrSimpleFunction?) { - init { - require(subnodes.isNotEmpty()) - require(subnodes.map { it.nameParts.dropLast(1) }.allEqual()) - } +val List.leaves get() = this.mapLeaves { it } - private val mapping = subnodes.associateBy { it.name }.also { mapping -> - require(mapping.size == subnodes.size) { - subnodes - .groupBy { it.name } - .filterValues { it.size > 1 } - .entries.joinToString(prefix = "Repeating node names found: ") { (name, nodes) -> "${nodes.size} nodes with name '$name'" } - } - } - - operator fun get(name: Name): NameableMfvcNode? = mapping[name] - val leaves: List = mapLeaves { it } - val fields: List? = mapLeaves { it.field }.run { +val List.fields + get() = mapLeaves { it.field }.run { @Suppress("UNCHECKED_CAST") when { all { it == null } -> null @@ -199,20 +217,10 @@ class MfvcNodeWithSubnodesImpl(val subnodes: List, unboxMethod } } - val allInnerUnboxMethods: List = subnodes.flatMap { subnode -> - when (subnode) { - is MfvcNodeWithSubnodes -> subnode.allUnboxMethods - is LeafMfvcNode -> listOf(subnode.unboxMethod) - } - } - - val allUnboxMethods = allInnerUnboxMethods + listOfNotNull(unboxMethod) - - val indices: IntRange = leaves.indices - - val subnodeIndices: Map = buildMap { +val List.subnodeIndices: Map + get() = buildMap { var offset = 0 - for (node in subnodes) { + for (node in this@subnodeIndices) { when (node) { is IntermediateMfvcNode -> { val nodeSize = node.leavesCount @@ -228,26 +236,6 @@ class MfvcNodeWithSubnodesImpl(val subnodes: List, unboxMethod } } } -} - -val MfvcNodeWithSubnodes.subnodes: List - get() = subnodesImpl.subnodes - -operator fun MfvcNodeWithSubnodes.get(name: Name): NameableMfvcNode? = subnodesImpl[name] -val MfvcNodeWithSubnodes.leaves: List - get() = subnodesImpl.leaves -val MfvcNodeWithSubnodes.fields: List? - get() = subnodesImpl.fields -val RootMfvcNode.fields: List? - get() = subnodesImpl.fields -val MfvcNodeWithSubnodes.indices: IntRange - get() = subnodesImpl.indices -val MfvcNodeWithSubnodes.subnodeIndices: Map - get() = subnodesImpl.subnodeIndices -val MfvcNodeWithSubnodes.allUnboxMethods: List - get() = subnodesImpl.allUnboxMethods -val MfvcNodeWithSubnodes.allInnerUnboxMethods: List - get() = subnodesImpl.allInnerUnboxMethods inline fun MfvcNode.mapLeaves(crossinline f: (LeafMfvcNode) -> R): List = flatMapLeaves { listOf(f(it)) } @@ -256,7 +244,7 @@ fun MfvcNode.flatMapLeaves(f: (LeafMfvcNode) -> List): List = when (th is LeafMfvcNode -> f(this) } -inline fun MfvcNodeWithSubnodesImpl.mapLeaves(crossinline f: (LeafMfvcNode) -> R): List = subnodes.flatMap { it.mapLeaves(f) } +inline fun List.mapLeaves(crossinline f: (LeafMfvcNode) -> R): List = flatMap { it.mapLeaves(f) } private fun requireSameClasses(vararg classes: IrClass?) { @@ -330,11 +318,10 @@ class IntermediateMfvcNode( unboxMethod: IrSimpleFunction, defaultMethodsImplementationSourceNode: UnboxFunctionImplementation, val rootNode: RootMfvcNode, // root node corresponding type of the node -) : NameableMfvcNode, MfvcNodeWithSubnodes { +) : NameableMfvcNode, MfvcNodeWithSubnodes(subnodes) { override val hasPureUnboxMethod: Boolean = defaultMethodsImplementationSourceNode.hasPureUnboxMethod && subnodes.all { it.hasPureUnboxMethod } override val namedNodeImpl: NameableMfvcNodeImpl = NameableMfvcNodeImpl(methodFullNameMode, nameParts, unboxMethod) - override val subnodesImpl: MfvcNodeWithSubnodesImpl = MfvcNodeWithSubnodesImpl(subnodes, unboxMethod) override val leavesCount get() = leaves.size @@ -350,6 +337,8 @@ class IntermediateMfvcNode( validateGettingAccessorParameters(unboxMethod) } + override val allUnboxMethods = allInnerUnboxMethods + listOf(unboxMethod) + override val boxMethod: IrSimpleFunction get() = rootNode.boxMethod @@ -394,8 +383,7 @@ class RootMfvcNode internal constructor( override val boxMethod: IrSimpleFunction, val specializedEqualsMethod: IrSimpleFunction, val createdNewSpecializedEqualsMethod: Boolean, -) : MfvcNodeWithSubnodes { - override val subnodesImpl: MfvcNodeWithSubnodesImpl = MfvcNodeWithSubnodesImpl(subnodes, null) +) : MfvcNodeWithSubnodes(subnodes) { override val type: IrSimpleType = mfvc.defaultType override val leavesCount: Int @@ -403,6 +391,8 @@ class RootMfvcNode internal constructor( override val leavesUnboxMethods: List = collectLeavesUnboxMethods() + override val allUnboxMethods: List get() = allInnerUnboxMethods + init { require(type.needsMfvcFlattening()) { "MFVC type expected but got: ${type.render()}" } for (constructor in listOf(oldPrimaryConstructor, newPrimaryConstructor)) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt index 55ffebcd72c..6a8657530ab 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt @@ -341,12 +341,11 @@ fun getRootNode(context: JvmBackendContext, mfvc: IrClass): RootMfvcNode { val subnodes = makeRootMfvcNodeSubnodes(representation, properties, context, mfvc) - val mfvcNodeWithSubnodesImpl = MfvcNodeWithSubnodesImpl(subnodes, null) - val leaves = mfvcNodeWithSubnodesImpl.leaves - val fields = mfvcNodeWithSubnodesImpl.fields + val leaves = subnodes.leaves + val fields = subnodes.fields val newPrimaryConstructor = makeMfvcPrimaryConstructor(context, oldPrimaryConstructor, mfvc, leaves, fields) - val primaryConstructorImpl = makePrimaryConstructorImpl(context, oldPrimaryConstructor, mfvc, leaves, mfvcNodeWithSubnodesImpl) + val primaryConstructorImpl = makePrimaryConstructorImpl(context, oldPrimaryConstructor, mfvc, leaves, subnodes) val boxMethod = makeBoxMethod(context, mfvc, leaves, newPrimaryConstructor) val customEqualsAny = mfvc.functions.singleOrNull { @@ -438,7 +437,7 @@ private fun makePrimaryConstructorImpl( oldPrimaryConstructor: IrConstructor, mfvc: IrClass, leaves: List, - subnodesImpl: MfvcNodeWithSubnodesImpl, + subnodes: List, ) = context.irFactory.buildFun { name = InlineClassAbi.mangledNameFor(oldPrimaryConstructor, false, false) visibility = oldPrimaryConstructor.visibility @@ -452,9 +451,10 @@ private fun makePrimaryConstructorImpl( addValueParameter(leaf.fullFieldName, leaf.type.substitute(mfvc.typeParameters, typeParameters.map { it.defaultType })) } for ((index, oldParameter) in oldPrimaryConstructor.valueParameters.withIndex()) { - val node = subnodesImpl.subnodes[index] + val node = subnodes[index] + val subnodesIndices = subnodes.subnodeIndices if (node is LeafMfvcNode) { - val newIndex = subnodesImpl.subnodeIndices[node]!!.first + val newIndex = subnodesIndices[node]!!.first valueParameters[newIndex].annotations = oldParameter.annotations } }