[Commonizer] Log stats during building metadata

This commit is contained in:
Dmitriy Dolovov
2021-01-27 17:16:59 +03:00
parent d610837caf
commit 4c640e3f81
19 changed files with 653 additions and 435 deletions
@@ -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(
@@ -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<TargetDeclarationsBuilderComponents>,
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 {
@@ -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(
@@ -20,9 +20,6 @@ internal fun CirModuleNode.buildDescriptors(
}
commonDeclaration()?.buildDescriptor(components, output, indexOfCommon)
// log stats
components.statsCollector?.logStats(output)
}
private fun CirModule.buildDescriptor(
@@ -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(
@@ -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(
@@ -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<String, ModuleDescriptor>? = components?.targetComponents?.get(targetIndex)?.let { component ->
@@ -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) {
@@ -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<CirTypeSignature>,
val name: Name,
val valueParametersTypes: Array<CirTypeSignature>,
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<CirTypeSignature>,
val valueParametersTypes: Array<CirTypeSignature>,
private val additionalValueParametersNamesHash: Int
) {
constructor(constructor: ConstructorDescriptor) : this(
@@ -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<KmModuleFragment>) {
}
internal fun CirClass.buildClass(
context: VisitingContext,
context: MetadataBuildingVisitorContext,
className: ClassName,
directNestedClasses: Collection<KmClass>,
nestedConstructors: Collection<KmConstructor>,
@@ -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<CirTypeParameter>.buildTypeParameters(
context: VisitingContext,
context: MetadataBuildingVisitorContext,
output: MutableList<KmTypeParameter>
) {
mapIndexedTo(output) { index, cirTypeParameter ->
@@ -261,7 +262,7 @@ private fun List<CirTypeParameter>.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")
@@ -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<CommonizerTarget, Collection<KlibModuleMetadata>> {
return node.accept(
MetadataBuildingVisitor(statsCollector),
MetadataBuildingVisitorContext.rootContext(node, targetIndex)
).cast()
}
}
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
private class MetadataBuildingVisitor(private val statsCollector: StatsCollector?) : CirNodeVisitor<MetadataBuildingVisitorContext, Any?> {
private val classConsumer = ClassConsumer()
override fun visitRootNode(
node: CirRootNode,
rootContext: MetadataBuildingVisitorContext
): Pair<CommonizerTarget, Collection<KlibModuleMetadata>> {
val modules: List<KlibModuleMetadata> = 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<CirModule>(node) ?: return null
val fragments: MutableCollection<KmModuleFragment> = 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<CirPackage>(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<KmTypeAlias>()
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<KmFunction> = 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<KmProperty> = 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<CirProperty>(node)?.buildProperty(propertyContext)
}
override fun visitFunctionNode(
node: CirFunctionNode,
functionContext: MetadataBuildingVisitorContext
): KmFunction? {
return functionContext.get<CirFunction>(node)?.buildFunction(functionContext)
}
override fun visitClassNode(
node: CirClassNode,
classContext: MetadataBuildingVisitorContext
): KmClass? {
val cirClass = classContext.get<CirClass>(node) ?: return null
val classTypeParametersCount = cirClass.typeParameters.size
val fullClassName = classContext.currentPath.toString()
val directNestedClasses: Collection<KmClass> = node.classes.mapNotNull { (nestedClassName, nestedClassNode) ->
val isInnerClass = classContext.get<CirClass>(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<KmConstructor> = 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<KmFunction> = 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<KmProperty> = 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<CirClassConstructor>(node)?.buildClassConstructor(constructorContext)
}
override fun visitTypeAliasNode(
node: CirTypeAliasNode,
typeAliasContext: MetadataBuildingVisitorContext
): Any? {
val cirClassifier = typeAliasContext.get<CirClassifier>(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 <reified T : CirDeclaration> get(node: CirNode<*, *>): T? {
return (if (isCommon) node.commonDeclaration() else node.targetDeclarations[targetIndex]) as T?
}
inline fun <reified T : CirDeclaration> 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<KmClass>()
private val _sealedClasses = mutableListOf<KmClass>()
val allClasses: Collection<KmClass> get() = _allClasses
val sealedClasses: Collection<KmClass> get() = _sealedClasses
fun consume(clazz: KmClass) {
_allClasses += clazz
if (Flag.Common.IS_SEALED(clazz.flags)) _sealedClasses += clazz
}
fun reset() {
_allClasses.clear()
_sealedClasses.clear()
}
}
@@ -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<CirRoot>(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 <reified T : CirDeclaration> VisitingContext.get(node: CirNodeWithLiftingUp<*, *>): T? {
return when {
isCommon -> node.commonDeclaration() as T?
node.isLiftedUp -> null
else -> node.targetDeclarations[targetIndex] as T?
}
}
internal inline fun <reified T : CirDeclaration> VisitingContext.get(node: CirNode<*, *>): T? {
return (if (isCommon) node.commonDeclaration() else node.targetDeclarations[targetIndex]) as T?
}
@@ -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<CommonizerTarget, Collection<KlibModuleMetadata>> =
node.accept(MetadataBuildingVisitor(), VisitingContext.newContext(node, targetIndex)).cast()
private class MetadataBuildingVisitor : CirNodeVisitor<VisitingContext, Any?> {
private val classConsumer = ClassConsumer()
override fun visitRootNode(node: CirRootNode, context: VisitingContext): Pair<CommonizerTarget, Collection<KlibModuleMetadata>> {
val modules: Collection<KlibModuleMetadata> = buildMembers(context, node.modules)
return context.target to modules
}
override fun visitModuleNode(node: CirModuleNode, context: VisitingContext): KlibModuleMetadata? {
val cirModule = context.get<CirModule>(node) ?: return null
val fragments: MutableCollection<KmModuleFragment> = 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<CirPackage>(node) ?: return null
try {
buildMembers(context, node.classes, callback = classConsumer::consumeAll)
val topLevelTypeAliases = mutableListOf<KmTypeAlias>()
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<KmFunction> = buildMembers(context, node.functions)
val topLevelProperties: Collection<KmProperty> = 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<CirProperty>(node)?.buildProperty(context)
}
override fun visitFunctionNode(node: CirFunctionNode, context: VisitingContext): KmFunction? {
return context.get<CirFunction>(node)?.buildFunction(context)
}
override fun visitClassNode(node: CirClassNode, context: VisitingContext): KmClass? {
val cirClass = context.get<CirClass>(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<KmConstructor> = buildMembers(context = classContext, node.constructors)
val nestedFunctions: Collection<KmFunction> = buildMembers(context = classContext, node.functions)
val nestedProperties: Collection<KmProperty> = 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<CirClassConstructor>(node)?.buildClassConstructor(context)
}
override fun visitTypeAliasNode(node: CirTypeAliasNode, context: VisitingContext): Any? {
val cirClassifier = context.get<CirClassifier>(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 N : CirNode<*, *>, reified M : Any> buildMembers(
context: VisitingContext,
cirMembersNodes: Map<*, N>,
destination: MutableCollection<M> = mutableListOf(),
callback: (Collection<M>) -> Unit = {}
): Collection<M> {
return cirMembersNodes.values.mapNotNullTo(destination) { it.accept(this, context) as M? }.also(callback)
}
}
}
internal class ClassConsumer {
private val _allClasses = mutableListOf<KmClass>()
private val _sealedClasses = mutableListOf<KmClass>()
val allClasses: Collection<KmClass> get() = _allClasses
val sealedClasses: Collection<KmClass> get() = _sealedClasses
fun consume(clazz: KmClass) {
_allClasses += clazz
if (Flag.Common.IS_SEALED(clazz.flags)) _sealedClasses += clazz
}
fun consumeAll(classes: Collection<KmClass>) = classes.forEach(::consume)
fun reset() {
_allClasses.clear()
_sealedClasses.clear()
}
}
@@ -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<KonanTarget>,
private val output: StatsOutput
targets: List<KonanTarget>
) : StatsCollector {
private val aggregatingOutput = AggregatingOutput()
private val wrappedCollector = RawStatsCollector(targets, aggregatingOutput)
private val wrappedCollector = RawStatsCollector(targets)
override fun logStats(result: List<DeclarationDescriptor?>) {
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<String> = listOf(
"Declaration Type",
"Lifted Up",
"Lifted Up, %%",
@@ -46,11 +44,9 @@ class AggregatedStatsCollector(
"Failed: Other, %%",
"Total"
)
override fun toList(): List<String> = 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<DeclarationType, AggregatedStatsRow>()
@Suppress("MoveVariableDeclarationIntoWhen")
private class AggregatingOutput : StatsOutput {
val aggregatedStats = HashMap<DeclarationType, AggregatedStatsRow>()
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
}
}
@@ -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")
}
@@ -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, <platform1>, <platform2> [<platformN>...]"
* Header row: "ID, Extension Receiver, Parameter Names, Parameter Types, Declaration Type, common, <platform1>, <platform2> [<platformN>...]"
*
* 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
<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
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<KonanTarget>,
private val output: StatsOutput
) : StatsCollector {
private var headerWritten = false
class RawStatsCollector(private val targets: List<KonanTarget>) : StatsCollector {
private inline val dimension get() = targets.size + 1
private inline val targetNames get() = targets.map { it.name }
override fun logStats(result: List<DeclarationDescriptor?>) {
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<StatsKey, StatsValue> { 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<PlatformDeclarationStatus>(platformDeclarationsCount)
class RawStatsHeader(
private val targetNames: List<String>
) : StatsOutput.StatsHeader {
override fun toList(): List<String> = mutableListOf<String>().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<String>) : 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<PlatformDeclarationStatus> = ArrayList(dimension)
val statsKey: StatsKey,
val common: CommonDeclarationStatus,
val platform: List<PlatformDeclarationStatus>
) : StatsRow {
override fun toList(): List<String> {
val result = mutableListOf(
statsKey.id,
statsKey.extensionReceiver.orEmpty(),
statsKey.parameterNames.joinToString(),
statsKey.parameterTypes.joinToString(),
statsKey.declarationType.alias,
common.alias.toString()
)
override fun toList(): List<String> = mutableListOf<String>().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
@@ -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<String>,
val parameterTypes: List<String>,
val declarationType: DeclarationType
) {
constructor(id: String, declarationType: DeclarationType) : this(id, null, emptyList(), emptyList(), declarationType)
}
interface StatsCollector : Closeable {
fun logStats(result: List<DeclarationDescriptor?>)
fun logDeclaration(targetIndex: Int, lazyStatsKey: () -> StatsKey)
fun writeTo(statsOutput: StatsOutput)
}
@@ -44,6 +44,9 @@ private val OBJC_INTEROP_CALLABLE_ANNOTATIONS = listOf(
"ObjCFactory"
)
internal val DEFAULT_CONSTRUCTOR_NAME = Name.identifier("<init>").intern()
internal val DEFAULT_SETTER_VALUE_NAME = Name.identifier("value").intern()
internal fun Name.strip(): String =
asString().removeSurrounding("<", ">")
@@ -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"