From 4c640e3f8117f1c72643c42e50cf89398000ab0f Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Wed, 27 Jan 2021 17:16:59 +0300 Subject: [PATCH] [Commonizer] Log stats during building metadata --- .../commonizer/builder/classDescriptors.kt | 6 - .../descriptors/commonizer/builder/context.kt | 6 +- .../commonizer/builder/functionDescriptors.kt | 3 - .../commonizer/builder/moduleDescriptors.kt | 3 - .../commonizer/builder/propertyDescriptors.kt | 3 - .../builder/typeAliasDescriptors.kt | 3 - .../kotlin/descriptors/commonizer/facade.kt | 2 +- .../konan/NativeDistributionCommonizer.kt | 48 +- .../mergedtree/approximationKeys.kt | 12 +- .../commonizer/metadata/builders.kt | 31 +- .../commonizer/metadata/buildingVisitor.kt | 452 ++++++++++++++++++ .../commonizer/metadata/context.kt | 60 --- .../commonizer/metadata/visitor.kt | 134 ------ .../stats/AggregatedStatsCollector.kt | 79 ++- .../commonizer/stats/DeclarationType.kt | 30 +- .../commonizer/stats/RawStatsCollector.kt | 188 ++++---- .../commonizer/stats/StatsCollector.kt | 16 +- .../descriptors/commonizer/utils/fqName.kt | 3 + .../descriptors/commonizer/utils/type.kt | 9 +- 19 files changed, 653 insertions(+), 435 deletions(-) create mode 100644 native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/buildingVisitor.kt delete mode 100644 native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/context.kt delete mode 100644 native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/visitor.kt diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/classDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/classDescriptors.kt index b19d2b33103..28e4fce117b 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/classDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/classDescriptors.kt @@ -30,9 +30,6 @@ internal fun CirClassNode.buildDescriptors( } commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, classId, isExpect = true) - - // log stats - components.statsCollector?.logStats(output) } internal fun CirClass.buildDescriptor( @@ -86,9 +83,6 @@ internal fun CirClassConstructorNode.buildDescriptors( } commonConstructor?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = true) - - // log stats - components.statsCollector?.logStats(output) } private fun CirClassConstructor.buildDescriptor( diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt index adca0e6ec3a..1125348f81e 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/context.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.dimension import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode -import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector import org.jetbrains.kotlin.descriptors.commonizer.utils.* import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroupMap import org.jetbrains.kotlin.descriptors.commonizer.utils.createKotlinNativeForwardDeclarationsModule @@ -121,8 +120,7 @@ class DeclarationsBuilderCache(private val dimension: Int) { class GlobalDeclarationsBuilderComponents( val storageManager: StorageManager, val targetComponents: List, - val cache: DeclarationsBuilderCache, - val statsCollector: StatsCollector? + val cache: DeclarationsBuilderCache ) { init { check(targetComponents.size > 1) @@ -274,7 +272,7 @@ fun CirRootNode.createGlobalBuilderComponents( ) } - return GlobalDeclarationsBuilderComponents(storageManager, targetContexts, cache, parameters.statsCollector) + return GlobalDeclarationsBuilderComponents(storageManager, targetContexts, cache) } interface TypeParameterResolver { diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/functionDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/functionDescriptors.kt index cef90307746..dd3cb8614c8 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/functionDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/functionDescriptors.kt @@ -28,9 +28,6 @@ internal fun CirFunctionNode.buildDescriptors( } commonFunction?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual) - - // log stats - components.statsCollector?.logStats(output) } private fun CirFunction.buildDescriptor( diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/moduleDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/moduleDescriptors.kt index e8e2db550ac..d7a036745f0 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/moduleDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/moduleDescriptors.kt @@ -20,9 +20,6 @@ internal fun CirModuleNode.buildDescriptors( } commonDeclaration()?.buildDescriptor(components, output, indexOfCommon) - - // log stats - components.statsCollector?.logStats(output) } private fun CirModule.buildDescriptor( diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt index 27b1e01a971..f03ed8acf24 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt @@ -37,9 +37,6 @@ internal fun CirPropertyNode.buildDescriptors( } commonProperty?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual) - - // log stats - components.statsCollector?.logStats(output) } private fun CirProperty.buildDescriptor( diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt index 23c8bc29060..8b6b4f02134 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt @@ -41,9 +41,6 @@ internal fun CirTypeAliasNode.buildDescriptors( } else if (commonClassifier != null && commonClassifier is CirClass) { commonClassifier.buildDescriptor(components, output, indexOfCommon, containingDeclarations, classId, isExpect = true) } - - // log stats - components.statsCollector?.logStats(output) } private fun CirTypeAlias.buildDescriptor( diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/facade.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/facade.kt index 50cbf13dc9a..3909663d46a 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/facade.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/facade.kt @@ -43,7 +43,7 @@ fun runCommonization(parameters: CommonizerParameters): CommonizerResult { // optional part for generating descriptors: end for (targetIndex in 0 until mergedTree.dimension) { - val (target, metadataModules) = MetadataBuilder.build(mergedTree, targetIndex) + val (target, metadataModules) = MetadataBuilder.build(mergedTree, targetIndex, parameters.statsCollector) // optional part for generating descriptors: begin val moduleDescriptors: Map? = components?.targetComponents?.get(targetIndex)?.let { component -> diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionCommonizer.kt index 581581352dd..3f6e8291fbc 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/konan/NativeDistributionCommonizer.kt @@ -10,9 +10,7 @@ import org.jetbrains.kotlin.backend.common.serialization.metadata.metadataVersio import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns import org.jetbrains.kotlin.descriptors.commonizer.* import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeDistributionCommonizer.StatsType.* -import org.jetbrains.kotlin.descriptors.commonizer.stats.AggregatedStatsCollector -import org.jetbrains.kotlin.descriptors.commonizer.stats.FileStatsOutput -import org.jetbrains.kotlin.descriptors.commonizer.stats.RawStatsCollector +import org.jetbrains.kotlin.descriptors.commonizer.stats.* import org.jetbrains.kotlin.descriptors.commonizer.utils.ResettableClockMark import org.jetbrains.kotlin.konan.library.* import org.jetbrains.kotlin.konan.target.KonanTarget @@ -132,36 +130,38 @@ class NativeDistributionCommonizer( private fun commonize(allLibraries: AllNativeLibraries): CommonizerResult { val statsCollector = when (statsType) { - RAW -> RawStatsCollector(targets, FileStatsOutput(destination, "raw")) - AGGREGATED -> AggregatedStatsCollector(targets, FileStatsOutput(destination, "aggregated")) + RAW -> RawStatsCollector(targets) + AGGREGATED -> AggregatedStatsCollector(targets) NONE -> null } - statsCollector.use { - val parameters = CommonizerParameters(statsCollector, ::logProgress).apply { - val storageManager = LockBasedStorageManager("Commonized modules") - val stdlibProvider = NativeDistributionStdlibProvider(storageManager, allLibraries.stdlib) - dependeeModulesProvider = stdlibProvider + val parameters = CommonizerParameters(statsCollector, ::logProgress).apply { + val storageManager = LockBasedStorageManager("Commonized modules") - allLibraries.librariesByTargets.forEach { (target, librariesToCommonize) -> - if (librariesToCommonize.libraries.isEmpty()) return@forEach + val stdlibProvider = NativeDistributionStdlibProvider(storageManager, allLibraries.stdlib) + dependeeModulesProvider = stdlibProvider - val modulesProvider = NativeDistributionModulesProvider(storageManager, librariesToCommonize) + allLibraries.librariesByTargets.forEach { (target, librariesToCommonize) -> + if (librariesToCommonize.libraries.isEmpty()) return@forEach - addTarget( - TargetProvider( - target = target, - builtInsClass = KonanBuiltIns::class.java, - builtInsProvider = stdlibProvider, - modulesProvider = modulesProvider, - dependeeModulesProvider = null // stdlib is already set as common dependency - ) + val modulesProvider = NativeDistributionModulesProvider(storageManager, librariesToCommonize) + + addTarget( + TargetProvider( + target = target, + builtInsClass = KonanBuiltIns::class.java, + builtInsProvider = stdlibProvider, + modulesProvider = modulesProvider, + dependeeModulesProvider = null // stdlib is already set as common dependency ) - } + ) } - - return runCommonization(parameters) } + + val result = runCommonization(parameters) + statsCollector?.writeTo(FileStatsOutput(destination, statsType.name.toLowerCase())) + + return result } private fun saveModules(originalLibraries: AllNativeLibraries, result: CommonizerResult) { diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/approximationKeys.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/approximationKeys.kt index c10d2af88ba..8679475a246 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/approximationKeys.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/approximationKeys.kt @@ -15,8 +15,8 @@ import org.jetbrains.kotlin.name.Name /** Used for approximation of [PropertyDescriptor]s before running concrete [Commonizer]s */ data class PropertyApproximationKey( - private val name: Name, - private val extensionReceiverParameterType: CirTypeSignature? + val name: Name, + val extensionReceiverParameterType: CirTypeSignature? ) { constructor(property: PropertyDescriptor) : this( property.name.intern(), @@ -26,10 +26,10 @@ data class PropertyApproximationKey( /** Used for approximation of [SimpleFunctionDescriptor]s before running concrete [Commonizer]s */ data class FunctionApproximationKey( - private val name: Name, - private val valueParametersTypes: Array, + val name: Name, + val valueParametersTypes: Array, private val additionalValueParametersNamesHash: Int, - private val extensionReceiverParameterType: CirTypeSignature? + val extensionReceiverParameterType: CirTypeSignature? ) { constructor(function: SimpleFunctionDescriptor) : this( function.name.intern(), @@ -56,7 +56,7 @@ data class FunctionApproximationKey( /** Used for approximation of [ConstructorDescriptor]s before running concrete [Commonizer]s */ data class ConstructorApproximationKey( - private val valueParametersTypes: Array, + val valueParametersTypes: Array, private val additionalValueParametersNamesHash: Int ) { constructor(constructor: ConstructorDescriptor) : this( diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/builders.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/builders.kt index de3a9ebf672..172d7f40c90 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/builders.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/builders.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirValueParameterImp import org.jetbrains.kotlin.descriptors.commonizer.core.computeExpandedType import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.* import org.jetbrains.kotlin.descriptors.commonizer.metadata.TypeAliasExpansion.* +import org.jetbrains.kotlin.descriptors.commonizer.utils.DEFAULT_SETTER_VALUE_NAME import org.jetbrains.kotlin.descriptors.commonizer.utils.strip import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -72,7 +73,7 @@ internal fun addEmptyFragments(fragments: MutableCollection) { } internal fun CirClass.buildClass( - context: VisitingContext, + context: MetadataBuildingVisitorContext, className: ClassName, directNestedClasses: Collection, nestedConstructors: Collection, @@ -122,7 +123,7 @@ internal fun linkSealedClassesWithSubclasses(packageFqName: FqName, classConsume } internal fun CirClassConstructor.buildClassConstructor( - context: VisitingContext + context: MetadataBuildingVisitorContext ): KmConstructor = KmConstructor( flags = classConstructorFlags() ).also { constructor -> @@ -131,7 +132,7 @@ internal fun CirClassConstructor.buildClassConstructor( } internal fun CirTypeAlias.buildTypeAlias( - context: VisitingContext + context: MetadataBuildingVisitorContext ): KmTypeAlias = KmTypeAlias( flags = typeAliasFlags(), name = name.asString() @@ -143,7 +144,7 @@ internal fun CirTypeAlias.buildTypeAlias( } internal fun CirProperty.buildProperty( - context: VisitingContext, + context: MetadataBuildingVisitorContext, ): KmProperty = KmProperty( flags = propertyFlags(isExpect = context.isCommon && !isLiftedUp), name = name.asString(), @@ -162,7 +163,7 @@ internal fun CirProperty.buildProperty( setter?.takeIf { !it.isDefault }?.let { setter -> property.setterParameter = CirValueParameterImpl( annotations = setter.parameterAnnotations, - name = SETTER_VALUE_NAME, + name = DEFAULT_SETTER_VALUE_NAME, returnType = returnType, varargElementType = null, declaresDefaultValue = false, @@ -174,7 +175,7 @@ internal fun CirProperty.buildProperty( } internal fun CirFunction.buildFunction( - context: VisitingContext, + context: MetadataBuildingVisitorContext, ): KmFunction = KmFunction( flags = functionFlags(isExpect = context.isCommon), name = name.asString() @@ -231,7 +232,7 @@ private fun ConstantValue<*>.buildAnnotationArgument(): KmAnnotationArgument<*> } private fun CirValueParameter.buildValueParameter( - context: VisitingContext + context: MetadataBuildingVisitorContext ): KmValueParameter = KmValueParameter( flags = valueParameterFlags(), name = name.asString() @@ -244,7 +245,7 @@ private fun CirValueParameter.buildValueParameter( } private fun List.buildTypeParameters( - context: VisitingContext, + context: MetadataBuildingVisitorContext, output: MutableList ) { mapIndexedTo(output) { index, cirTypeParameter -> @@ -261,7 +262,7 @@ private fun List.buildTypeParameters( } private fun CirType.buildType( - context: VisitingContext, + context: MetadataBuildingVisitorContext, expansion: TypeAliasExpansion = FOR_TOP_LEVEL_TYPE ): KmType = when (this) { is CirClassType -> buildType(context, expansion) @@ -283,7 +284,7 @@ private fun CirTypeParameterType.buildType(): KmType = } private fun CirClassType.buildType( - context: VisitingContext, + context: MetadataBuildingVisitorContext, expansion: TypeAliasExpansion ): KmType = KmType(typeFlags()).also { type -> type.classifier = KmClassifier.Class(classifierId.asString()) @@ -292,7 +293,7 @@ private fun CirClassType.buildType( } private fun CirTypeAliasType.buildType( - context: VisitingContext, + context: MetadataBuildingVisitorContext, expansion: TypeAliasExpansion ): KmType = when (expansion) { ONLY_ABBREVIATIONS -> buildAbbreviationType(context, expansion) @@ -306,7 +307,7 @@ private fun CirTypeAliasType.buildType( } private fun CirTypeAliasType.buildAbbreviationType( - context: VisitingContext, + context: MetadataBuildingVisitorContext, expansion: TypeAliasExpansion ): KmType { val abbreviationType = KmType(typeFlags()) @@ -317,7 +318,7 @@ private fun CirTypeAliasType.buildAbbreviationType( @Suppress("UnnecessaryVariable") private fun CirTypeAliasType.buildExpandedType( - context: VisitingContext, + context: MetadataBuildingVisitorContext, expansion: TypeAliasExpansion ): KmType { val cirExpandedType = computeExpandedType(underlyingType) @@ -326,7 +327,7 @@ private fun CirTypeAliasType.buildExpandedType( } private fun CirTypeProjection.buildArgument( - context: VisitingContext, + context: MetadataBuildingVisitorContext, expansion: TypeAliasExpansion ): KmTypeProjection { val effectiveExpansion = if (expansion == FOR_TOP_LEVEL_TYPE) FOR_NESTED_TYPE else expansion @@ -353,5 +354,3 @@ private enum class TypeAliasExpansion { FOR_TOP_LEVEL_TYPE, FOR_NESTED_TYPE } - -private val SETTER_VALUE_NAME = Name.identifier("value") diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/buildingVisitor.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/buildingVisitor.kt new file mode 100644 index 00000000000..9df8b1e14b1 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/buildingVisitor.kt @@ -0,0 +1,452 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.descriptors.commonizer.metadata + +import kotlinx.metadata.* +import kotlinx.metadata.klib.KlibModuleMetadata +import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget +import org.jetbrains.kotlin.descriptors.commonizer.cir.* +import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.* +import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon +import org.jetbrains.kotlin.descriptors.commonizer.stats.DeclarationType +import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector +import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector.StatsKey +import org.jetbrains.kotlin.descriptors.commonizer.utils.DEFAULT_CONSTRUCTOR_NAME +import org.jetbrains.kotlin.descriptors.commonizer.utils.strip +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addToStdlib.cast +import org.jetbrains.kotlin.descriptors.commonizer.utils.firstNonNull +import org.jetbrains.kotlin.descriptors.commonizer.metadata.MetadataBuildingVisitorContext.Path + +internal object MetadataBuilder { + fun build( + node: CirRootNode, + targetIndex: Int, + statsCollector: StatsCollector? + ): Pair> { + return node.accept( + MetadataBuildingVisitor(statsCollector), + MetadataBuildingVisitorContext.rootContext(node, targetIndex) + ).cast() + } +} + +@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") +private class MetadataBuildingVisitor(private val statsCollector: StatsCollector?) : CirNodeVisitor { + private val classConsumer = ClassConsumer() + + override fun visitRootNode( + node: CirRootNode, + rootContext: MetadataBuildingVisitorContext + ): Pair> { + val modules: List = node.modules.mapNotNull { (moduleName, moduleNode) -> + val moduleContext = rootContext.moduleContext(moduleName) + val module: KlibModuleMetadata? = moduleNode.accept(this, moduleContext)?.cast() + statsCollector?.logModule(moduleContext) + module + } + + return rootContext.target to modules + } + + override fun visitModuleNode( + node: CirModuleNode, + moduleContext: MetadataBuildingVisitorContext + ): KlibModuleMetadata? { + val cirModule = moduleContext.get(node) ?: return null + + val fragments: MutableCollection = mutableListOf() + node.packages.mapNotNullTo(fragments) { (packageFqName, packageNode) -> + val packageContext = moduleContext.packageContext(packageFqName) + packageNode.accept(this, packageContext)?.cast() + } + + addEmptyFragments(fragments) + + return cirModule.buildModule(fragments) + } + + override fun visitPackageNode( + node: CirPackageNode, + packageContext: MetadataBuildingVisitorContext + ): KmModuleFragment? { + val cirPackage = packageContext.get(node) ?: return null + + try { + node.classes.forEach { (className, classNode) -> + val classContext = packageContext.classifierContext(className) + val clazz: KmClass = classNode.accept(this, classContext)?.cast() ?: return@forEach + classConsumer.consume(clazz) + statsCollector?.logClass(clazz, classContext) + } + + val topLevelTypeAliases = mutableListOf() + node.typeAliases.forEach { (typeAliasName, typeAliasNode) -> + val typeAliasContext = packageContext.classifierContext(typeAliasName) + when (val classifier = typeAliasNode.accept(this, typeAliasContext)) { + null -> Unit + is KmClass -> { + classConsumer.consume(classifier) + statsCollector?.logClass(classifier, typeAliasContext) + } + is KmTypeAlias -> { + topLevelTypeAliases += classifier + statsCollector?.logTypeAlias(typeAliasContext) + } + else -> error("Unexpected classifier: ${classifier::class.java}, $classifier") + } + } + + linkSealedClassesWithSubclasses(cirPackage.fqName, classConsumer) + + val topLevelFunctions: Collection = node.functions.mapNotNull { (functionKey, functionNode) -> + val functionContext = packageContext.callableMemberContext(functionKey.name) + val function: KmFunction = functionNode.accept(this, functionContext)?.cast() ?: return@mapNotNull null + statsCollector?.logFunction(function, functionContext, functionKey) + function + } + + val topLevelProperties: Collection = node.properties.mapNotNull { (propertyKey, propertyNode) -> + val propertyContext = packageContext.callableMemberContext(propertyKey.name) + val property: KmProperty = propertyNode.accept(this, propertyContext)?.cast() ?: return@mapNotNull null + statsCollector?.logProperty(propertyContext, propertyKey, propertyNode) + property + } + + return cirPackage.buildModuleFragment(classConsumer.allClasses, topLevelTypeAliases, topLevelFunctions, topLevelProperties) + } finally { + // Important: clean-up class consumer every time when leaving package + classConsumer.reset() + } + } + + override fun visitPropertyNode( + node: CirPropertyNode, + propertyContext: MetadataBuildingVisitorContext + ): KmProperty? { + return propertyContext.get(node)?.buildProperty(propertyContext) + } + + override fun visitFunctionNode( + node: CirFunctionNode, + functionContext: MetadataBuildingVisitorContext + ): KmFunction? { + return functionContext.get(node)?.buildFunction(functionContext) + } + + override fun visitClassNode( + node: CirClassNode, + classContext: MetadataBuildingVisitorContext + ): KmClass? { + val cirClass = classContext.get(node) ?: return null + val classTypeParametersCount = cirClass.typeParameters.size + val fullClassName = classContext.currentPath.toString() + + val directNestedClasses: Collection = node.classes.mapNotNull { (nestedClassName, nestedClassNode) -> + val isInnerClass = classContext.get(nestedClassNode)?.isInner ?: return@mapNotNull null + val outerClassTypeParametersCount = if (isInnerClass) classTypeParametersCount else 0 + val nestedClassContext = classContext.classifierContext(nestedClassName, isInnerClass, outerClassTypeParametersCount) + val nestedClass: KmClass = nestedClassNode.accept(this, nestedClassContext)?.cast() ?: return@mapNotNull null + classConsumer.consume(nestedClass) + statsCollector?.logClass(nestedClass, nestedClassContext) + nestedClass + } + + val nestedConstructors: Collection = node.constructors.mapNotNull { (constructorKey, constructorNode) -> + val constructorContext = classContext.callableMemberContext(DEFAULT_CONSTRUCTOR_NAME, classTypeParametersCount) + val constructor: KmConstructor = constructorNode.accept(this, constructorContext)?.cast() ?: return@mapNotNull null + statsCollector?.logClassConstructor(constructor, constructorContext, constructorKey) + constructor + } + + val nestedFunctions: Collection = node.functions.mapNotNull { (functionKey, functionNode) -> + val functionContext = classContext.callableMemberContext(functionKey.name, classTypeParametersCount) + val function: KmFunction = functionNode.accept(this, functionContext)?.cast() ?: return@mapNotNull null + statsCollector?.logFunction(function, functionContext, functionKey) + function + } + + val nestedProperties: Collection = node.properties.mapNotNull { (propertyKey, propertyNode) -> + val propertyContext = classContext.callableMemberContext(propertyKey.name, classTypeParametersCount) + val property: KmProperty = propertyNode.accept(this, propertyContext)?.cast() ?: return@mapNotNull null + statsCollector?.logProperty(propertyContext, propertyKey, propertyNode) + property + } + + return cirClass.buildClass(classContext, fullClassName, directNestedClasses, nestedConstructors, nestedFunctions, nestedProperties) + } + + override fun visitClassConstructorNode( + node: CirClassConstructorNode, + constructorContext: MetadataBuildingVisitorContext + ): KmConstructor? { + return constructorContext.get(node)?.buildClassConstructor(constructorContext) + } + + override fun visitTypeAliasNode( + node: CirTypeAliasNode, + typeAliasContext: MetadataBuildingVisitorContext + ): Any? { + val cirClassifier = typeAliasContext.get(node) ?: return null + + return when (cirClassifier) { + is CirTypeAlias -> cirClassifier.buildTypeAlias(typeAliasContext) + is CirClass -> { + val fullClassName = typeAliasContext.currentPath.toString() + cirClassifier.buildClass(typeAliasContext, fullClassName, emptyList(), emptyList(), emptyList(), emptyList()) + } + else -> error("Unexpected CIR classifier: ${cirClassifier::class.java}, $cirClassifier") + } + } + + companion object { + private fun StatsCollector.logModule( + moduleContext: MetadataBuildingVisitorContext + ) = logDeclaration(moduleContext.targetIndex) { + StatsKey(moduleContext.currentPath.toString(), DeclarationType.MODULE) + } + + private fun StatsCollector.logClass( + clazz: KmClass, + classContext: MetadataBuildingVisitorContext + ) = logDeclaration(classContext.targetIndex) { + val declarationType = when { + Flag.Class.IS_ENUM_CLASS(clazz.flags) -> DeclarationType.ENUM_CLASS + Flag.Class.IS_ENUM_ENTRY(clazz.flags) -> DeclarationType.ENUM_ENTRY + Flag.Class.IS_INTERFACE(clazz.flags) -> when { + (classContext.currentPath as Path.Classifier).classifierId.isNestedClass -> DeclarationType.NESTED_INTERFACE + else -> DeclarationType.TOP_LEVEL_INTERFACE + } + else -> when { + Flag.Class.IS_COMPANION_OBJECT(clazz.flags) -> DeclarationType.COMPANION_OBJECT + (classContext.currentPath as Path.Classifier).classifierId.isNestedClass -> DeclarationType.NESTED_CLASS + else -> DeclarationType.TOP_LEVEL_CLASS + } + } + + StatsKey(classContext.currentPath.toString(), declarationType) + } + + private fun StatsCollector.logTypeAlias( + typeAliasContext: MetadataBuildingVisitorContext + ) = logDeclaration(typeAliasContext.targetIndex) { + StatsKey(typeAliasContext.currentPath.toString(), DeclarationType.TYPE_ALIAS) + } + + private fun StatsCollector.logProperty( + propertyContext: MetadataBuildingVisitorContext, + propertyKey: PropertyApproximationKey, + propertyNode: CirPropertyNode + ) = logDeclaration(propertyContext.targetIndex) { + val declarationType = when { + (propertyContext.currentPath as Path.CallableMember).memberId.isNestedClass -> DeclarationType.NESTED_VAL + propertyNode.targetDeclarations.firstNonNull().isConst -> DeclarationType.TOP_LEVEL_CONST_VAL + else -> DeclarationType.TOP_LEVEL_VAL + } + + StatsKey( + id = propertyContext.currentPath.toString(), + extensionReceiver = propertyKey.extensionReceiverParameterType, + parameterNames = emptyList(), + parameterTypes = emptyList(), + declarationType = declarationType + ) + } + + private fun StatsCollector.logFunction( + function: KmFunction, + functionContext: MetadataBuildingVisitorContext, + functionKey: FunctionApproximationKey + ) = logDeclaration(functionContext.targetIndex) { + val declarationType = when { + (functionContext.currentPath as Path.CallableMember).memberId.isNestedClass -> DeclarationType.NESTED_FUN + else -> DeclarationType.TOP_LEVEL_FUN + } + + StatsKey( + id = functionContext.currentPath.toString(), + extensionReceiver = functionKey.extensionReceiverParameterType, + parameterNames = function.valueParameters.map { it.name }, + parameterTypes = functionKey.valueParametersTypes.asList(), + declarationType = declarationType + ) + } + + private fun StatsCollector.logClassConstructor( + constructor: KmConstructor, + constructorContext: MetadataBuildingVisitorContext, + constructorKey: ConstructorApproximationKey + ) = logDeclaration(constructorContext.targetIndex) { + StatsKey( + id = constructorContext.currentPath.toString(), + extensionReceiver = null, + parameterNames = constructor.valueParameters.map { it.name }, + parameterTypes = constructorKey.valueParametersTypes.asList(), + declarationType = DeclarationType.CLASS_CONSTRUCTOR + ) + } + } +} + +internal data class MetadataBuildingVisitorContext( + val targetIndex: Int, + val target: CommonizerTarget, + val isCommon: Boolean, + val typeParameterIndexOffset: Int, + val currentPath: Path +) { + sealed class Path { + object Empty : Path() { + override fun toString() = "" + } + + class Module(val moduleName: Name) : Path() { + override fun toString() = moduleName.strip() + } + + class Package(val packageFqName: FqName) : Path() { + fun nestedClassifier(classifierName: Name) = Classifier(ClassId(packageFqName, classifierName)) + fun nestedCallableMember(memberName: Name) = CallableMember(ClassId(packageFqName, memberName)) + + override fun toString() = packageFqName.asString() + } + + class Classifier(val classifierId: ClassId) : Path() { + fun nestedClassifier(classifierName: Name) = Classifier(classifierId.createNestedClassId(classifierName)) + fun nestedCallableMember(memberName: Name) = CallableMember(classifierId.createNestedClassId(memberName)) + + override fun toString() = classifierId.asString() + } + + class CallableMember(val memberId: ClassId) : Path() { + override fun toString() = memberId.asString() + } + } + + fun moduleContext(moduleName: Name): MetadataBuildingVisitorContext { + check(moduleName.isSpecial) + check(currentPath is Path.Empty) + + return MetadataBuildingVisitorContext( + targetIndex = targetIndex, + target = target, + isCommon = isCommon, + typeParameterIndexOffset = 0, + currentPath = Path.Module(moduleName) + ) + } + + fun packageContext(packageFqName: FqName): MetadataBuildingVisitorContext { + check(currentPath is Path.Module) + + return MetadataBuildingVisitorContext( + targetIndex = targetIndex, + target = target, + isCommon = isCommon, + typeParameterIndexOffset = 0, + currentPath = Path.Package(packageFqName) + ) + } + + fun classifierContext( + classifierName: Name, + isInner: Boolean = false, + outerClassTypeParametersCount: Int = 0 + ): MetadataBuildingVisitorContext { + val newPath = when (currentPath) { + is Path.Package -> { + check(!isInner) + check(outerClassTypeParametersCount == 0) + currentPath.nestedClassifier(classifierName) + } + is Path.Classifier -> { + check((isInner && outerClassTypeParametersCount >= 0) || (!isInner && outerClassTypeParametersCount == 0)) + currentPath.nestedClassifier(classifierName) + } + else -> error("Illegal state") + } + + return MetadataBuildingVisitorContext( + targetIndex = targetIndex, + target = target, + isCommon = isCommon, + typeParameterIndexOffset = if (isInner) typeParameterIndexOffset + outerClassTypeParametersCount else 0, + currentPath = newPath + ) + } + + fun callableMemberContext( + memberName: Name, + ownerClassTypeParametersCount: Int = 0 + ): MetadataBuildingVisitorContext { + val newPath = when (currentPath) { + is Path.Package -> { + check(ownerClassTypeParametersCount == 0) + currentPath.nestedCallableMember(memberName) + } + is Path.Classifier -> { + check(ownerClassTypeParametersCount >= 0) + currentPath.nestedCallableMember(memberName) + } + else -> error("Illegal state") + } + + return MetadataBuildingVisitorContext( + targetIndex = targetIndex, + target = target, + isCommon = isCommon, + typeParameterIndexOffset = typeParameterIndexOffset + ownerClassTypeParametersCount, + currentPath = newPath + ) + } + + inline fun get(node: CirNode<*, *>): T? { + return (if (isCommon) node.commonDeclaration() else node.targetDeclarations[targetIndex]) as T? + } + + inline fun get(node: CirNodeWithLiftingUp<*, *>): T? { + return when { + isCommon -> node.commonDeclaration() as T? + node.isLiftedUp -> null + else -> node.targetDeclarations[targetIndex] as T? + } + } + + companion object { + fun rootContext(rootNode: CirRootNode, targetIndex: Int): MetadataBuildingVisitorContext { + val isCommon = rootNode.indexOfCommon == targetIndex + val target = (if (isCommon) rootNode.commonDeclaration() else rootNode.targetDeclarations[targetIndex])!!.target + + return MetadataBuildingVisitorContext( + targetIndex = targetIndex, + target = target, + isCommon = isCommon, + typeParameterIndexOffset = 0, + currentPath = Path.Empty + ) + } + } +} + +internal class ClassConsumer { + private val _allClasses = mutableListOf() + private val _sealedClasses = mutableListOf() + + val allClasses: Collection get() = _allClasses + val sealedClasses: Collection get() = _sealedClasses + + fun consume(clazz: KmClass) { + _allClasses += clazz + if (Flag.Common.IS_SEALED(clazz.flags)) _sealedClasses += clazz + } + + fun reset() { + _allClasses.clear() + _sealedClasses.clear() + } +} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/context.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/context.kt deleted file mode 100644 index d2abb16131c..00000000000 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/context.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.descriptors.commonizer.metadata - -import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget -import org.jetbrains.kotlin.descriptors.commonizer.cir.* -import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode -import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon -import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNodeWithLiftingUp -import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode - -internal interface VisitingContext { - val targetIndex: Int - val target: CommonizerTarget - val isCommon: Boolean - val typeParameterIndexOffset: Int - val topLevelContext: VisitingContext - - fun childContext(declarationWithTypeParameters: CirHasTypeParameters): VisitingContext { - val ownTypeParametersCount = declarationWithTypeParameters.typeParameters.size - return if (ownTypeParametersCount == 0) this else ChildVisitingContext(this, ownTypeParametersCount) - } - - companion object { - fun newContext(rootNode: CirRootNode, targetIndex: Int): VisitingContext = - TopLevelVisitingContext(rootNode, targetIndex) - } - - private class TopLevelVisitingContext( - rootNode: CirRootNode, - override val targetIndex: Int - ) : VisitingContext { - override val isCommon = rootNode.indexOfCommon == targetIndex - override val target = get(rootNode)!!.target - override val typeParameterIndexOffset get() = 0 - override val topLevelContext: VisitingContext get() = this - } - - private class ChildVisitingContext( - private val parent: VisitingContext, - typeParametersCount: Int - ) : VisitingContext by parent { - override val typeParameterIndexOffset = parent.typeParameterIndexOffset + typeParametersCount - } -} - -internal inline fun VisitingContext.get(node: CirNodeWithLiftingUp<*, *>): T? { - return when { - isCommon -> node.commonDeclaration() as T? - node.isLiftedUp -> null - else -> node.targetDeclarations[targetIndex] as T? - } -} - -internal inline fun VisitingContext.get(node: CirNode<*, *>): T? { - return (if (isCommon) node.commonDeclaration() else node.targetDeclarations[targetIndex]) as T? -} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/visitor.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/visitor.kt deleted file mode 100644 index a9da38596aa..00000000000 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/metadata/visitor.kt +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.descriptors.commonizer.metadata - -import kotlinx.metadata.* -import kotlinx.metadata.klib.KlibModuleMetadata -import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget -import org.jetbrains.kotlin.descriptors.commonizer.cir.* -import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.* -import org.jetbrains.kotlin.utils.addToStdlib.cast - -// TODO: add logging -@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") -internal object MetadataBuilder { - fun build(node: CirRootNode, targetIndex: Int): Pair> = - node.accept(MetadataBuildingVisitor(), VisitingContext.newContext(node, targetIndex)).cast() - - private class MetadataBuildingVisitor : CirNodeVisitor { - private val classConsumer = ClassConsumer() - - override fun visitRootNode(node: CirRootNode, context: VisitingContext): Pair> { - val modules: Collection = buildMembers(context, node.modules) - return context.target to modules - } - - override fun visitModuleNode(node: CirModuleNode, context: VisitingContext): KlibModuleMetadata? { - val cirModule = context.get(node) ?: return null - - val fragments: MutableCollection = mutableListOf() - buildMembers(context, node.packages, destination = fragments) - addEmptyFragments(fragments) - - return cirModule.buildModule(fragments) - } - - override fun visitPackageNode(node: CirPackageNode, context: VisitingContext): KmModuleFragment? { - val cirPackage = context.get(node) ?: return null - try { - buildMembers(context, node.classes, callback = classConsumer::consumeAll) - - val topLevelTypeAliases = mutableListOf() - node.typeAliases.values.forEach { typeAliasNode -> - when (val classifier = typeAliasNode.accept(this, context)) { - null -> Unit - is KmClass -> classConsumer.consume(classifier) - is KmTypeAlias -> topLevelTypeAliases += classifier - else -> error("Unexpected classifier: ${classifier::class.java}, $classifier") - } - } - - linkSealedClassesWithSubclasses(node.fqName, classConsumer) - - val topLevelFunctions: Collection = buildMembers(context, node.functions) - val topLevelProperties: Collection = buildMembers(context, node.properties) - - return cirPackage.buildModuleFragment(classConsumer.allClasses, topLevelTypeAliases, topLevelFunctions, topLevelProperties) - } finally { - // Important: clean-up class consumer every time when leaving package - classConsumer.reset() - } - } - - override fun visitPropertyNode(node: CirPropertyNode, context: VisitingContext): KmProperty? { - return context.get(node)?.buildProperty(context) - } - - override fun visitFunctionNode(node: CirFunctionNode, context: VisitingContext): KmFunction? { - return context.get(node)?.buildFunction(context) - } - - override fun visitClassNode(node: CirClassNode, context: VisitingContext): KmClass? { - val cirClass = context.get(node) ?: return null - - @Suppress("NAME_SHADOWING") val context = if (cirClass.isInner) context else context.topLevelContext - val classContext = context.childContext(cirClass) - - val directNestedClasses = buildMembers(context = classContext, node.classes, callback = classConsumer::consumeAll) - val nestedConstructors: Collection = buildMembers(context = classContext, node.constructors) - val nestedFunctions: Collection = buildMembers(context = classContext, node.functions) - val nestedProperties: Collection = buildMembers(context = classContext, node.properties) - - val className = node.classId.asString() - - return cirClass.buildClass(context, className, directNestedClasses, nestedConstructors, nestedFunctions, nestedProperties) - } - - override fun visitClassConstructorNode(node: CirClassConstructorNode, context: VisitingContext): KmConstructor? { - return context.get(node)?.buildClassConstructor(context) - } - - override fun visitTypeAliasNode(node: CirTypeAliasNode, context: VisitingContext): Any? { - val cirClassifier = context.get(node) ?: return null - val className = node.classId.asString() - - return when (cirClassifier) { - is CirTypeAlias -> cirClassifier.buildTypeAlias(context) - is CirClass -> cirClassifier.buildClass(context, className, emptyList(), emptyList(), emptyList(), emptyList()) - else -> error("Unexpected CIR classifier: ${cirClassifier::class.java}, $cirClassifier") - } - } - - private inline fun , reified M : Any> buildMembers( - context: VisitingContext, - cirMembersNodes: Map<*, N>, - destination: MutableCollection = mutableListOf(), - callback: (Collection) -> Unit = {} - ): Collection { - return cirMembersNodes.values.mapNotNullTo(destination) { it.accept(this, context) as M? }.also(callback) - } - } -} - -internal class ClassConsumer { - private val _allClasses = mutableListOf() - private val _sealedClasses = mutableListOf() - - val allClasses: Collection get() = _allClasses - val sealedClasses: Collection get() = _sealedClasses - - fun consume(clazz: KmClass) { - _allClasses += clazz - if (Flag.Common.IS_SEALED(clazz.flags)) _sealedClasses += clazz - } - - fun consumeAll(classes: Collection) = classes.forEach(::consume) - - fun reset() { - _allClasses.clear() - _sealedClasses.clear() - } -} diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/AggregatedStatsCollector.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/AggregatedStatsCollector.kt index 241cc876ba4..5c3f1e4b6dc 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/AggregatedStatsCollector.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/AggregatedStatsCollector.kt @@ -5,36 +5,34 @@ package org.jetbrains.kotlin.descriptors.commonizer.stats -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.commonizer.stats.AggregatedStatsCollector.AggregatedStatsRow import org.jetbrains.kotlin.descriptors.commonizer.stats.RawStatsCollector.CommonDeclarationStatus.* import org.jetbrains.kotlin.konan.target.KonanTarget class AggregatedStatsCollector( - targets: List, - private val output: StatsOutput + targets: List ) : StatsCollector { - private val aggregatingOutput = AggregatingOutput() - private val wrappedCollector = RawStatsCollector(targets, aggregatingOutput) + private val wrappedCollector = RawStatsCollector(targets) - override fun logStats(result: List) { - wrappedCollector.logStats(result) + override fun logDeclaration(targetIndex: Int, lazyStatsKey: () -> StatsCollector.StatsKey) { + wrappedCollector.logDeclaration(targetIndex, lazyStatsKey) } - override fun close() { - output.writeHeader(AggregatedStatsHeader) + override fun writeTo(statsOutput: StatsOutput) { + val aggregatingOutput = AggregatingOutput() + wrappedCollector.writeTo(aggregatingOutput) - aggregatingOutput.aggregatedStats.keys.sortedBy { it }.forEach { key -> - val row = aggregatingOutput.aggregatedStats.getValue(key) - output.writeRow(row) + statsOutput.use { + statsOutput.writeHeader(AggregatedStatsHeader) + + aggregatingOutput.aggregatedStats.keys.sortedBy { it }.forEach { key -> + val row = aggregatingOutput.aggregatedStats.getValue(key) + statsOutput.writeRow(row) + } } - - output.close() - wrappedCollector.close() } object AggregatedStatsHeader : StatsOutput.StatsHeader { - private val headerItems = listOf( + override fun toList(): List = listOf( "Declaration Type", "Lifted Up", "Lifted Up, %%", @@ -46,11 +44,9 @@ class AggregatedStatsCollector( "Failed: Other, %%", "Total" ) - - override fun toList(): List = headerItems } - class AggregatedStatsRow( + private class AggregatedStatsRow( private val declarationType: DeclarationType ) : StatsOutput.StatsRow { var liftedUp: Int = 0 @@ -78,33 +74,32 @@ class AggregatedStatsCollector( } } -} + private class AggregatingOutput : StatsOutput { + val aggregatedStats = HashMap() -@Suppress("MoveVariableDeclarationIntoWhen") -private class AggregatingOutput : StatsOutput { - val aggregatedStats = HashMap() + override fun writeHeader(header: StatsOutput.StatsHeader) { + check(header is RawStatsCollector.RawStatsHeader) + // do nothing + } - override fun writeHeader(header: StatsOutput.StatsHeader) { - check(header is RawStatsCollector.RawStatsHeader) - // do nothing - } + override fun writeRow(row: StatsOutput.StatsRow) { + check(row is RawStatsCollector.RawStatsRow) - override fun writeRow(row: StatsOutput.StatsRow) { - check(row is RawStatsCollector.RawStatsRow) - - val aggregatedStatsRow = aggregatedStats.getOrPut(row.declarationType) { AggregatedStatsRow(row.declarationType) } - when (row.common) { - LIFTED_UP -> aggregatedStatsRow.liftedUp++ - EXPECT -> aggregatedStatsRow.successfullyCommonized++ - MISSING -> { - if (row.platform.any { it == RawStatsCollector.PlatformDeclarationStatus.MISSING }) { - aggregatedStatsRow.failedBecauseMissing++ - } else { - aggregatedStatsRow.failedOther++ + val declarationType = row.statsKey.declarationType + val aggregatedStatsRow = aggregatedStats.getOrPut(declarationType) { AggregatedStatsRow(declarationType) } + when (row.common) { + LIFTED_UP -> aggregatedStatsRow.liftedUp++ + EXPECT -> aggregatedStatsRow.successfullyCommonized++ + MISSING -> { + if (row.platform.any { it == RawStatsCollector.PlatformDeclarationStatus.MISSING }) { + aggregatedStatsRow.failedBecauseMissing++ + } else { + aggregatedStatsRow.failedOther++ + } } } } - } - override fun close() = Unit + override fun close() = Unit + } } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/DeclarationType.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/DeclarationType.kt index ef510c4e964..529c2e11264 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/DeclarationType.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/DeclarationType.kt @@ -5,9 +5,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.stats -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.resolve.DescriptorUtils - enum class DeclarationType(val alias: String) { TOP_LEVEL_CONST_VAL("TOP-LEVEL CONST-VAL"), TOP_LEVEL_VAL("TOP-LEVEL VAL"), @@ -23,30 +20,5 @@ enum class DeclarationType(val alias: String) { TYPE_ALIAS("TYPE_ALIAS"), ENUM_ENTRY("ENUM_ENTRY"), ENUM_CLASS("ENUM_CLASS"), - MODULE("MODULE"), - UNKNOWN("UNKNOWN"); - - companion object { - val DeclarationDescriptor.declarationType: DeclarationType - get() = when (this) { - is ClassDescriptor -> { - if (isCompanionObject) { - COMPANION_OBJECT - } else when (kind) { - ClassKind.ENUM_CLASS -> ENUM_CLASS - ClassKind.ENUM_ENTRY -> ENUM_ENTRY - ClassKind.INTERFACE -> if (DescriptorUtils.isTopLevelDeclaration(this)) TOP_LEVEL_INTERFACE else NESTED_INTERFACE - else -> if (DescriptorUtils.isTopLevelDeclaration(this)) TOP_LEVEL_CLASS else NESTED_CLASS - } - } - is TypeAliasDescriptor -> TYPE_ALIAS - is ClassConstructorDescriptor -> CLASS_CONSTRUCTOR - is FunctionDescriptor -> if (DescriptorUtils.isTopLevelDeclaration(this)) TOP_LEVEL_FUN else NESTED_FUN - is PropertyDescriptor -> if (DescriptorUtils.isTopLevelDeclaration(this)) { - if (isConst) TOP_LEVEL_CONST_VAL else TOP_LEVEL_VAL - } else NESTED_VAL - is ModuleDescriptor -> MODULE - else -> UNKNOWN - } - } + MODULE("MODULE") } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/RawStatsCollector.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/RawStatsCollector.kt index 098e8d90670..2142e3aa1ab 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/RawStatsCollector.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/RawStatsCollector.kt @@ -5,19 +5,21 @@ package org.jetbrains.kotlin.descriptors.commonizer.stats +import com.intellij.util.containers.FactoryMap import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.commonizer.stats.DeclarationType.Companion.declarationType -import org.jetbrains.kotlin.descriptors.commonizer.utils.firstNonNull -import org.jetbrains.kotlin.descriptors.commonizer.utils.signature +import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector.StatsKey +import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsOutput.StatsHeader +import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsOutput.StatsRow import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import java.util.* +import kotlin.collections.ArrayList /** * Allows printing commonization statistics to the file system. * - * Output format is defined in [RawStatsCollector.output]. + * Output format is defined in [StatsOutput]. * - * Header row: "FQ Name, Extension Receiver, Parameter Names, Parameter Types, Declaration Type, common, , [...]" + * Header row: "ID, Extension Receiver, Parameter Names, Parameter Types, Declaration Type, common, , [...]" * * Possible values for "Declaration Type": * - MODULE @@ -44,113 +46,109 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe * * Example of output: -FQ Name|Extension Receiver|Parameter Names|Parameter Types|Declaration Type|common|macos_x64|ios_x64 -||||MODULE|E|A|A -platform.SystemConfiguration.SCPreferencesContext||||CLASS|E|A|A -platform.SystemConfiguration.SCPreferencesContext.Companion||||COMPANION_OBJECT|E|A|A -platform.SystemConfiguration.SCNetworkConnectionContext||||CLASS|E|A|A -platform.SystemConfiguration.SCNetworkConnectionContext.Companion||||COMPANION_OBJECT|E|A|A -platform.SystemConfiguration.SCDynamicStoreRefVar||||TYPE_ALIAS|-|O|O -platform.SystemConfiguration.SCVLANInterfaceRef||||TYPE_ALIAS|-|O|O +ID|Extension Receiver|Parameter Names|Parameter Types|Declaration Type|common|macos_x64|ios_x64 +SystemConfiguration||||MODULE|E|A|A +platform/SystemConfiguration/SCPreferencesContext||||CLASS|E|A|A +platform/SystemConfiguration/SCPreferencesContext.Companion||||COMPANION_OBJECT|E|A|A +platform/SystemConfiguration/SCNetworkConnectionContext||||CLASS|E|A|A +platform/SystemConfiguration/SCNetworkConnectionContext.Companion||||COMPANION_OBJECT|E|A|A +platform/SystemConfiguration/SCDynamicStoreRefVar||||TYPE_ALIAS|-|O|O +platform/SystemConfiguration/SCVLANInterfaceRef||||TYPE_ALIAS|-|O|O */ -class RawStatsCollector( - private val targets: List, - private val output: StatsOutput -) : StatsCollector { - private var headerWritten = false +class RawStatsCollector(private val targets: List) : StatsCollector { + private inline val dimension get() = targets.size + 1 + private inline val targetNames get() = targets.map { it.name } - override fun logStats(result: List) { - if (!headerWritten) { - writeHeader() - headerWritten = true - } + private inline val indexOfCommon get() = targets.size + private inline val platformDeclarationsCount get() = targets.size - val firstNotNull = result.firstNonNull() - val lastIsNull = result.last() == null + private val stats = FactoryMap.create { StatsValue(dimension) } - val statsRow = RawStatsRow( - dimension = targets.size, - fqName = if (firstNotNull is ModuleDescriptor) firstNotNull.name.asString() else firstNotNull.fqNameSafe.asString(), - declarationType = firstNotNull.declarationType - ) + override fun logDeclaration(targetIndex: Int, lazyStatsKey: () -> StatsKey) { + stats.getValue(lazyStatsKey())[targetIndex] = true + } - // extension receiver - if (firstNotNull is PropertyDescriptor || firstNotNull is SimpleFunctionDescriptor) { - statsRow.extensionReceiver = - (firstNotNull as CallableDescriptor).extensionReceiverParameter?.type?.signature.orEmpty() - } - - if (firstNotNull is ConstructorDescriptor || firstNotNull is SimpleFunctionDescriptor) { - val functionDescriptor = (firstNotNull as FunctionDescriptor) - // parameter names - statsRow.parameterNames = functionDescriptor.valueParameters.joinToString { it.name.asString() } - // parameter types - statsRow.parameterTypes = functionDescriptor.valueParameters.joinToString { it.type.signature } - } - - var isLiftedUp = !lastIsNull - for (index in 0 until result.size - 1) { - statsRow.platform += when { - result[index] == null -> PlatformDeclarationStatus.MISSING - lastIsNull -> PlatformDeclarationStatus.ORIGINAL - else -> { - isLiftedUp = false - PlatformDeclarationStatus.ACTUAL - } + override fun writeTo(statsOutput: StatsOutput) { + val mergedStats = stats.filterTo(mutableMapOf()) { (statsKey, _) -> + when (statsKey.declarationType) { + DeclarationType.TOP_LEVEL_CLASS, DeclarationType.TOP_LEVEL_INTERFACE -> false + else -> true } } - statsRow.common = when { - isLiftedUp -> CommonDeclarationStatus.LIFTED_UP - lastIsNull -> CommonDeclarationStatus.MISSING - else -> CommonDeclarationStatus.EXPECT + stats.forEach { (statsKey, statsValue) -> + when (statsKey.declarationType) { + DeclarationType.TOP_LEVEL_CLASS, DeclarationType.TOP_LEVEL_INTERFACE -> { + if (statsValue[indexOfCommon]) { + val alternativeKey = statsKey.copy(declarationType = DeclarationType.TYPE_ALIAS) + val alternativeValue = mergedStats[alternativeKey] + if (alternativeValue != null && !alternativeValue[indexOfCommon]) { + alternativeValue[indexOfCommon] = true + return@forEach + } + } + + mergedStats[statsKey] = statsValue + } + else -> Unit + } } - output.writeRow(statsRow) - } + statsOutput.use { + statsOutput.writeHeader(RawStatsHeader(targetNames)) - override fun close() { - output.close() - } + mergedStats.forEach { (statsKey, statsValue) -> + val commonIsMissing = !statsValue[indexOfCommon] - private fun writeHeader() { - output.writeHeader(RawStatsHeader(targets.map { it.name })) - } + var isLiftedUp = !commonIsMissing + val platform = ArrayList(platformDeclarationsCount) - class RawStatsHeader( - private val targetNames: List - ) : StatsOutput.StatsHeader { - override fun toList(): List = mutableListOf().apply { - this += "FQ Name" - this += "Extension Receiver" - this += "Parameter Names" - this += "Parameter Types" - this += "Declaration Type" - this += "common" - this += targetNames + for (index in 0 until platformDeclarationsCount) { + platform += when { + !statsValue[index] -> PlatformDeclarationStatus.MISSING + commonIsMissing -> PlatformDeclarationStatus.ORIGINAL + else -> { + isLiftedUp = false + PlatformDeclarationStatus.ACTUAL + } + } + } + + val common = when { + isLiftedUp -> CommonDeclarationStatus.LIFTED_UP + commonIsMissing -> CommonDeclarationStatus.MISSING + else -> CommonDeclarationStatus.EXPECT + } + + statsOutput.writeRow(RawStatsRow(statsKey, common, platform)) + } } } + class RawStatsHeader(private val targetNames: List) : StatsHeader { + override fun toList() = + listOf("ID", "Extension Receiver", "Parameter Names", "Parameter Types", "Declaration Type", "common") + targetNames + } + class RawStatsRow( - dimension: Int, - val fqName: String, - val declarationType: DeclarationType - ) : StatsOutput.StatsRow { - var extensionReceiver: String = "" - var parameterNames: String = "" - var parameterTypes: String = "" - lateinit var common: CommonDeclarationStatus - val platform: MutableList = ArrayList(dimension) + val statsKey: StatsKey, + val common: CommonDeclarationStatus, + val platform: List + ) : StatsRow { + override fun toList(): List { + val result = mutableListOf( + statsKey.id, + statsKey.extensionReceiver.orEmpty(), + statsKey.parameterNames.joinToString(), + statsKey.parameterTypes.joinToString(), + statsKey.declarationType.alias, + common.alias.toString() + ) - override fun toList(): List = mutableListOf().apply { - this += fqName - this += extensionReceiver - this += parameterNames - this += parameterTypes - this += declarationType.alias - this += common.alias.toString() - platform.forEach { this += it.alias.toString() } + platform.mapTo(result) { it.alias.toString() } + + return result } } @@ -166,3 +164,5 @@ class RawStatsCollector( MISSING('-') } } + +private typealias StatsValue = BitSet diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/StatsCollector.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/StatsCollector.kt index c7872277fc0..6a67558db9d 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/StatsCollector.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/stats/StatsCollector.kt @@ -5,9 +5,17 @@ package org.jetbrains.kotlin.descriptors.commonizer.stats -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import java.io.Closeable +interface StatsCollector { + data class StatsKey( + val id: String, + val extensionReceiver: String?, + val parameterNames: List, + val parameterTypes: List, + val declarationType: DeclarationType + ) { + constructor(id: String, declarationType: DeclarationType) : this(id, null, emptyList(), emptyList(), declarationType) + } -interface StatsCollector : Closeable { - fun logStats(result: List) + fun logDeclaration(targetIndex: Int, lazyStatsKey: () -> StatsKey) + fun writeTo(statsOutput: StatsOutput) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt index 3b91f0b733c..91aa52b71d5 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/fqName.kt @@ -44,6 +44,9 @@ private val OBJC_INTEROP_CALLABLE_ANNOTATIONS = listOf( "ObjCFactory" ) +internal val DEFAULT_CONSTRUCTOR_NAME = Name.identifier("").intern() +internal val DEFAULT_SETTER_VALUE_NAME = Name.identifier("value").intern() + internal fun Name.strip(): String = asString().removeSurrounding("<", ">") diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt index d55607fe847..dc9ed8ad2de 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils/type.kt @@ -58,6 +58,9 @@ private fun StringBuilder.buildTypeSignature(type: KotlinType, exploredTypeParam } append("]") } + + if (type.isMarkedNullable) + append("?") } else { // N.B. this is classifier type val abbreviation = (type as? AbbreviatedType)?.abbreviation ?: type @@ -81,10 +84,10 @@ private fun StringBuilder.buildTypeSignature(type: KotlinType, exploredTypeParam } append(">") } - } - if (type.isMarkedNullable) - append("?") + if (abbreviation.isMarkedNullable) + append("?") + } } // dedicated to hold unique entries of "signature"