[K/N][IR][codegen] Lazy initialization fix for new GC

A mutable field should be registered in GC even if its initializer is a const
This commit is contained in:
Igor Chevdar
2021-08-18 17:45:25 +05:00
parent af59955566
commit a576160847
2 changed files with 12 additions and 7 deletions
@@ -70,6 +70,12 @@ internal val IrField.storageKind: FieldStorageKind get() {
}
}
internal fun IrField.needsGCRegistration(context: Context) =
context.memoryModel == MemoryModel.EXPERIMENTAL && // only for the new MM
type.binaryTypeIsReference() && // only for references
(initializer?.expression !is IrConst<*>? || // which are initialized from heap object
!isFinal) // or are not final
internal fun IrClass.storageKind(context: Context): ObjectStorageKind = when {
this.annotations.hasAnnotation(KonanFqNames.threadLocal) &&
context.config.threadsAreAllowed -> ObjectStorageKind.THREAD_LOCAL
@@ -341,12 +347,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
} else {
null
}
val needRegistration =
context.memoryModel == MemoryModel.EXPERIMENTAL && // only for the new MM
irField.type.binaryTypeIsReference() && // only for references
(initialValue != null || // which are initialized from heap object
!irField.isFinal) // or are not final
if (needRegistration) {
if (irField.needsGCRegistration(context)) {
call(context.llvm.initAndRegisterGlobalFunction, listOf(address, initialValue
?: kNullObjHeaderPtr))
} else if (initialValue != null) {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanFqNames
import org.jetbrains.kotlin.backend.konan.llvm.FieldStorageKind
import org.jetbrains.kotlin.backend.konan.llvm.needsGCRegistration
import org.jetbrains.kotlin.backend.konan.llvm.storageKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrStatement
@@ -55,7 +56,7 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass
var kPropertiesField: IrField? = null
for (declaration in irFile.declarations) {
val irField = (declaration as? IrField) ?: (declaration as? IrProperty)?.backingField
if (irField == null || !irField.hasNonConstInitializer || irField.shouldBeInitializedEagerly) continue
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" }
@@ -133,6 +134,9 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass
irFile.declarations.add(0, this)
}
private val IrField.needsInitializationAtRuntime: Boolean
get() = hasNonConstInitializer || needsGCRegistration(context)
private val IrField.hasNonConstInitializer: Boolean
get() = initializer?.expression.let { it != null && it !is IrConst<*> }
}