Clarify field storage. (#1957)
This commit is contained in:
+33
-17
@@ -19,11 +19,13 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|||||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin
|
import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.SourceManager
|
import org.jetbrains.kotlin.ir.SourceManager
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
@@ -41,24 +43,38 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
|||||||
private val threadLocalAnnotationFqName = FqName("kotlin.native.ThreadLocal")
|
private val threadLocalAnnotationFqName = FqName("kotlin.native.ThreadLocal")
|
||||||
private val sharedAnnotationFqName = FqName("kotlin.native.SharedImmutable")
|
private val sharedAnnotationFqName = FqName("kotlin.native.SharedImmutable")
|
||||||
|
|
||||||
|
|
||||||
|
val IrField.propertyDescriptor: PropertyDescriptor
|
||||||
|
get() {
|
||||||
|
val descriptor = this.descriptor
|
||||||
|
return if (descriptor is IrPropertyDelegateDescriptor)
|
||||||
|
descriptor.correspondingProperty
|
||||||
|
else
|
||||||
|
descriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum class FieldStorage {
|
||||||
|
MAIN_THREAD,
|
||||||
|
SHARED,
|
||||||
|
THREAD_LOCAL
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: maybe unannotated singleton objects shall be accessed from main thread only as well?
|
// TODO: maybe unannotated singleton objects shall be accessed from main thread only as well?
|
||||||
val IrClass.objectIsShared get() =
|
val IrClass.objectIsShared get() =
|
||||||
!descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName)
|
!descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName)
|
||||||
|
|
||||||
val IrField.isThreadLocal get() =
|
internal val IrField.storageClass: FieldStorage get() {
|
||||||
descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName)
|
val descriptor = propertyDescriptor
|
||||||
|
return when {
|
||||||
val IrField.isShared get() =
|
descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName) -> FieldStorage.THREAD_LOCAL
|
||||||
descriptor.annotations.hasAnnotation(sharedAnnotationFqName)
|
descriptor.annotations.hasAnnotation(sharedAnnotationFqName) -> FieldStorage.SHARED
|
||||||
|
else -> FieldStorage.MAIN_THREAD
|
||||||
val IrField.isMainOnly get() =
|
}
|
||||||
!descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName) &&
|
}
|
||||||
!descriptor.annotations.hasAnnotation(sharedAnnotationFqName) &&
|
|
||||||
!descriptor.isDelegated
|
|
||||||
|
|
||||||
val IrField.isMainOnlyNonPrimitive get() = when {
|
val IrField.isMainOnlyNonPrimitive get() = when {
|
||||||
KotlinBuiltIns.isPrimitiveType(descriptor.type) -> false
|
KotlinBuiltIns.isPrimitiveType(descriptor.type) -> false
|
||||||
else -> isMainOnly
|
else -> storageClass == FieldStorage.MAIN_THREAD
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun emitLLVM(context: Context, phaser: PhaseManager) {
|
internal fun emitLLVM(context: Context, phaser: PhaseManager) {
|
||||||
@@ -409,10 +425,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
context.llvm.fileInitializers
|
context.llvm.fileInitializers
|
||||||
.forEach {
|
.forEach {
|
||||||
if (it.initializer?.expression !is IrConst<*>?) {
|
if (it.initializer?.expression !is IrConst<*>?) {
|
||||||
if (!it.isThreadLocal) {
|
if (it.storageClass != FieldStorage.THREAD_LOCAL) {
|
||||||
val initialization = evaluateExpression(it.initializer!!.expression)
|
val initialization = evaluateExpression(it.initializer!!.expression)
|
||||||
val address = context.llvmDeclarations.forStaticField(it).storage
|
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||||
if (it.isShared)
|
if (it.storageClass == FieldStorage.SHARED)
|
||||||
freeze(initialization, currentCodeContext.exceptionHandler)
|
freeze(initialization, currentCodeContext.exceptionHandler)
|
||||||
storeAny(initialization, address)
|
storeAny(initialization, address)
|
||||||
}
|
}
|
||||||
@@ -425,7 +441,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
context.llvm.fileInitializers
|
context.llvm.fileInitializers
|
||||||
.forEach {
|
.forEach {
|
||||||
if (it.initializer?.expression !is IrConst<*>?) {
|
if (it.initializer?.expression !is IrConst<*>?) {
|
||||||
if (it.isThreadLocal) {
|
if (it.storageClass == FieldStorage.THREAD_LOCAL) {
|
||||||
val initialization = evaluateExpression(it.initializer!!.expression)
|
val initialization = evaluateExpression(it.initializer!!.expression)
|
||||||
val address = context.llvmDeclarations.forStaticField(it).storage
|
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||||
storeAny(initialization, address)
|
storeAny(initialization, address)
|
||||||
@@ -438,7 +454,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
appendingTo(bbLocalDeinit) {
|
appendingTo(bbLocalDeinit) {
|
||||||
context.llvm.fileInitializers.forEach {
|
context.llvm.fileInitializers.forEach {
|
||||||
// Only if a subject for memory management.
|
// Only if a subject for memory management.
|
||||||
if (it.type.binaryTypeIsReference() && it.isThreadLocal) {
|
if (it.type.binaryTypeIsReference() && it.storageClass == FieldStorage.THREAD_LOCAL) {
|
||||||
val address = context.llvmDeclarations.forStaticField(it).storage
|
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||||
storeAny(codegen.kNullObjHeaderPtr, address)
|
storeAny(codegen.kNullObjHeaderPtr, address)
|
||||||
}
|
}
|
||||||
@@ -451,7 +467,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
context.llvm.fileInitializers
|
context.llvm.fileInitializers
|
||||||
// Only if a subject for memory management.
|
// Only if a subject for memory management.
|
||||||
.forEach {
|
.forEach {
|
||||||
if (it.type.binaryTypeIsReference() && !it.isThreadLocal) {
|
if (it.type.binaryTypeIsReference() && it.storageClass != FieldStorage.THREAD_LOCAL) {
|
||||||
val address = context.llvmDeclarations.forStaticField(it).storage
|
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||||
storeAny(codegen.kNullObjHeaderPtr, address)
|
storeAny(codegen.kNullObjHeaderPtr, address)
|
||||||
}
|
}
|
||||||
@@ -1467,7 +1483,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val globalValue = context.llvmDeclarations.forStaticField(value.symbol.owner).storage
|
val globalValue = context.llvmDeclarations.forStaticField(value.symbol.owner).storage
|
||||||
if (context.config.threadsAreAllowed && value.symbol.owner.isMainOnlyNonPrimitive)
|
if (context.config.threadsAreAllowed && value.symbol.owner.isMainOnlyNonPrimitive)
|
||||||
functionGenerationContext.checkMainThread(currentCodeContext.exceptionHandler)
|
functionGenerationContext.checkMainThread(currentCodeContext.exceptionHandler)
|
||||||
if (value.symbol.owner.isShared)
|
if (value.symbol.owner.storageClass == FieldStorage.SHARED)
|
||||||
functionGenerationContext.freeze(valueToAssign, currentCodeContext.exceptionHandler)
|
functionGenerationContext.freeze(valueToAssign, currentCodeContext.exceptionHandler)
|
||||||
functionGenerationContext.storeAny(valueToAssign, globalValue)
|
functionGenerationContext.storeAny(valueToAssign, globalValue)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -376,7 +376,8 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
|||||||
// Fields are module-private, so we use internal name:
|
// Fields are module-private, so we use internal name:
|
||||||
val name = "kvar:" + qualifyInternalName(descriptor)
|
val name = "kvar:" + qualifyInternalName(descriptor)
|
||||||
val storage = addGlobal(
|
val storage = addGlobal(
|
||||||
name, getLLVMType(descriptor.type), isExported = false, threadLocal = declaration.isThreadLocal)
|
name, getLLVMType(descriptor.type), isExported = false,
|
||||||
|
threadLocal = declaration.storageClass == FieldStorage.THREAD_LOCAL)
|
||||||
|
|
||||||
this.staticFields[descriptor] = StaticFieldLlvmDeclarations(storage)
|
this.staticFields[descriptor] = StaticFieldLlvmDeclarations(storage)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user