[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:
+7
-6
@@ -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) {
|
||||
|
||||
+5
-1
@@ -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<*> }
|
||||
}
|
||||
Reference in New Issue
Block a user