diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt index 6749700930e2c..cc294508bc739 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.konan.llvm.objcexport.ObjCExportCodeGenerato import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageUtil import org.jetbrains.kotlin.config.nativeBinaryOptions.BinaryOptions +import org.jetbrains.kotlin.config.parallelBackendThreads import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.konan.exec.Command import org.jetbrains.kotlin.konan.file.File @@ -85,7 +86,7 @@ internal fun produceObjCExportInterface( val additionalImports = context.config.configuration.getNotNull(KonanConfigKeys.FRAMEWORK_IMPORT_HEADERS) val headerGenerator = ObjCExportHeaderGenerator.createInstance( moduleDescriptors, mapper, namer, problemCollector, objcGenerics, objcExportBlockExplicitParameterNames, shouldExportKDoc = shouldExportKDoc, - additionalImports = additionalImports) + additionalImports = additionalImports, config.threadsCount) headerGenerator.translateModule() return headerGenerator.buildInterface() } diff --git a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt index 1b60e07c1b579..95a34e461ee7c 100644 --- a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt +++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt @@ -14,6 +14,9 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.SourceFile import org.jetbrains.kotlin.resolve.scopes.MemberScope +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit +import java.util.Collections.synchronizedList abstract class ObjCExportHeaderGenerator @InternalKotlinNativeApi constructor( val moduleDescriptors: List, @@ -22,6 +25,7 @@ abstract class ObjCExportHeaderGenerator @InternalKotlinNativeApi constructor( val objcGenerics: Boolean, val objcExportBlockExplicitParameterNames: Boolean, problemCollector: ObjCExportProblemCollector, + val threadsCount: Int = Runtime.getRuntime().availableProcessors() ) { private val stubs = mutableListOf() @@ -117,31 +121,49 @@ abstract class ObjCExportHeaderGenerator @InternalKotlinNativeApi constructor( .flatMap { it.getPackageFragments() } .makePackagesOrderStable() + val classesToTranslate = synchronizedList(mutableListOf()) + + val executor = if (threadsCount > 1) { + Executors.newFixedThreadPool(threadsCount) + } else { + null + } + + packageFragments.forEach { packageFragment -> - packageFragment.getMemberScope().getContributedDescriptors() + val memberScope = packageFragment.getMemberScope() + + val task = { + memberScope.getContributedDescriptors() .asSequence() .filterIsInstance() .filter { mapper.shouldBeExposed(it) } .forEach { val classDescriptor = getClassIfCategory(it) if (classDescriptor == null) { - topLevel.getOrPut(it.findSourceFile(), { mutableListOf() }) += it + synchronized(topLevel) { + topLevel.getOrPut(it.findSourceFile(), { mutableListOf() }) += it + } } else { // If a class is hidden from Objective-C API then it is meaningless // to export its extensions. if (!classDescriptor.isHiddenFromObjC()) { - extensions.getOrPut(classDescriptor, { mutableListOf() }) += it + synchronized(extensions) { + extensions.getOrPut(classDescriptor, { mutableListOf() }) += it + } } } } - } + } - val classesToTranslate = mutableListOf() + executor?.submit(task) ?: task() - packageFragments.forEach { packageFragment -> - packageFragment.getMemberScope().collectClasses(classesToTranslate) + memberScope.collectClasses(classesToTranslate) } + executor?.shutdown() + executor?.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS) + classesToTranslate.makeClassesOrderStable().forEach { translateClass(it) } extensions.makeCategoriesOrderStable().forEach { (classDescriptor, declarations) -> @@ -247,6 +269,7 @@ abstract class ObjCExportHeaderGenerator @InternalKotlinNativeApi constructor( objcExportBlockExplicitParameterNames: Boolean, shouldExportKDoc: Boolean, additionalImports: List, + threadsCount: Int ): ObjCExportHeaderGenerator = ObjCExportHeaderGeneratorImpl( moduleDescriptors, mapper, @@ -255,7 +278,8 @@ abstract class ObjCExportHeaderGenerator @InternalKotlinNativeApi constructor( objcGenerics, objcExportBlockExplicitParameterNames, shouldExportKDoc, - additionalImports + additionalImports, + threadsCount ) } } diff --git a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt index 12e03be29e2e9..f290df3f9231a 100644 --- a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt +++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGeneratorImpl.kt @@ -16,7 +16,16 @@ internal class ObjCExportHeaderGeneratorImpl( objcExportBlockExplicitParameterNames: Boolean, override val shouldExportKDoc: Boolean, private val additionalImports: List, -) : ObjCExportHeaderGenerator(moduleDescriptors, mapper, namer, objcGenerics, objcExportBlockExplicitParameterNames, problemCollector) { + threadsCount: Int, +) : ObjCExportHeaderGenerator( + moduleDescriptors, + mapper, + namer, + objcGenerics, + objcExportBlockExplicitParameterNames, + problemCollector, + threadsCount +) { override fun getAdditionalImports(): List = additionalImports } diff --git a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt index 5bcda8abcf268..7c67d8cb68a08 100644 --- a/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt +++ b/native/objcexport-header-generator/impl/k1/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjcExportHeaderGeneratorMobile.kt @@ -19,7 +19,16 @@ class ObjcExportHeaderGeneratorMobile internal constructor( objcGenerics: Boolean, objcExportBlockExplicitParameterNames: Boolean, private val restrictToLocalModules: Boolean, -) : ObjCExportHeaderGenerator(moduleDescriptors, mapper, namer, objcGenerics, objcExportBlockExplicitParameterNames, problemCollector) { + threadsCount: Int, +) : ObjCExportHeaderGenerator( + moduleDescriptors, + mapper, + namer, + objcGenerics, + objcExportBlockExplicitParameterNames, + problemCollector, + threadsCount +) { companion object { fun createInstance( @@ -30,6 +39,7 @@ class ObjcExportHeaderGeneratorMobile internal constructor( deprecationResolver: DeprecationResolver? = null, local: Boolean = false, restrictToLocalModules: Boolean = false, + threadsCount: Int = Runtime.getRuntime().availableProcessors(), ): ObjCExportHeaderGenerator { val mapper = ObjCExportMapper(deprecationResolver, local, configuration.unitSuspendFunctionExport, configuration.entryPoints) val namerConfiguration = createNamerConfiguration(configuration) @@ -42,7 +52,8 @@ class ObjcExportHeaderGeneratorMobile internal constructor( problemCollector, configuration.objcGenerics, configuration.objcExportBlockExplicitParameterNames, - restrictToLocalModules + restrictToLocalModules, + threadsCount, ) } }