[K/N] Support volatile intrinsics on globals

Also, make intrinsics signature more consistent with other intrinsics,
e.g. with isInitialized on lateinit field.

^KT-54944
This commit is contained in:
Pavel Kunyavskiy
2022-12-15 10:40:58 +01:00
committed by Space Team
parent 49d286e4e8
commit 6ab00a65dd
8 changed files with 224 additions and 111 deletions
@@ -22,5 +22,5 @@ import kotlin.concurrent.*
fun box() : String {
val o = "O"
val x = Box(o)
return x.compareAndSwapField(Box::value, o, "K") + x.value
return x::value.compareAndSwapField(o, "K") + x.value
}
+22 -22
View File
@@ -23,44 +23,44 @@ interface RefWrapper<T> : Wrapper<T> {
class IntWrapper(@Volatile var x : Int) : IncWrapper<Int> {
override fun compareAndSwap(expected: Int, new: Int) = compareAndSwapField(IntWrapper::x, expected, new)
override fun compareAndSet(expected: Int, new: Int) = compareAndSetField(IntWrapper::x, expected, new)
override fun getAndSet(new: Int) = getAndSetField(IntWrapper::x, new)
override fun getAndAdd(delta: Int) = getAndAddField(IntWrapper::x, delta)
override fun compareAndSwap(expected: Int, new: Int) = this::x.compareAndSwapField(expected, new)
override fun compareAndSet(expected: Int, new: Int) = this::x.compareAndSetField(expected, new)
override fun getAndSet(new: Int) = this::x.getAndSetField(new)
override fun getAndAdd(delta: Int) = this::x.getAndAddField(delta)
}
class LongWrapper(@Volatile var x : Long) : IncWrapper<Long> {
override fun compareAndSwap(expected: Long, new: Long) = compareAndSwapField(LongWrapper::x, expected, new)
override fun compareAndSet(expected: Long, new: Long) = compareAndSetField(LongWrapper::x, expected, new)
override fun getAndSet(new: Long) = getAndSetField(LongWrapper::x, new)
override fun getAndAdd(delta: Long) = getAndAddField(LongWrapper::x, delta)
override fun compareAndSwap(expected: Long, new: Long) = this::x.compareAndSwapField(expected, new)
override fun compareAndSet(expected: Long, new: Long) = this::x.compareAndSetField(expected, new)
override fun getAndSet(new: Long) = this::x.getAndSetField(new)
override fun getAndAdd(delta: Long) = this::x.getAndAddField(delta)
}
class ShortWrapper(@Volatile var x : Short) : IncWrapper<Short> {
override fun compareAndSwap(expected: Short, new: Short) = compareAndSwapField(ShortWrapper::x, expected, new)
override fun compareAndSet(expected: Short, new: Short) = compareAndSetField(ShortWrapper::x, expected, new)
override fun getAndSet(new: Short) = getAndSetField(ShortWrapper::x, new)
override fun getAndAdd(delta: Short) = getAndAddField(ShortWrapper::x, delta)
override fun compareAndSwap(expected: Short, new: Short) = this::x.compareAndSwapField(expected, new)
override fun compareAndSet(expected: Short, new: Short) = this::x.compareAndSetField(expected, new)
override fun getAndSet(new: Short) = this::x.getAndSetField(new)
override fun getAndAdd(delta: Short) = this::x.getAndAddField(delta)
}
class ByteWrapper(@Volatile var x : Byte) : IncWrapper<Byte> {
override fun compareAndSwap(expected: Byte, new: Byte) = compareAndSwapField(ByteWrapper::x, expected, new)
override fun compareAndSet(expected: Byte, new: Byte) = compareAndSetField(ByteWrapper::x, expected, new)
override fun getAndSet(new: Byte) = getAndSetField(ByteWrapper::x, new)
override fun getAndAdd(delta: Byte) = getAndAddField(ByteWrapper::x, delta)
override fun compareAndSwap(expected: Byte, new: Byte) = this::x.compareAndSwapField(expected, new)
override fun compareAndSet(expected: Byte, new: Byte) = this::x.compareAndSetField(expected, new)
override fun getAndSet(new: Byte) = this::x.getAndSetField(new)
override fun getAndAdd(delta: Byte) = this::x.getAndAddField(delta)
}
class StringWrapper(@Volatile var x : String) : RefWrapper<String> {
override fun compareAndSwap(expected: String, new: String) = compareAndSwapField(StringWrapper::x, expected, new)
override fun compareAndSet(expected: String, new: String) = compareAndSetField(StringWrapper::x, expected, new)
override fun getAndSet(new: String) = getAndSetField(StringWrapper::x, new)
override fun compareAndSwap(expected: String, new: String) = this::x.compareAndSwapField(expected, new)
override fun compareAndSet(expected: String, new: String) = this::x.compareAndSetField(expected, new)
override fun getAndSet(new: String) = this::x.getAndSetField(new)
}
class GenericWrapper<T>(@Volatile var x : T) : RefWrapper<T> {
override fun compareAndSwap(expected: T, new: T) = compareAndSwapField(GenericWrapper<T>::x, expected, new)
override fun compareAndSet(expected: T, new: T) = compareAndSetField(GenericWrapper<T>::x, expected, new)
override fun getAndSet(new: T) = getAndSetField(GenericWrapper<T>::x, new)
override fun compareAndSwap(expected: T, new: T) = this::x.compareAndSwapField(expected, new)
override fun compareAndSet(expected: T, new: T) = this::x.compareAndSetField(expected, new)
override fun getAndSet(new: T) = this::x.getAndSetField(new)
}
@@ -0,0 +1,62 @@
// TARGET_BACKEND: NATIVE
// KT-55904
// IGNORE_BACKEND_K2: NATIVE
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@file:OptIn(kotlin.ExperimentalStdlibApi::class)
import kotlin.native.concurrent.*
import kotlin.concurrent.*
val a = "1"
val b = "2"
val c = "3"
@Volatile var x: Int = 1
@Volatile var y: Long = 1L
@Volatile var z: String = a
@Volatile var t: Boolean = true
fun box() : String {
if (::x.compareAndSetField(1, 2) != true) return "FAIL Int: 1"
if (::x.compareAndSetField(1, 2) != false) return "FAIL Int: 2"
if (::x.compareAndSwapField(2, 1) != 2) return "FAIL Int: 3"
if (::x.compareAndSwapField(2, 1) != 1) return "FAIL Int: 4"
if (::x.getAndSetField(3) != 1) return "FAIL Int: 5"
if (::x.getAndSetField(1) != 3) return "FAIL Int: 6"
if (::x.getAndAddField(1) != 1) return "FAIL Int: 7"
if (::x.getAndAddField(1) != 2) return "FAIL Int: 8"
if (x != 3) return "FAIL Int: 9"
if (::y.compareAndSetField(1L, 2L) != true) return "FAIL Long: 1"
if (::y.compareAndSetField(1L, 2L) != false) return "FAIL Long: 2"
if (::y.compareAndSwapField(2L, 1L) != 2L) return "FAIL Long: 3"
if (::y.compareAndSwapField(2L, 1L) != 1L) return "FAIL Long: 4"
if (::y.getAndSetField(3L) != 1L) return "FAIL Long: 5"
if (::y.getAndSetField(1L) != 3L) return "FAIL Long: 6"
if (::y.getAndAddField(1L) != 1L) return "FAIL Long: 7"
if (::y.getAndAddField(1L) != 2L) return "FAIL Long: 8"
if (y != 3L) return "FAIL Long: 9"
if (isExperimentalMM()) {
if (::z.compareAndSetField(a, b) != true) return "FAIL String: 1"
if (::z.compareAndSetField(a, b) != false) return "FAIL String: 2"
if (::z.compareAndSwapField(b, a) != b) return "FAIL String: 3"
if (::z.compareAndSwapField(b, a) != a) return "FAIL String: 4"
if (::z.getAndSetField(c) != a) return "FAIL String: 5"
if (::z.getAndSetField(a) != c) return "FAIL String: 6"
if (z != a) return "FAIL String: 7"
}
if (::t.compareAndSetField(true, false) != true) return "FAIL Bool: 1"
if (::t.compareAndSetField(true, false) != false) return "FAIL Bool: 2"
if (::t.compareAndSwapField(false, true) != false) return "FAIL Bool: 3"
if (::t.compareAndSwapField(false, true) != true) return "FAIL Bool: 4"
if (::t.getAndSetField(false) != true) return "FAIL Bool: 5"
if (::t.getAndSetField(true) != false) return "FAIL Bool: 6"
if (t != true) return "FAIL Bool: 7"
return "OK"
}