IR: thread pool in PerformByIrFilePhase
This commit is contained in:
+4
-3
@@ -115,10 +115,11 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
|||||||
var doNotClearBindingContext: Boolean by FreezableVar(false)
|
var doNotClearBindingContext: Boolean by FreezableVar(false)
|
||||||
|
|
||||||
@Argument(
|
@Argument(
|
||||||
value = "-Xir-run-lowerings-in-parallel",
|
value = "-Xir-threads-for-file-lowerings",
|
||||||
description = "When using the IR backend, run lowerings for each file in parallel"
|
description = "When using the IR backend, run lowerings by file in N parallel threads.\n" +
|
||||||
|
"Default value is 1"
|
||||||
)
|
)
|
||||||
var runLoweringsInParallel: Boolean by FreezableVar(false)
|
var threadsForFileLowerings: String by FreezableVar("1")
|
||||||
|
|
||||||
@Argument(value = "-Xmodule-path", valueDescription = "<path>", description = "Paths where to find Java 9+ modules")
|
@Argument(value = "-Xmodule-path", valueDescription = "<path>", description = "Paths where to find Java 9+ modules")
|
||||||
var javaModulePath: String? by NullableStringFreezableVar(null)
|
var javaModulePath: String? by NullableStringFreezableVar(null)
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
|
|||||||
|
|
||||||
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
|
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
|
||||||
|
|
||||||
put(CommonConfigurationKeys.RUN_LOWERINGS_IN_PARALLEL, arguments.runLoweringsInParallel)
|
put(CommonConfigurationKeys.THREADS_FOR_FILE_LOWERINGS, arguments.threadsForFileLowerings.toIntOrNull() ?: 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CompilerConfiguration.configureKlibPaths(arguments: K2JVMCompilerArguments) {
|
fun CompilerConfiguration.configureKlibPaths(arguments: K2JVMCompilerArguments) {
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ object CommonConfigurationKeys {
|
|||||||
val USE_FIR_EXTENDED_CHECKERS = CompilerConfigurationKey.create<Boolean>("fir extended checkers")
|
val USE_FIR_EXTENDED_CHECKERS = CompilerConfigurationKey.create<Boolean>("fir extended checkers")
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val RUN_LOWERINGS_IN_PARALLEL =
|
val THREADS_FOR_FILE_LOWERINGS =
|
||||||
CompilerConfigurationKey.create<Boolean>("When using the IR backend, run lowerings for each file in parallel")
|
CompilerConfigurationKey.create<Int>("When using the IR backend, run lowerings by file in N parallel threads")
|
||||||
}
|
}
|
||||||
|
|
||||||
var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings
|
var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings
|
||||||
|
|||||||
+22
-14
@@ -13,8 +13,9 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import java.lang.IllegalStateException
|
import java.util.concurrent.Executors
|
||||||
import kotlin.concurrent.thread
|
import java.util.concurrent.TimeUnit
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
|
||||||
// Phase composition.
|
// Phase composition.
|
||||||
private class CompositePhase<Context : CommonBackendContext, Input, Output>(
|
private class CompositePhase<Context : CommonBackendContext, Input, Output>(
|
||||||
@@ -120,10 +121,13 @@ private class PerformByIrFilePhase<Context : CommonBackendContext>(
|
|||||||
phaserState: PhaserState<IrModuleFragment>,
|
phaserState: PhaserState<IrModuleFragment>,
|
||||||
context: Context,
|
context: Context,
|
||||||
input: IrModuleFragment
|
input: IrModuleFragment
|
||||||
): IrModuleFragment = if (context.configuration.getBoolean(CommonConfigurationKeys.RUN_LOWERINGS_IN_PARALLEL))
|
): IrModuleFragment {
|
||||||
invokeParallel(phaseConfig, phaserState, context, input)
|
val nThreads = context.configuration.get(CommonConfigurationKeys.THREADS_FOR_FILE_LOWERINGS) ?: 1
|
||||||
else
|
return if (nThreads > 1)
|
||||||
invokeSequential(phaseConfig, phaserState, context, input)
|
invokeParallel(phaseConfig, phaserState, context, input, nThreads)
|
||||||
|
else
|
||||||
|
invokeSequential(phaseConfig, phaserState, context, input)
|
||||||
|
}
|
||||||
|
|
||||||
private fun invokeSequential(
|
private fun invokeSequential(
|
||||||
phaseConfig: PhaseConfig, phaserState: PhaserState<IrModuleFragment>, context: Context, input: IrModuleFragment
|
phaseConfig: PhaseConfig, phaserState: PhaserState<IrModuleFragment>, context: Context, input: IrModuleFragment
|
||||||
@@ -144,31 +148,35 @@ private class PerformByIrFilePhase<Context : CommonBackendContext>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun invokeParallel(
|
private fun invokeParallel(
|
||||||
phaseConfig: PhaseConfig, phaserState: PhaserState<IrModuleFragment>, context: Context, input: IrModuleFragment
|
phaseConfig: PhaseConfig, phaserState: PhaserState<IrModuleFragment>, context: Context, input: IrModuleFragment, nThreads: Int
|
||||||
): IrModuleFragment {
|
): IrModuleFragment {
|
||||||
if (input.files.isEmpty()) return input
|
if (input.files.isEmpty()) return input
|
||||||
|
|
||||||
// We can only report one exception through ISE
|
// We can only report one exception through ISE
|
||||||
var thrownFromThread: Throwable? = null
|
val thrownFromThread = AtomicReference<Pair<Throwable, IrFile>?>(null)
|
||||||
|
|
||||||
// Each thread needs its own copy of phaserState.alreadyDone
|
// Each thread needs its own copy of phaserState.alreadyDone
|
||||||
val filesAndStates = input.files.map { it to phaserState.clone() }
|
val filesAndStates = input.files.map { it to phaserState.clone() }
|
||||||
val threads = filesAndStates.map { (irFile, state) ->
|
|
||||||
thread {
|
val executor = Executors.newFixedThreadPool(nThreads)
|
||||||
|
for ((irFile, state) in filesAndStates) {
|
||||||
|
executor.execute {
|
||||||
try {
|
try {
|
||||||
val filePhaserState = state.changeType<IrModuleFragment, IrFile>()
|
val filePhaserState = state.changeType<IrModuleFragment, IrFile>()
|
||||||
for (phase in lower) {
|
for (phase in lower) {
|
||||||
phase.invoke(phaseConfig, filePhaserState, context, irFile)
|
phase.invoke(phaseConfig, filePhaserState, context, irFile)
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
thrownFromThread = e
|
thrownFromThread.set(Pair(e, irFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
executor.shutdown()
|
||||||
|
executor.awaitTermination(1, TimeUnit.DAYS) // Wait long enough
|
||||||
|
|
||||||
threads.forEach { it.join() }
|
thrownFromThread.get()?.let { (e, irFile) ->
|
||||||
|
CodegenUtil.reportBackendException(e, "IrLowering", irFile.fileEntry.name)
|
||||||
if (thrownFromThread != null) throw IllegalStateException("Exception in file lowering", thrownFromThread)
|
}
|
||||||
|
|
||||||
// Presumably each thread has run through the same list of phases.
|
// Presumably each thread has run through the same list of phases.
|
||||||
phaserState.alreadyDone.addAll(filesAndStates[0].second.alreadyDone)
|
phaserState.alreadyDone.addAll(filesAndStates[0].second.alreadyDone)
|
||||||
|
|||||||
+3
-1
@@ -99,7 +99,6 @@ where advanced options include:
|
|||||||
-Xsam-conversions={class|indy} Select code generation scheme for SAM conversions.
|
-Xsam-conversions={class|indy} Select code generation scheme for SAM conversions.
|
||||||
-Xsam-conversions=indy Generate SAM conversions using `invokedynamic` with `LambdaMetafactory.metafactory`. Requires `-jvm-target 1.8` or greater.
|
-Xsam-conversions=indy Generate SAM conversions using `invokedynamic` with `LambdaMetafactory.metafactory`. Requires `-jvm-target 1.8` or greater.
|
||||||
-Xsam-conversions=class Generate SAM conversions as explicit classes
|
-Xsam-conversions=class Generate SAM conversions as explicit classes
|
||||||
-Xir-run-lowerings-in-parallel When using the IR backend, run lowerings for each file in parallel
|
|
||||||
-Xsanitize-parentheses Transform '(' and ')' in method names to some other character sequence.
|
-Xsanitize-parentheses Transform '(' and ')' in method names to some other character sequence.
|
||||||
This mode can BREAK BINARY COMPATIBILITY and is only supposed to be used to workaround
|
This mode can BREAK BINARY COMPATIBILITY and is only supposed to be used to workaround
|
||||||
problems with parentheses in identifiers on certain platforms
|
problems with parentheses in identifiers on certain platforms
|
||||||
@@ -123,6 +122,9 @@ where advanced options include:
|
|||||||
Suppress deprecation warning about deprecated JVM target versions
|
Suppress deprecation warning about deprecated JVM target versions
|
||||||
-Xsuppress-missing-builtins-error
|
-Xsuppress-missing-builtins-error
|
||||||
Suppress the "cannot access built-in declaration" error (useful with -no-stdlib)
|
Suppress the "cannot access built-in declaration" error (useful with -no-stdlib)
|
||||||
|
-Xir-threads-for-file-lowerings
|
||||||
|
When using the IR backend, run lowerings by file in N parallel threads.
|
||||||
|
Default value is 1
|
||||||
-Xuse-ir Use the IR backend
|
-Xuse-ir Use the IR backend
|
||||||
-Xuse-javac Use javac for Java source and class files analysis
|
-Xuse-javac Use javac for Java source and class files analysis
|
||||||
-Xuse-old-backend Use the old JVM backend
|
-Xuse-old-backend Use the old JVM backend
|
||||||
|
|||||||
Reference in New Issue
Block a user