[Commonizer] Improve iteration performance in transformer and mergeCirTree

An allocation/iterator free `forEach` is used for lists that
are not intended to be modified at the same time.
This commit is contained in:
sebastian.sellmair
2021-08-17 17:52:31 +02:00
committed by Space
parent e2816ffabb
commit 565ea2c4f5
3 changed files with 40 additions and 16 deletions

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.commonizer.transformer
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.ParentNode
import org.jetbrains.kotlin.commonizer.utils.fastForEach
import org.jetbrains.kotlin.storage.StorageManager
internal class TypeSubstitutionCirNodeTransformer(
@@ -26,16 +27,16 @@ internal class TypeSubstitutionCirNodeTransformer(
}
private operator fun invoke(pkg: CirPackageNode, index: Int) {
pkg.functions.values.toList().forEach { function -> this(pkg, function, index, CirMemberContext.empty) }
pkg.properties.values.toList().forEach { property -> this(pkg, property, index, CirMemberContext.empty) }
pkg.classes.values.toList().forEach { clazz -> this(clazz, index, CirMemberContext.empty) }
pkg.functions.values.toTypedArray().fastForEach { function -> this(pkg, function, index, CirMemberContext.empty) }
pkg.properties.values.toTypedArray().fastForEach { property -> this(pkg, property, index, CirMemberContext.empty) }
pkg.classes.values.toTypedArray().fastForEach { clazz -> this(clazz, index, CirMemberContext.empty) }
}
private operator fun invoke(clazz: CirClassNode, index: Int, context: CirMemberContext) {
val contextWithClass = context.withContextOf(clazz.targetDeclarations[index] ?: return)
clazz.functions.values.toList().forEach { function -> this(clazz, function, index, contextWithClass) }
clazz.properties.values.toList().forEach { property -> this(clazz, property, index, contextWithClass) }
clazz.classes.values.toList().forEach { innerClass -> this(innerClass, index, contextWithClass) }
clazz.functions.values.toTypedArray().fastForEach { function -> this(clazz, function, index, contextWithClass) }
clazz.properties.values.toTypedArray().fastForEach { property -> this(clazz, property, index, contextWithClass) }
clazz.classes.values.toTypedArray().fastForEach { innerClass -> this(innerClass, index, contextWithClass) }
}
private operator fun invoke(parent: CirNodeWithMembers<*, *>, function: CirFunctionNode, index: Int, context: CirMemberContext) {

View File

@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.Companion.ParentNode
import org.jetbrains.kotlin.commonizer.mergedtree.CirNodeRelationship.ParentNode
import org.jetbrains.kotlin.commonizer.utils.fastForEach
import org.jetbrains.kotlin.storage.StorageManager
internal data class TargetBuildingContext(
@@ -41,7 +42,7 @@ internal fun mergeCirTree(
}
internal fun CirRootNode.buildModules(context: TargetBuildingContext, modules: List<CirTreeModule>) {
modules.forEach { module -> buildModule(context, module) }
modules.fastForEach { module -> buildModule(context, module) }
}
internal fun CirRootNode.buildModule(context: TargetBuildingContext, treeModule: CirTreeModule) {
@@ -49,7 +50,7 @@ internal fun CirRootNode.buildModule(context: TargetBuildingContext, treeModule:
buildModuleNode(context.storageManager, context.targets)
}
moduleNode.targetDeclarations[context.targetIndex] = treeModule.module
treeModule.packages.forEach { pkg -> moduleNode.buildPackage(context, pkg) }
treeModule.packages.fastForEach { pkg -> moduleNode.buildPackage(context, pkg) }
}
internal fun CirModuleNode.buildPackage(context: TargetBuildingContext, treePackage: CirTreePackage) {
@@ -57,10 +58,10 @@ internal fun CirModuleNode.buildPackage(context: TargetBuildingContext, treePack
buildPackageNode(context.storageManager, context.targets)
}
packageNode.targetDeclarations[context.targetIndex] = treePackage.pkg
treePackage.functions.forEach { function -> packageNode.buildFunction(context, function) }
treePackage.properties.forEach { property -> packageNode.buildProperty(context, property) }
treePackage.typeAliases.forEach { typeAlias -> packageNode.buildTypeAlias(context, typeAlias) }
treePackage.classes.forEach { clazz -> packageNode.buildClass(context, clazz) }
treePackage.functions.fastForEach { function -> packageNode.buildFunction(context, function) }
treePackage.properties.fastForEach { property -> packageNode.buildProperty(context, property) }
treePackage.typeAliases.fastForEach { typeAlias -> packageNode.buildTypeAlias(context, typeAlias) }
treePackage.classes.fastForEach { clazz -> packageNode.buildClass(context, clazz) }
}
internal fun CirNodeWithMembers<*, *>.buildClass(
@@ -71,10 +72,10 @@ internal fun CirNodeWithMembers<*, *>.buildClass(
}
classNode.targetDeclarations[context.targetIndex] = treeClass.clazz
val contextWithClass = context.withMemberContextOf(treeClass.clazz)
treeClass.functions.forEach { function -> classNode.buildFunction(contextWithClass, function, classNode) }
treeClass.properties.forEach { property -> classNode.buildProperty(contextWithClass, property, classNode) }
treeClass.constructors.forEach { constructor -> classNode.buildConstructor(contextWithClass, constructor, classNode) }
treeClass.classes.forEach { clazz -> classNode.buildClass(contextWithClass, clazz, classNode) }
treeClass.functions.fastForEach { function -> classNode.buildFunction(contextWithClass, function, classNode) }
treeClass.properties.fastForEach { property -> classNode.buildProperty(contextWithClass, property, classNode) }
treeClass.constructors.fastForEach { constructor -> classNode.buildConstructor(contextWithClass, constructor, classNode) }
treeClass.classes.fastForEach { clazz -> classNode.buildClass(contextWithClass, clazz, classNode) }
}
internal fun CirNodeWithMembers<*, *>.buildFunction(

View File

@@ -100,3 +100,25 @@ inline fun Int.appendHashCode(value: Any?): Int = 31 * this + hashCode(value)
@Suppress("NOTHING_TO_INLINE")
inline fun Int.appendHashCode(array: Array<*>?): Int = 31 * this + hashCode(array)
/**
* Allocation Free 'forEach' implementation that won't use any underlying iterator.
* Note: This implementation therefore is unsafe when mutating the collection at the same time!!!
*/
inline fun <T> List<T>.fastForEach(action: (T) -> Unit) {
val size = this.size
for (index in 0 until size) {
action(this[index])
}
}
/**
* Allocation Free 'forEach' implementation that won't use any underlying iterator.
* Note: This implementation therefore is unsafe when mutating the collection at the same time!!!
*/
inline fun <T> Array<T>.fastForEach(action: (T) -> Unit) {
val size = this.size
for (index in 0 until size) {
action(this[index])
}
}