[Commonizer] Log commonization stats into a single file
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
|
||||||
|
class CommonizationParameters(
|
||||||
|
val statsCollector: StatsCollector? = null
|
||||||
|
) {
|
||||||
|
// use linked hash map to preserve order
|
||||||
|
private val modulesByTargets = LinkedHashMap<InputTarget, Collection<ModuleDescriptor>>()
|
||||||
|
|
||||||
|
fun addTarget(target: InputTarget, modules: Collection<ModuleDescriptor>): CommonizationParameters {
|
||||||
|
require(target !in modulesByTargets) { "Target $target is already added" }
|
||||||
|
|
||||||
|
val modulesWithUniqueNames = modules.groupingBy { it.name }.eachCount()
|
||||||
|
require(modulesWithUniqueNames.size == modules.size) {
|
||||||
|
"Modules with duplicated names found: ${modulesWithUniqueNames.filter { it.value > 1 }}"
|
||||||
|
}
|
||||||
|
|
||||||
|
modulesByTargets[target] = modules
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
// get them as ordered immutable collection (List) for further processing
|
||||||
|
fun getModulesByTargets(): List<Pair<InputTarget, Collection<ModuleDescriptor>>> =
|
||||||
|
modulesByTargets.map { it.key to it.value }
|
||||||
|
|
||||||
|
fun hasIntersection(): Boolean {
|
||||||
|
if (modulesByTargets.size < 2)
|
||||||
|
return false
|
||||||
|
|
||||||
|
return modulesByTargets.flatMap { it.value }
|
||||||
|
.groupingBy { it.name }
|
||||||
|
.eachCount()
|
||||||
|
.any { it.value == modulesByTargets.size }
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
|
||||||
|
sealed class CommonizationResult
|
||||||
|
|
||||||
|
object NothingToCommonize : CommonizationResult()
|
||||||
|
|
||||||
|
class CommonizationPerformed(
|
||||||
|
val modulesByTargets: Map<Target, Collection<ModuleDescriptor>>
|
||||||
|
) : CommonizationResult() {
|
||||||
|
val commonTarget: OutputTarget by lazy {
|
||||||
|
modulesByTargets.keys.filterIsInstance<OutputTarget>().single()
|
||||||
|
}
|
||||||
|
|
||||||
|
val concreteTargets: Set<InputTarget> by lazy {
|
||||||
|
modulesByTargets.keys.filterIsInstance<InputTarget>().toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import java.io.Closeable
|
||||||
|
|
||||||
|
interface StatsCollector : Closeable {
|
||||||
|
fun logStats(output: List<DeclarationDescriptor?>)
|
||||||
|
}
|
||||||
+4
-12
@@ -52,8 +52,7 @@ internal class DeclarationsBuilderVisitor1(
|
|||||||
|
|
||||||
override fun visitModuleNode(node: CirModuleNode, data: List<DeclarationDescriptor?>): List<ModuleDescriptorImpl?> {
|
override fun visitModuleNode(node: CirModuleNode, data: List<DeclarationDescriptor?>): List<ModuleDescriptorImpl?> {
|
||||||
// build module descriptors:
|
// build module descriptors:
|
||||||
val moduleDescriptorsGroup =
|
val moduleDescriptorsGroup = CommonizedGroup<ModuleDescriptorImpl>(node.dimension)
|
||||||
CommonizedGroup<ModuleDescriptorImpl>(node.dimension)
|
|
||||||
node.buildDescriptors(components, moduleDescriptorsGroup)
|
node.buildDescriptors(components, moduleDescriptorsGroup)
|
||||||
val moduleDescriptors = moduleDescriptorsGroup.toList()
|
val moduleDescriptors = moduleDescriptorsGroup.toList()
|
||||||
|
|
||||||
@@ -76,8 +75,7 @@ internal class DeclarationsBuilderVisitor1(
|
|||||||
val containingDeclarations = data.asListContaining<ModuleDescriptorImpl>()
|
val containingDeclarations = data.asListContaining<ModuleDescriptorImpl>()
|
||||||
|
|
||||||
// build package fragments:
|
// build package fragments:
|
||||||
val packageFragmentsGroup =
|
val packageFragmentsGroup = CommonizedGroup<CommonizedPackageFragmentDescriptor>(node.dimension)
|
||||||
CommonizedGroup<CommonizedPackageFragmentDescriptor>(node.dimension)
|
|
||||||
node.buildDescriptors(components, packageFragmentsGroup, containingDeclarations)
|
node.buildDescriptors(components, packageFragmentsGroup, containingDeclarations)
|
||||||
val packageFragments = packageFragmentsGroup.toList()
|
val packageFragments = packageFragmentsGroup.toList()
|
||||||
|
|
||||||
@@ -105,10 +103,7 @@ internal class DeclarationsBuilderVisitor1(
|
|||||||
error("This method should not be called in ${this::class.java}")
|
error("This method should not be called in ${this::class.java}")
|
||||||
|
|
||||||
override fun visitClassNode(node: CirClassNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
override fun visitClassNode(node: CirClassNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
||||||
val classesGroup =
|
val classesGroup = CommonizedGroup<ClassifierDescriptorWithTypeParameters>(node.dimension)
|
||||||
CommonizedGroup<ClassifierDescriptorWithTypeParameters>(
|
|
||||||
node.dimension
|
|
||||||
)
|
|
||||||
node.buildDescriptors(components, classesGroup, data)
|
node.buildDescriptors(components, classesGroup, data)
|
||||||
val classes = classesGroup.toList().asListContaining<CommonizedClassDescriptor>()
|
val classes = classesGroup.toList().asListContaining<CommonizedClassDescriptor>()
|
||||||
|
|
||||||
@@ -130,10 +125,7 @@ internal class DeclarationsBuilderVisitor1(
|
|||||||
error("This method should not be called in ${this::class.java}")
|
error("This method should not be called in ${this::class.java}")
|
||||||
|
|
||||||
override fun visitTypeAliasNode(node: CirTypeAliasNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
override fun visitTypeAliasNode(node: CirTypeAliasNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
||||||
val typeAliasesGroup =
|
val typeAliasesGroup = CommonizedGroup<ClassifierDescriptorWithTypeParameters>(node.dimension)
|
||||||
CommonizedGroup<ClassifierDescriptorWithTypeParameters>(
|
|
||||||
node.dimension
|
|
||||||
)
|
|
||||||
node.buildDescriptors(components, typeAliasesGroup, data)
|
node.buildDescriptors(components, typeAliasesGroup, data)
|
||||||
val typeAliases = typeAliasesGroup.toList()
|
val typeAliases = typeAliasesGroup.toList()
|
||||||
|
|
||||||
|
|||||||
+3
-6
@@ -65,16 +65,14 @@ internal class DeclarationsBuilderVisitor2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitPropertyNode(node: CirPropertyNode, data: List<DeclarationDescriptor?>): List<PropertyDescriptor?> {
|
override fun visitPropertyNode(node: CirPropertyNode, data: List<DeclarationDescriptor?>): List<PropertyDescriptor?> {
|
||||||
val propertyDescriptorsGroup =
|
val propertyDescriptorsGroup = CommonizedGroup<PropertyDescriptor>(node.dimension)
|
||||||
CommonizedGroup<PropertyDescriptor>(node.dimension)
|
|
||||||
node.buildDescriptors(components, propertyDescriptorsGroup, data)
|
node.buildDescriptors(components, propertyDescriptorsGroup, data)
|
||||||
|
|
||||||
return propertyDescriptorsGroup.toList()
|
return propertyDescriptorsGroup.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunctionNode(node: CirFunctionNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
override fun visitFunctionNode(node: CirFunctionNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
||||||
val functionDescriptorsGroup =
|
val functionDescriptorsGroup = CommonizedGroup<SimpleFunctionDescriptor>(node.dimension)
|
||||||
CommonizedGroup<SimpleFunctionDescriptor>(node.dimension)
|
|
||||||
node.buildDescriptors(components, functionDescriptorsGroup, data)
|
node.buildDescriptors(components, functionDescriptorsGroup, data)
|
||||||
|
|
||||||
return functionDescriptorsGroup.toList()
|
return functionDescriptorsGroup.toList()
|
||||||
@@ -116,8 +114,7 @@ internal class DeclarationsBuilderVisitor2(
|
|||||||
override fun visitClassConstructorNode(node: CirClassConstructorNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
override fun visitClassConstructorNode(node: CirClassConstructorNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
||||||
val containingDeclarations = data.asListContaining<CommonizedClassDescriptor>()
|
val containingDeclarations = data.asListContaining<CommonizedClassDescriptor>()
|
||||||
|
|
||||||
val constructorsGroup =
|
val constructorsGroup = CommonizedGroup<ClassConstructorDescriptor>(node.dimension)
|
||||||
CommonizedGroup<ClassConstructorDescriptor>(node.dimension)
|
|
||||||
node.buildDescriptors(components, constructorsGroup, containingDeclarations)
|
node.buildDescriptors(components, constructorsGroup, containingDeclarations)
|
||||||
|
|
||||||
return constructorsGroup.toList()
|
return constructorsGroup.toList()
|
||||||
|
|||||||
+6
@@ -26,6 +26,9 @@ internal fun CirClassNode.buildDescriptors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true)
|
commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true)
|
||||||
|
|
||||||
|
// log stats
|
||||||
|
components.statsCollector?.logStats(output.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun CirClass.buildDescriptor(
|
internal fun CirClass.buildDescriptor(
|
||||||
@@ -79,6 +82,9 @@ internal fun CirClassConstructorNode.buildDescriptors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
commonConstructor?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = true)
|
commonConstructor?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = true)
|
||||||
|
|
||||||
|
// log stats
|
||||||
|
components.statsCollector?.logStats(output.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CirClassConstructor.buildDescriptor(
|
private fun CirClassConstructor.buildDescriptor(
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.StatsCollector
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.Target
|
import org.jetbrains.kotlin.descriptors.commonizer.Target
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CirRootNode
|
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CirRootNode
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.dimension
|
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.dimension
|
||||||
@@ -108,7 +109,8 @@ class DeclarationsBuilderCache(dimension: Int) {
|
|||||||
class GlobalDeclarationsBuilderComponents(
|
class GlobalDeclarationsBuilderComponents(
|
||||||
val storageManager: StorageManager,
|
val storageManager: StorageManager,
|
||||||
val targetComponents: List<TargetDeclarationsBuilderComponents>,
|
val targetComponents: List<TargetDeclarationsBuilderComponents>,
|
||||||
val cache: DeclarationsBuilderCache
|
val cache: DeclarationsBuilderCache,
|
||||||
|
val statsCollector: StatsCollector?
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
check(targetComponents.size > 1)
|
check(targetComponents.size > 1)
|
||||||
@@ -154,7 +156,10 @@ class TargetDeclarationsBuilderComponents(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CirRootNode.createGlobalBuilderComponents(storageManager: StorageManager): GlobalDeclarationsBuilderComponents {
|
fun CirRootNode.createGlobalBuilderComponents(
|
||||||
|
storageManager: StorageManager,
|
||||||
|
statsCollector: StatsCollector?
|
||||||
|
): GlobalDeclarationsBuilderComponents {
|
||||||
val cache = DeclarationsBuilderCache(dimension)
|
val cache = DeclarationsBuilderCache(dimension)
|
||||||
|
|
||||||
val targetContexts = (0 until dimension).map { index ->
|
val targetContexts = (0 until dimension).map { index ->
|
||||||
@@ -176,7 +181,7 @@ fun CirRootNode.createGlobalBuilderComponents(storageManager: StorageManager): G
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return GlobalDeclarationsBuilderComponents(storageManager, targetContexts, cache)
|
return GlobalDeclarationsBuilderComponents(storageManager, targetContexts, cache, statsCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TypeParameterResolver {
|
interface TypeParameterResolver {
|
||||||
|
|||||||
+3
@@ -28,6 +28,9 @@ internal fun CirFunctionNode.buildDescriptors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
commonFunction?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual)
|
commonFunction?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual)
|
||||||
|
|
||||||
|
// log stats
|
||||||
|
components.statsCollector?.logStats(output.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CirFunction.buildDescriptor(
|
private fun CirFunction.buildDescriptor(
|
||||||
|
|||||||
+3
@@ -20,6 +20,9 @@ internal fun CirModuleNode.buildDescriptors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
common()?.buildDescriptor(components, output, indexOfCommon)
|
common()?.buildDescriptor(components, output, indexOfCommon)
|
||||||
|
|
||||||
|
// log stats
|
||||||
|
components.statsCollector?.logStats(output.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CirModule.buildDescriptor(
|
private fun CirModule.buildDescriptor(
|
||||||
|
|||||||
+3
@@ -31,6 +31,9 @@ internal fun CirPropertyNode.buildDescriptors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
commonProperty?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual)
|
commonProperty?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, isExpect = markAsExpectAndActual)
|
||||||
|
|
||||||
|
// log stats
|
||||||
|
components.statsCollector?.logStats(output.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CirProperty.buildDescriptor(
|
private fun CirProperty.buildDescriptor(
|
||||||
|
|||||||
+3
@@ -27,6 +27,9 @@ internal fun CirTypeAliasNode.buildDescriptors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true)
|
commonClass?.buildDescriptor(components, output, indexOfCommon, containingDeclarations, fqName, isExpect = true)
|
||||||
|
|
||||||
|
// log stats
|
||||||
|
components.statsCollector?.logStats(output.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CirTypeAlias.buildDescriptor(
|
private fun CirTypeAlias.buildDescriptor(
|
||||||
|
|||||||
+3
@@ -28,10 +28,13 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
val destination = parsedArgs["-output"]?.firstOrNull()?.let(::File) ?: printUsageAndExit("output not specified")
|
val destination = parsedArgs["-output"]?.firstOrNull()?.let(::File) ?: printUsageAndExit("output not specified")
|
||||||
|
|
||||||
|
val withStats = parsedArgs["-stats"]?.firstOrNull()?.toLowerCase() in setOf("1", "on", "yes", "true")
|
||||||
|
|
||||||
NativeDistributionCommonizer(
|
NativeDistributionCommonizer(
|
||||||
repository = repository,
|
repository = repository,
|
||||||
targets = targets,
|
targets = targets,
|
||||||
destination = destination,
|
destination = destination,
|
||||||
|
withStats = withStats,
|
||||||
handleError = ::printErrorAndExit,
|
handleError = ::printErrorAndExit,
|
||||||
log = ::println
|
log = ::println
|
||||||
).run()
|
).run()
|
||||||
|
|||||||
@@ -6,61 +6,13 @@
|
|||||||
package org.jetbrains.kotlin.descriptors.commonizer
|
package org.jetbrains.kotlin.descriptors.commonizer
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.builder.*
|
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.builder.DeclarationsBuilderVisitor1
|
import org.jetbrains.kotlin.descriptors.commonizer.builder.DeclarationsBuilderVisitor1
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.builder.DeclarationsBuilderVisitor2
|
import org.jetbrains.kotlin.descriptors.commonizer.builder.DeclarationsBuilderVisitor2
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.builder.createGlobalBuilderComponents
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizationVisitor
|
import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizationVisitor
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.mergeRoots
|
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.mergeRoots
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
|
||||||
class CommonizationParameters {
|
|
||||||
// use linked hash map to preserve order
|
|
||||||
private val modulesByTargets = LinkedHashMap<InputTarget, Collection<ModuleDescriptor>>()
|
|
||||||
|
|
||||||
fun addTarget(target: InputTarget, modules: Collection<ModuleDescriptor>): CommonizationParameters {
|
|
||||||
require(target !in modulesByTargets) { "Target $target is already added" }
|
|
||||||
|
|
||||||
val modulesWithUniqueNames = modules.groupingBy { it.name }.eachCount()
|
|
||||||
require(modulesWithUniqueNames.size == modules.size) {
|
|
||||||
"Modules with duplicated names found: ${modulesWithUniqueNames.filter { it.value > 1 }}"
|
|
||||||
}
|
|
||||||
|
|
||||||
modulesByTargets[target] = modules
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
// get them as ordered immutable collection (List) for further processing
|
|
||||||
fun getModulesByTargets(): List<Pair<InputTarget, Collection<ModuleDescriptor>>> =
|
|
||||||
modulesByTargets.map { it.key to it.value }
|
|
||||||
|
|
||||||
fun hasIntersection(): Boolean {
|
|
||||||
if (modulesByTargets.size < 2)
|
|
||||||
return false
|
|
||||||
|
|
||||||
return modulesByTargets.flatMap { it.value }
|
|
||||||
.groupingBy { it.name }
|
|
||||||
.eachCount()
|
|
||||||
.any { it.value == modulesByTargets.size }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class CommonizationResult
|
|
||||||
|
|
||||||
object NothingToCommonize : CommonizationResult()
|
|
||||||
|
|
||||||
class CommonizationPerformed(
|
|
||||||
val modulesByTargets: Map<Target, Collection<ModuleDescriptor>>
|
|
||||||
) : CommonizationResult() {
|
|
||||||
val commonTarget: OutputTarget by lazy {
|
|
||||||
modulesByTargets.keys.filterIsInstance<OutputTarget>().single()
|
|
||||||
}
|
|
||||||
|
|
||||||
val concreteTargets: Set<InputTarget> by lazy {
|
|
||||||
modulesByTargets.keys.filterIsInstance<InputTarget>().toSet()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun runCommonization(parameters: CommonizationParameters): CommonizationResult {
|
fun runCommonization(parameters: CommonizationParameters): CommonizationResult {
|
||||||
if (!parameters.hasIntersection())
|
if (!parameters.hasIntersection())
|
||||||
return NothingToCommonize
|
return NothingToCommonize
|
||||||
@@ -74,7 +26,7 @@ fun runCommonization(parameters: CommonizationParameters): CommonizationResult {
|
|||||||
mergedTree.accept(CommonizationVisitor(mergedTree), Unit)
|
mergedTree.accept(CommonizationVisitor(mergedTree), Unit)
|
||||||
|
|
||||||
// build resulting descriptors:
|
// build resulting descriptors:
|
||||||
val components = mergedTree.createGlobalBuilderComponents(storageManager)
|
val components = mergedTree.createGlobalBuilderComponents(storageManager, parameters.statsCollector)
|
||||||
mergedTree.accept(DeclarationsBuilderVisitor1(components), emptyList())
|
mergedTree.accept(DeclarationsBuilderVisitor1(components), emptyList())
|
||||||
mergedTree.accept(DeclarationsBuilderVisitor2(components), emptyList())
|
mergedTree.accept(DeclarationsBuilderVisitor2(components), emptyList())
|
||||||
|
|
||||||
|
|||||||
+36
-28
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.Target
|
|||||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeModuleForCommonization.DeserializedModule
|
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeModuleForCommonization.DeserializedModule
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeModuleForCommonization.SyntheticModule
|
import org.jetbrains.kotlin.descriptors.commonizer.konan.NativeModuleForCommonization.SyntheticModule
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.EmptyDescriptorTable
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.EmptyDescriptorTable
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.ResettableClockMark
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.createKotlinNativeForwardDeclarationsModule
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.createKotlinNativeForwardDeclarationsModule
|
||||||
import org.jetbrains.kotlin.konan.library.*
|
import org.jetbrains.kotlin.konan.library.*
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
@@ -27,13 +28,13 @@ import org.jetbrains.kotlin.serialization.konan.impl.KlibResolvedModuleDescripto
|
|||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
import kotlin.time.MonoClock
|
|
||||||
import org.jetbrains.kotlin.konan.file.File as KFile
|
import org.jetbrains.kotlin.konan.file.File as KFile
|
||||||
|
|
||||||
class NativeDistributionCommonizer(
|
class NativeDistributionCommonizer(
|
||||||
private val repository: File,
|
private val repository: File,
|
||||||
private val targets: List<KonanTarget>,
|
private val targets: List<KonanTarget>,
|
||||||
private val destination: File,
|
private val destination: File,
|
||||||
|
private val withStats: Boolean,
|
||||||
private val handleError: (String) -> Nothing,
|
private val handleError: (String) -> Nothing,
|
||||||
private val log: (String) -> Unit
|
private val log: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
@@ -41,23 +42,21 @@ class NativeDistributionCommonizer(
|
|||||||
fun run() {
|
fun run() {
|
||||||
checkPreconditions()
|
checkPreconditions()
|
||||||
|
|
||||||
val startMark = MonoClock.markNow()
|
with(ResettableClockMark()) {
|
||||||
val modulesByTargets = loadModules(repository, targets)
|
// 1. load modules
|
||||||
val loadDuration = startMark.elapsedNow()
|
val modulesByTargets = loadModules()
|
||||||
|
log("Loaded lazy (uninitialized) libraries in ${elapsedSinceLast()}")
|
||||||
|
|
||||||
log("Loaded lazy (uninitialized) libraries in $loadDuration")
|
// 2. run commonization
|
||||||
|
val result = commonize(modulesByTargets)
|
||||||
|
log("Commonization performed in ${elapsedSinceLast()}")
|
||||||
|
|
||||||
val result = commonize(modulesByTargets)
|
// 3. write new libraries
|
||||||
val commonizationDuration = startMark.elapsedNow() - loadDuration
|
saveModules(modulesByTargets, result)
|
||||||
|
log("Written libraries in ${elapsedSinceLast()}")
|
||||||
|
|
||||||
log("Commonization performed in $commonizationDuration")
|
log("TOTAL: ${elapsedSinceStart()}")
|
||||||
|
}
|
||||||
saveModules(modulesByTargets, destination, result)
|
|
||||||
val totalDuration = startMark.elapsedNow()
|
|
||||||
val writeDuration = totalDuration - commonizationDuration - loadDuration
|
|
||||||
|
|
||||||
log("Written libraries in $writeDuration")
|
|
||||||
log("TOTAL: $totalDuration")
|
|
||||||
|
|
||||||
log("Done.")
|
log("Done.")
|
||||||
log("")
|
log("")
|
||||||
@@ -79,7 +78,7 @@ class NativeDistributionCommonizer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadModules(repository: File, targets: List<KonanTarget>): Map<InputTarget, List<NativeModuleForCommonization>> {
|
private fun loadModules(): Map<InputTarget, List<NativeModuleForCommonization>> {
|
||||||
val stdlibPath = repository.resolve(konanCommonLibraryPath(KONAN_STDLIB_NAME))
|
val stdlibPath = repository.resolve(konanCommonLibraryPath(KONAN_STDLIB_NAME))
|
||||||
val stdlib = loadLibrary(stdlibPath)
|
val stdlib = loadLibrary(stdlibPath)
|
||||||
|
|
||||||
@@ -162,22 +161,24 @@ class NativeDistributionCommonizer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun commonize(modulesByTargets: Map<InputTarget, List<NativeModuleForCommonization>>): CommonizationPerformed {
|
private fun commonize(modulesByTargets: Map<InputTarget, List<NativeModuleForCommonization>>): CommonizationPerformed {
|
||||||
val parameters = CommonizationParameters().apply {
|
val statsCollector = if (withStats) NativeStatsCollector(targets, destination) else null
|
||||||
modulesByTargets.forEach { (target, modules) ->
|
statsCollector.use {
|
||||||
addTarget(target, modules.map { it.module })
|
val parameters = CommonizationParameters(statsCollector).apply {
|
||||||
|
modulesByTargets.forEach { (target, modules) ->
|
||||||
|
addTarget(target, modules.map { it.module })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val result = runCommonization(parameters)
|
val result = runCommonization(parameters)
|
||||||
return when (result) {
|
return when (result) {
|
||||||
is NothingToCommonize -> handleError("too few targets specified: ${modulesByTargets.keys}")
|
is NothingToCommonize -> handleError("too few targets specified: ${modulesByTargets.keys}")
|
||||||
is CommonizationPerformed -> result
|
is CommonizationPerformed -> result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveModules(
|
private fun saveModules(
|
||||||
originalModulesByTargets: Map<InputTarget, List<NativeModuleForCommonization>>,
|
originalModulesByTargets: Map<InputTarget, List<NativeModuleForCommonization>>,
|
||||||
destination: File,
|
|
||||||
result: CommonizationPerformed
|
result: CommonizationPerformed
|
||||||
) {
|
) {
|
||||||
// optimization: stdlib effectively remains the same across all Kotlin/Native targets,
|
// optimization: stdlib effectively remains the same across all Kotlin/Native targets,
|
||||||
@@ -205,8 +206,6 @@ class NativeDistributionCommonizer(
|
|||||||
skipExpects = false
|
skipExpects = false
|
||||||
)
|
)
|
||||||
|
|
||||||
val stdlibName = Name.special("<$KONAN_STDLIB_NAME>")
|
|
||||||
|
|
||||||
fun serializeTarget(target: Target) {
|
fun serializeTarget(target: Target) {
|
||||||
val libsDestination: File
|
val libsDestination: File
|
||||||
val newModulesManifestData: Map<Name, NativeSensitiveManifestData>
|
val newModulesManifestData: Map<Name, NativeSensitiveManifestData>
|
||||||
@@ -226,7 +225,9 @@ class NativeDistributionCommonizer(
|
|||||||
|
|
||||||
for (newModule in newModules) {
|
for (newModule in newModules) {
|
||||||
val libraryName = newModule.name
|
val libraryName = newModule.name
|
||||||
if (libraryName == stdlibName || libraryName == KlibResolvedModuleDescriptorsFactoryImpl.FORWARD_DECLARATIONS_MODULE_NAME) continue
|
|
||||||
|
if (!shouldBeSerialized(libraryName))
|
||||||
|
continue
|
||||||
|
|
||||||
val metadata = serializer.serializeModule(newModule)
|
val metadata = serializer.serializeModule(newModule)
|
||||||
val manifestData = newModulesManifestData.getValue(newModule.name)
|
val manifestData = newModulesManifestData.getValue(newModule.name)
|
||||||
@@ -250,4 +251,11 @@ class NativeDistributionCommonizer(
|
|||||||
manifestData.applyTo(library.base as BaseWriterImpl)
|
manifestData.applyTo(library.base as BaseWriterImpl)
|
||||||
library.commit()
|
library.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
val stdlibName = Name.special("<$KONAN_STDLIB_NAME>")
|
||||||
|
|
||||||
|
fun shouldBeSerialized(libraryName: Name) =
|
||||||
|
libraryName != stdlibName && libraryName != KlibResolvedModuleDescriptorsFactoryImpl.FORWARD_DECLARATIONS_MODULE_NAME
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+132
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.konan
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.StatsCollector
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.firstNonNull
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows printing commonization statistics to the file system.
|
||||||
|
*
|
||||||
|
* File format: text, "|"-separated columns.
|
||||||
|
*
|
||||||
|
* Header row: "FQ Name|Declaration Type|common|<platform1>|<platform2>[|<platformN>...]"
|
||||||
|
*
|
||||||
|
* Possible values for "Declaration Type":
|
||||||
|
* - MODULE
|
||||||
|
* - CLASS
|
||||||
|
* - INTERFACE
|
||||||
|
* - OBJECT
|
||||||
|
* - COMPANION_OBJECT
|
||||||
|
* - ENUM_CLASS
|
||||||
|
* - ENUM_ENTRY
|
||||||
|
* - TYPE_ALIAS
|
||||||
|
* - CLASS_CONSTRUCTOR
|
||||||
|
* - FUN
|
||||||
|
* - VAL
|
||||||
|
*
|
||||||
|
* Possible values for "common" column:
|
||||||
|
* - E = successfully commonized, expect declaration generated
|
||||||
|
* - "-" = no common declaration
|
||||||
|
*
|
||||||
|
* Possible values for each target platform column:
|
||||||
|
* - A = successfully commonized, actual declaration generated
|
||||||
|
* - O = not commonized, the declaration is as in the original library
|
||||||
|
* - "-" = no such declaration in the original library
|
||||||
|
*
|
||||||
|
* Example of output:
|
||||||
|
|
||||||
|
FQ Name|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 NativeStatsCollector(
|
||||||
|
private val targets: List<KonanTarget>,
|
||||||
|
destination: File
|
||||||
|
) : StatsCollector {
|
||||||
|
|
||||||
|
init {
|
||||||
|
destination.mkdirs()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val writer = destination.resolve("plain_stats.csv").printWriter()
|
||||||
|
private var headerWritten = false
|
||||||
|
|
||||||
|
override fun logStats(output: List<DeclarationDescriptor?>) {
|
||||||
|
if (!headerWritten) {
|
||||||
|
headerWritten = true
|
||||||
|
writeHeader()
|
||||||
|
}
|
||||||
|
|
||||||
|
val firstNotNull = output.firstNonNull()
|
||||||
|
val lastIsNull = output.last() == null
|
||||||
|
|
||||||
|
val row = buildString {
|
||||||
|
append((firstNotNull as? ModuleDescriptor)?.name ?: firstNotNull.fqNameSafe) // FQN (or name for module descriptor)
|
||||||
|
append(SEPARATOR)
|
||||||
|
append(firstNotNull.declarationType) // readable declaration type
|
||||||
|
append(SEPARATOR)
|
||||||
|
append(if (lastIsNull) '-' else 'E') // common
|
||||||
|
|
||||||
|
for (index in 0 until output.size - 1) {
|
||||||
|
append(SEPARATOR)
|
||||||
|
append(
|
||||||
|
when {
|
||||||
|
output[index] == null -> '-' // absent
|
||||||
|
lastIsNull -> 'O' // original (not commonized)
|
||||||
|
else -> 'A' // actual (commonized)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.println(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() = writer.close()
|
||||||
|
|
||||||
|
private fun writeHeader() {
|
||||||
|
val row = buildString {
|
||||||
|
append("FQ Name")
|
||||||
|
append(SEPARATOR)
|
||||||
|
append("Declaration Type")
|
||||||
|
append(SEPARATOR)
|
||||||
|
append("common")
|
||||||
|
|
||||||
|
targets.forEach { target ->
|
||||||
|
append(SEPARATOR)
|
||||||
|
append(target.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.println(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val SEPARATOR = '|'
|
||||||
|
|
||||||
|
private inline val DeclarationDescriptor.declarationType: String
|
||||||
|
get() = when (this) {
|
||||||
|
is ClassDescriptor -> if (isCompanionObject) "COMPANION_OBJECT" else kind.toString()
|
||||||
|
is TypeAliasDescriptor -> "TYPE_ALIAS"
|
||||||
|
is ClassConstructorDescriptor -> "CLASS_CONSTRUCTOR"
|
||||||
|
is FunctionDescriptor -> "FUN"
|
||||||
|
is PropertyDescriptor -> "VAL"
|
||||||
|
is ModuleDescriptor -> "MODULE"
|
||||||
|
else -> "UNKNOWN: ${this::class.java}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.utils
|
||||||
|
|
||||||
|
import kotlin.time.Duration
|
||||||
|
import kotlin.time.ExperimentalTime
|
||||||
|
import kotlin.time.MonoClock
|
||||||
|
|
||||||
|
@ExperimentalTime
|
||||||
|
internal class ResettableClockMark {
|
||||||
|
private val startMark = MonoClock.markNow()
|
||||||
|
private var lastMark = startMark
|
||||||
|
|
||||||
|
fun elapsedSinceLast(): Duration = lastMark.elapsedNow().also { lastMark = lastMark.plus(it) }
|
||||||
|
fun elapsedSinceStart(): Duration = startMark.elapsedNow()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user