diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index e25731017c4..2497f5ac878 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -17,7 +17,6 @@ import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport import org.jetbrains.kotlin.backend.konan.optimizations.* import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.UnsignedType -import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin @@ -39,10 +38,11 @@ import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.resolve.hasBackingField private val threadLocalAnnotationFqName = FqName("kotlin.native.ThreadLocal") private val sharedAnnotationFqName = FqName("kotlin.native.SharedImmutable") - +private val frozenAnnotationFqName = FqName("kotlin.native.internal.Frozen") val IrField.propertyDescriptor: PropertyDescriptor get() { @@ -67,7 +67,11 @@ internal val IrField.storageClass: FieldStorage get() { val descriptor = propertyDescriptor return when { descriptor.annotations.hasAnnotation(threadLocalAnnotationFqName) -> FieldStorage.THREAD_LOCAL + !isFinal -> FieldStorage.MAIN_THREAD descriptor.annotations.hasAnnotation(sharedAnnotationFqName) -> FieldStorage.SHARED + // TODO: simplify, once IR types are fully there. + type is IrSimpleType && (type as IrSimpleType). + classifier.descriptor.annotations.hasAnnotation(frozenAnnotationFqName) -> FieldStorage.SHARED else -> FieldStorage.MAIN_THREAD } } diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index ff146dc9652..02a1d926379 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -659,6 +659,12 @@ task worker9(type: RunKonanTest) { source = "runtime/workers/worker9.kt" } +task worker10(type: RunKonanTest) { + disabled = (project.testTarget == 'wasm32') // Workers need pthreads. + goldValue = "OK\n" + source = "runtime/workers/worker10.kt" +} + task freeze0(type: RunKonanTest) { disabled = (project.testTarget == 'wasm32') // No workers on WASM. goldValue = "frozen bit is true\n" + diff --git a/backend.native/tests/runtime/workers/worker10.kt b/backend.native/tests/runtime/workers/worker10.kt new file mode 100644 index 00000000000..fcebcd0a47d --- /dev/null +++ b/backend.native/tests/runtime/workers/worker10.kt @@ -0,0 +1,81 @@ +package runtime.workers.worker10 + +import kotlin.test.* + +import kotlin.native.concurrent.* + +class Data(val x: Int) + +val topInt = 1 +val topString = "string" +var topStringVar = "string" +val topSharedStringWithGetter: String + get() = "top" +val topData = Data(42) +@SharedImmutable +val topSharedData = Data(43) + +@Test fun runTest() { + val worker = Worker.start() + + assertEquals(1, topInt) + assertEquals("string", topString) + assertEquals(42, topData.x) + assertEquals(43, topSharedData.x) + assertEquals("top", topSharedStringWithGetter) + + worker.execute(TransferMode.SAFE, { -> }, { + it -> topInt == 1 + }).consume { + result -> assertEquals(true, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> topString == "string" + }).consume { + result -> assertEquals(true, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> try { + topStringVar == "string" + } catch (e: IncorrectDereferenceException) { + false + } + }).consume { + result -> assertEquals(false, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> try { + topSharedStringWithGetter == "top" + } catch (e: IncorrectDereferenceException) { + false + } + }).consume { + result -> assertEquals(true, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> try { + topData.x == 42 + } catch (e: IncorrectDereferenceException) { + false + } + }).consume { + result -> assertEquals(false, result) + } + + worker.execute(TransferMode.SAFE, { -> }, { + it -> try { + topSharedData.x == 43 + } catch (e: Throwable) { + false + } + }).consume { + result -> assertEquals(true, result) + } + + worker.requestTermination().result + println("OK") +} \ No newline at end of file