mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
[K/N] Enable lazy property initialization with the new MM
This commit is contained in:
committed by
Space
parent
b5fa129540
commit
a7460e9061
@@ -328,7 +328,20 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
|||||||
RuntimeAssertsMode.IGNORE
|
RuntimeAssertsMode.IGNORE
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
put(PROPERTY_LAZY_INITIALIZATION, arguments.propertyLazyInitialization)
|
put(PROPERTY_LAZY_INITIALIZATION, when (arguments.propertyLazyInitialization) {
|
||||||
|
null -> {
|
||||||
|
when (memoryModel) {
|
||||||
|
MemoryModel.EXPERIMENTAL -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"enable" -> true
|
||||||
|
"disable" -> false
|
||||||
|
else -> {
|
||||||
|
configuration.report(ERROR, "Expected 'enable' or 'disable' for lazy property initialization")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
put(WORKER_EXCEPTION_HANDLING, when (arguments.workerExceptionHandling) {
|
put(WORKER_EXCEPTION_HANDLING, when (arguments.workerExceptionHandling) {
|
||||||
null -> if (memoryModel == MemoryModel.EXPERIMENTAL) WorkerExceptionHandling.USE_HOOK else WorkerExceptionHandling.LEGACY
|
null -> if (memoryModel == MemoryModel.EXPERIMENTAL) WorkerExceptionHandling.USE_HOOK else WorkerExceptionHandling.LEGACY
|
||||||
"legacy" -> WorkerExceptionHandling.LEGACY
|
"legacy" -> WorkerExceptionHandling.LEGACY
|
||||||
|
|||||||
@@ -323,8 +323,8 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
|||||||
@Argument(value="-Xgc-aggressive", description = "Make GC agressive. Works only with -memory-model experimental")
|
@Argument(value="-Xgc-aggressive", description = "Make GC agressive. Works only with -memory-model experimental")
|
||||||
var gcAggressive: Boolean = false
|
var gcAggressive: Boolean = false
|
||||||
|
|
||||||
@Argument(value = "-Xir-property-lazy-initialization", description = "Initialize top level properties lazily per file")
|
@Argument(value = "-Xir-property-lazy-initialization", valueDescription = "{disable|enable}", description = "Initialize top level properties lazily per file")
|
||||||
var propertyLazyInitialization: Boolean = false
|
var propertyLazyInitialization: String? = null
|
||||||
|
|
||||||
@Argument(value="-Xruntime-asserts-mode", valueDescription = "<mode>", description = "Enable asserts in runtime. Possible values: 'ignore', 'log', 'panic'")
|
@Argument(value="-Xruntime-asserts-mode", valueDescription = "<mode>", description = "Enable asserts in runtime. Possible values: 'ignore', 'log', 'panic'")
|
||||||
var runtimeAssertsMode: String? = "ignore"
|
var runtimeAssertsMode: String? = "ignore"
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
internal object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION : IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION")
|
|
||||||
|
|
||||||
internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass {
|
internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass {
|
||||||
private var tempIndex = 0
|
private var tempIndex = 0
|
||||||
|
|
||||||
@@ -292,4 +290,6 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
|||||||
}
|
}
|
||||||
return type.classifier == expectedClass
|
return type.classifier == expectedClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION : IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,25 +53,19 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass
|
|||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
var requireGlobalInitializer = false
|
var requireGlobalInitializer = false
|
||||||
var requireThreadLocalInitializer = false
|
var requireThreadLocalInitializer = false
|
||||||
var kPropertiesField: IrField? = null
|
|
||||||
for (declaration in irFile.declarations) {
|
for (declaration in irFile.declarations) {
|
||||||
val irField = (declaration as? IrField) ?: (declaration as? IrProperty)?.backingField
|
val irField = (declaration as? IrField) ?: (declaration as? IrProperty)?.backingField
|
||||||
if (irField == null || !irField.needsInitializationAtRuntime || irField.shouldBeInitializedEagerly) continue
|
if (irField == null || !irField.needsInitializationAtRuntime || irField.shouldBeInitializedEagerly) continue
|
||||||
when {
|
if (irField.storageKind == FieldStorageKind.SHARED_FROZEN) {
|
||||||
irField.origin == DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION -> {
|
requireGlobalInitializer = true
|
||||||
require(kPropertiesField == null) { "Expected at most one kProperties field" }
|
} else {
|
||||||
kPropertiesField = irField
|
requireThreadLocalInitializer = true // Either marked with thread local or only main thread visible.
|
||||||
}
|
|
||||||
irField.storageKind == FieldStorageKind.SHARED_FROZEN -> requireGlobalInitializer = true
|
|
||||||
else -> requireThreadLocalInitializer = true // Either marked with thread local or only main thread visible.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: think about pure initializers.
|
// TODO: think about pure initializers.
|
||||||
if (!requireGlobalInitializer && !requireThreadLocalInitializer) {
|
if (!requireGlobalInitializer && !requireThreadLocalInitializer) {
|
||||||
kPropertiesField?.let { transformKPropertiesInitializerToModuleInitializer(irFile, it) }
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
kPropertiesField?.let { requireGlobalInitializer = true }
|
|
||||||
|
|
||||||
val globalInitFunction =
|
val globalInitFunction =
|
||||||
if (requireGlobalInitializer)
|
if (requireGlobalInitializer)
|
||||||
@@ -102,25 +96,6 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformKPropertiesInitializerToModuleInitializer(irFile: IrFile, irField: IrField) {
|
|
||||||
val initializer = context.irFactory.buildFun {
|
|
||||||
startOffset = irField.startOffset
|
|
||||||
endOffset = irField.endOffset
|
|
||||||
origin = DECLARATION_ORIGIN_MODULE_GLOBAL_INITIALIZER
|
|
||||||
name = Name.identifier("\$kProperties_init")
|
|
||||||
visibility = DescriptorVisibilities.PRIVATE
|
|
||||||
returnType = context.irBuiltIns.unitType
|
|
||||||
}.apply {
|
|
||||||
val function = this
|
|
||||||
parent = irFile
|
|
||||||
body = context.createIrBuilder(symbol, startOffset, endOffset).irBlockBody {
|
|
||||||
+irSetField(null, irField, irField.initializer!!.expression.also { it.setDeclarationsParent(function) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
irField.initializer = null
|
|
||||||
irFile.declarations.add(initializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildInitFileFunction(irFile: IrFile, name: String, origin: IrDeclarationOrigin) = context.irFactory.buildFun {
|
private fun buildInitFileFunction(irFile: IrFile, name: String, origin: IrDeclarationOrigin) = context.irFactory.buildFun {
|
||||||
startOffset = SYNTHETIC_OFFSET
|
startOffset = SYNTHETIC_OFFSET
|
||||||
endOffset = SYNTHETIC_OFFSET
|
endOffset = SYNTHETIC_OFFSET
|
||||||
@@ -139,4 +114,4 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass
|
|||||||
|
|
||||||
private val IrField.hasNonConstInitializer: Boolean
|
private val IrField.hasNonConstInitializer: Boolean
|
||||||
get() = initializer?.expression.let { it != null && it !is IrConst<*> }
|
get() = initializer?.expression.let { it != null && it !is IrConst<*> }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1486,22 +1486,22 @@ standaloneTest("initializers_globalInitedBeforeThreadLocal") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
standaloneTest("initializers_eagerInitializationGlobal1") {
|
standaloneTest("initializers_eagerInitializationGlobal1") {
|
||||||
enabled = project.globalTestArgs.contains('-Xir-property-lazy-initialization')
|
enabled = project.globalTestArgs.contains('-Xir-property-lazy-initialization=enable') || isExperimentalMM
|
||||||
source = "codegen/initializers/eagerInitializationGlobal1.kt"
|
source = "codegen/initializers/eagerInitializationGlobal1.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
standaloneTest("initializers_eagerInitializationGlobal2") {
|
standaloneTest("initializers_eagerInitializationGlobal2") {
|
||||||
enabled = project.globalTestArgs.contains('-Xir-property-lazy-initialization')
|
enabled = project.globalTestArgs.contains('-Xir-property-lazy-initialization=enable') || isExperimentalMM
|
||||||
source = "codegen/initializers/eagerInitializationGlobal2.kt"
|
source = "codegen/initializers/eagerInitializationGlobal2.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
standaloneTest("initializers_eagerInitializationThreadLocal1") {
|
standaloneTest("initializers_eagerInitializationThreadLocal1") {
|
||||||
enabled = project.globalTestArgs.contains('-Xir-property-lazy-initialization')
|
enabled = project.globalTestArgs.contains('-Xir-property-lazy-initialization=enable') || isExperimentalMM
|
||||||
source = "codegen/initializers/eagerInitializationThreadLocal1.kt"
|
source = "codegen/initializers/eagerInitializationThreadLocal1.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
standaloneTest("initializers_eagerInitializationThreadLocal2") {
|
standaloneTest("initializers_eagerInitializationThreadLocal2") {
|
||||||
enabled = project.globalTestArgs.contains('-Xir-property-lazy-initialization')
|
enabled = project.globalTestArgs.contains('-Xir-property-lazy-initialization=enable') || isExperimentalMM
|
||||||
source = "codegen/initializers/eagerInitializationThreadLocal2.kt"
|
source = "codegen/initializers/eagerInitializationThreadLocal2.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1521,28 +1521,28 @@ standaloneTest("initializers_failInInitializer1") {
|
|||||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||||
source = "codegen/initializers/failInInitializer1.kt"
|
source = "codegen/initializers/failInInitializer1.kt"
|
||||||
goldValue = "caught\n"
|
goldValue = "caught\n"
|
||||||
flags = ['-Xir-property-lazy-initialization']
|
flags = ['-Xir-property-lazy-initialization=enable']
|
||||||
}
|
}
|
||||||
|
|
||||||
standaloneTest("initializers_failInInitializer2") {
|
standaloneTest("initializers_failInInitializer2") {
|
||||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||||
source = "codegen/initializers/failInInitializer2.kt"
|
source = "codegen/initializers/failInInitializer2.kt"
|
||||||
goldValue = "caught\ncaught2\n"
|
goldValue = "caught\ncaught2\n"
|
||||||
flags = ['-Xir-property-lazy-initialization']
|
flags = ['-Xir-property-lazy-initialization=enable']
|
||||||
}
|
}
|
||||||
|
|
||||||
standaloneTest("initializers_failInInitializer3") {
|
standaloneTest("initializers_failInInitializer3") {
|
||||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||||
source = "codegen/initializers/failInInitializer3.kt"
|
source = "codegen/initializers/failInInitializer3.kt"
|
||||||
goldValue = "caught\ncaught2\n"
|
goldValue = "caught\ncaught2\n"
|
||||||
flags = ['-Xir-property-lazy-initialization']
|
flags = ['-Xir-property-lazy-initialization=enable']
|
||||||
}
|
}
|
||||||
|
|
||||||
standaloneTest("initializers_failInInitializer4") {
|
standaloneTest("initializers_failInInitializer4") {
|
||||||
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
|
||||||
source = "codegen/initializers/failInInitializer4.kt"
|
source = "codegen/initializers/failInInitializer4.kt"
|
||||||
goldValue = "caught\ncaught2\n"
|
goldValue = "caught\ncaught2\n"
|
||||||
flags = ['-Xir-property-lazy-initialization']
|
flags = ['-Xir-property-lazy-initialization=enable']
|
||||||
}
|
}
|
||||||
|
|
||||||
standaloneTest("initializers_when1") {
|
standaloneTest("initializers_when1") {
|
||||||
@@ -2367,7 +2367,7 @@ standaloneTest("link_testLib_explicitly") {
|
|||||||
enabled = project.target.name == project.hostName
|
enabled = project.target.name == project.hostName
|
||||||
|
|
||||||
dependsOn installTestLib
|
dependsOn installTestLib
|
||||||
if (project.globalTestArgs.contains('-Xir-property-lazy-initialization'))
|
if (project.globalTestArgs.contains('-Xir-property-lazy-initialization=enable') || isExperimentalMM)
|
||||||
goldValue = "Hello\n"
|
goldValue = "Hello\n"
|
||||||
else
|
else
|
||||||
goldValue = "This is a side effect of a test library linked into the binary.\nYou should not be seeing this.\n\nHello\n"
|
goldValue = "This is a side effect of a test library linked into the binary.\nYou should not be seeing this.\n\nHello\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user