[K/N] Enable lazy property initialization with the new MM

This commit is contained in:
Alexander Shabalin
2021-08-19 18:23:01 +00:00
committed by Space
parent b5fa129540
commit a7460e9061
5 changed files with 32 additions and 44 deletions

View File

@@ -328,7 +328,20 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
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) {
null -> if (memoryModel == MemoryModel.EXPERIMENTAL) WorkerExceptionHandling.USE_HOOK else WorkerExceptionHandling.LEGACY
"legacy" -> WorkerExceptionHandling.LEGACY

View File

@@ -323,8 +323,8 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
@Argument(value="-Xgc-aggressive", description = "Make GC agressive. Works only with -memory-model experimental")
var gcAggressive: Boolean = false
@Argument(value = "-Xir-property-lazy-initialization", description = "Initialize top level properties lazily per file")
var propertyLazyInitialization: Boolean = false
@Argument(value = "-Xir-property-lazy-initialization", valueDescription = "{disable|enable}", description = "Initialize top level properties lazily per file")
var propertyLazyInitialization: String? = null
@Argument(value="-Xruntime-asserts-mode", valueDescription = "<mode>", description = "Enable asserts in runtime. Possible values: 'ignore', 'log', 'panic'")
var runtimeAssertsMode: String? = "ignore"

View File

@@ -29,8 +29,6 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
internal object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION : IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION")
internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass {
private var tempIndex = 0
@@ -292,4 +290,6 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
}
return type.classifier == expectedClass
}
private object DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION : IrDeclarationOriginImpl("KPROPERTIES_FOR_DELEGATION")
}

View File

@@ -53,25 +53,19 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass
override fun lower(irFile: IrFile) {
var requireGlobalInitializer = false
var requireThreadLocalInitializer = false
var kPropertiesField: IrField? = null
for (declaration in irFile.declarations) {
val irField = (declaration as? IrField) ?: (declaration as? IrProperty)?.backingField
if (irField == null || !irField.needsInitializationAtRuntime || irField.shouldBeInitializedEagerly) continue
when {
irField.origin == DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION -> {
require(kPropertiesField == null) { "Expected at most one kProperties field" }
kPropertiesField = irField
}
irField.storageKind == FieldStorageKind.SHARED_FROZEN -> requireGlobalInitializer = true
else -> requireThreadLocalInitializer = true // Either marked with thread local or only main thread visible.
if (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.
if (!requireGlobalInitializer && !requireThreadLocalInitializer) {
kPropertiesField?.let { transformKPropertiesInitializerToModuleInitializer(irFile, it) }
return
}
kPropertiesField?.let { requireGlobalInitializer = true }
val globalInitFunction =
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 {
startOffset = SYNTHETIC_OFFSET
endOffset = SYNTHETIC_OFFSET
@@ -139,4 +114,4 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass
private val IrField.hasNonConstInitializer: Boolean
get() = initializer?.expression.let { it != null && it !is IrConst<*> }
}
}

View File

@@ -1486,22 +1486,22 @@ standaloneTest("initializers_globalInitedBeforeThreadLocal") {
}
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"
}
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"
}
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"
}
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"
}
@@ -1521,28 +1521,28 @@ standaloneTest("initializers_failInInitializer1") {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
source = "codegen/initializers/failInInitializer1.kt"
goldValue = "caught\n"
flags = ['-Xir-property-lazy-initialization']
flags = ['-Xir-property-lazy-initialization=enable']
}
standaloneTest("initializers_failInInitializer2") {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
source = "codegen/initializers/failInInitializer2.kt"
goldValue = "caught\ncaught2\n"
flags = ['-Xir-property-lazy-initialization']
flags = ['-Xir-property-lazy-initialization=enable']
}
standaloneTest("initializers_failInInitializer3") {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
source = "codegen/initializers/failInInitializer3.kt"
goldValue = "caught\ncaught2\n"
flags = ['-Xir-property-lazy-initialization']
flags = ['-Xir-property-lazy-initialization=enable']
}
standaloneTest("initializers_failInInitializer4") {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
source = "codegen/initializers/failInInitializer4.kt"
goldValue = "caught\ncaught2\n"
flags = ['-Xir-property-lazy-initialization']
flags = ['-Xir-property-lazy-initialization=enable']
}
standaloneTest("initializers_when1") {
@@ -2367,7 +2367,7 @@ standaloneTest("link_testLib_explicitly") {
enabled = project.target.name == project.hostName
dependsOn installTestLib
if (project.globalTestArgs.contains('-Xir-property-lazy-initialization'))
if (project.globalTestArgs.contains('-Xir-property-lazy-initialization=enable') || isExperimentalMM)
goldValue = "Hello\n"
else
goldValue = "This is a side effect of a test library linked into the binary.\nYou should not be seeing this.\n\nHello\n"