support multithreaded compilation
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt index 73cbdf9..3100395 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/TopLevelPhases.kt
@@ -173,23 +173,39 @@ } val subfragments = splitFragment(fragment) - val moduleCompilationOutputs = subfragments.map { - backendEngine.useContext(it.generationState(generationState)) { generationStateEngine -> - val bitcodeFile = tempFiles.create(generationStateEngine.context.llvmModuleName, "${it.name}.bc").javaFile() - val objectFile = tempFiles.create(File(outputFiles.nativeBinaryFile).name, "${it.name}.o").javaFile() - val cExportFiles = if (config.produceCInterface) { - CExportFiles( - cppAdapter = tempFiles.create("api", ".cpp").javaFile(), - bitcodeAdapter = tempFiles.create("api", ".bc").javaFile(), - header = outputFiles.cAdapterHeader.javaFile(), - def = if (config.target.family == Family.MINGW) outputFiles.cAdapterDef.javaFile() else null, - ) - } else null - // TODO: Make this work if we first compile all the fragments and only after that run the link phases. - generationStateEngine.compileModule(it.module, it.files, backendContext.irBuiltIns, bitcodeFile, objectFile, cExportFiles) - ModuleCompilationOutput(listOf(objectFile), generationStateEngine.context.dependenciesTracker.collectResult()) + val threadsCount = context.config.threadsCount + val executor = Executors.newFixedThreadPool(threadsCount) + val thrownFromThread = AtomicReference<Throwable?>(null) + val tasks = subfragments.map { + Callable { + try { + backendEngine.useContext(it.generationState(generationState)) { generationStateEngine -> + val bitcodeFile = tempFiles.create(generationStateEngine.context.llvmModuleName, "${it.name}.bc").javaFile() + val objectFile = tempFiles.create(File(outputFiles.nativeBinaryFile).name, "${it.name}.o").javaFile() + val cExportFiles = if (config.produceCInterface) { + CExportFiles( + cppAdapter = tempFiles.create("api", ".cpp").javaFile(), + bitcodeAdapter = tempFiles.create("api", ".bc").javaFile(), + header = outputFiles.cAdapterHeader.javaFile(), + def = if (config.target.family == Family.MINGW) outputFiles.cAdapterDef.javaFile() else null, + ) + } else null + // TODO: Make this work if we first compile all the fragments and only after that run the link phases. + generationStateEngine.compileModule(it.module, it.files, backendContext.irBuiltIns, bitcodeFile, objectFile, cExportFiles) + ModuleCompilationOutput(listOf(objectFile), generationStateEngine.context.dependenciesTracker.collectResult()) + } + } catch (t: Throwable) { + thrownFromThread.set(t) + null + } } } + val futures = executor.invokeAll(tasks.toList()) + executor.shutdown() + executor.awaitTermination(1, TimeUnit.DAYS) + thrownFromThread.get()?.let { throw it } + + val moduleCompilationOutputs = futures.map { it.get()!! } val dependencies = DependenciesTrackingResult.merge(moduleCompilationOutputs.map { it.dependenciesTrackingResult }, context.config) val objectFiles = buildList {