[K/N] Support of @Volatile annotation

^KT-54944
This commit is contained in:
Pavel Kunyavskiy
2022-11-14 17:08:28 +01:00
committed by Space Team
parent a29c418b63
commit 9dea349752
20 changed files with 631 additions and 295 deletions
@@ -29,41 +29,6 @@ struct AtomicReferenceLayout {
KInt cookie_;
};
template<typename T> struct AtomicPrimitive {
ObjHeader header;
volatile T value_;
};
template <typename T> inline volatile T* getValueLocation(KRef thiz) {
AtomicPrimitive<T>* atomic = reinterpret_cast<AtomicPrimitive<T>*>(thiz);
return &atomic->value_;
}
template <typename T> void setImpl(KRef thiz, T value) {
volatile T* location = getValueLocation<T>(thiz);
atomicSet(location, value);
}
template <typename T> T getImpl(KRef thiz) {
volatile T* location = getValueLocation<T>(thiz);
return atomicGet(location);
}
template <typename T> T addAndGetImpl(KRef thiz, T delta) {
volatile T* location = getValueLocation<T>(thiz);
return atomicAdd(location, delta);
}
template <typename T> T compareAndSwapImpl(KRef thiz, T expectedValue, T newValue) {
volatile T* location = getValueLocation<T>(thiz);
return compareAndSwap(location, expectedValue, newValue);
}
template <typename T> KBoolean compareAndSetImpl(KRef thiz, T expectedValue, T newValue) {
volatile T* location = getValueLocation<T>(thiz);
return compareAndSet(location, expectedValue, newValue);
}
inline AtomicReferenceLayout* asAtomicReference(KRef thiz) {
return reinterpret_cast<AtomicReferenceLayout*>(thiz);
}
@@ -72,119 +37,7 @@ inline AtomicReferenceLayout* asAtomicReference(KRef thiz) {
extern "C" {
KInt Kotlin_AtomicInt_addAndGet(KRef thiz, KInt delta) {
return addAndGetImpl(thiz, delta);
}
KInt Kotlin_AtomicInt_compareAndSwap(KRef thiz, KInt expectedValue, KInt newValue) {
return compareAndSwapImpl(thiz, expectedValue, newValue);
}
KBoolean Kotlin_AtomicInt_compareAndSet(KRef thiz, KInt expectedValue, KInt newValue) {
return compareAndSetImpl(thiz, expectedValue, newValue);
}
void Kotlin_AtomicInt_set(KRef thiz, KInt newValue) {
setImpl(thiz, newValue);
}
KInt Kotlin_AtomicInt_get(KRef thiz) {
return getImpl<KInt>(thiz);
}
#if KONAN_NO_64BIT_ATOMIC
static int lock64 = 0;
#endif
KLong Kotlin_AtomicLong_addAndGet(KRef thiz, KLong delta) {
#if KONAN_NO_64BIT_ATOMIC
// Potentially huge performance penalty, but correct.
while (compareAndSwap(&lock64, 0, 1) != 0);
volatile KLong* address = getValueLocation<KLong>(thiz);
KLong old = *address;
KLong newValue = old + delta;
*address = newValue;
compareAndSwap(&lock64, 1, 0);
return newValue;
#else
return addAndGetImpl(thiz, delta);
#endif
}
KLong Kotlin_AtomicLong_compareAndSwap(KRef thiz, KLong expectedValue, KLong newValue) {
#if KONAN_NO_64BIT_ATOMIC
// Potentially huge performance penalty, but correct.
while (compareAndSwap(&lock64, 0, 1) != 0);
volatile KLong* address = getValueLocation<KLong>(thiz);
KLong old = *address;
if (old == expectedValue) {
*address = newValue;
}
compareAndSwap(&lock64, 1, 0);
return old;
#else
return compareAndSwapImpl(thiz, expectedValue, newValue);
#endif
}
KBoolean Kotlin_AtomicLong_compareAndSet(KRef thiz, KLong expectedValue, KLong newValue) {
#if KONAN_NO_64BIT_ATOMIC
// Potentially huge performance penalty, but correct.
KBoolean result = false;
while (compareAndSwap(&lock64, 0, 1) != 0);
volatile KLong* address = getValueLocation<KLong>(thiz);
KLong old = *address;
if (old == expectedValue) {
result = true;
*address = newValue;
}
compareAndSwap(&lock64, 1, 0);
return result;
#else
return compareAndSetImpl(thiz, expectedValue, newValue);
#endif
}
void Kotlin_AtomicLong_set(KRef thiz, KLong newValue) {
#if KONAN_NO_64BIT_ATOMIC
// Potentially huge performance penalty, but correct.
while (compareAndSwap(&lock64, 0, 1) != 0);
volatile KLong* address = getValueLocation<KLong>(thiz);
*address = newValue;
compareAndSwap(&lock64, 1, 0);
#else
setImpl(thiz, newValue);
#endif
}
KLong Kotlin_AtomicLong_get(KRef thiz) {
#if KONAN_NO_64BIT_ATOMIC
// Potentially huge performance penalty, but correct.
while (compareAndSwap(&lock64, 0, 1) != 0);
volatile KLong* address = getValueLocation<KLong>(thiz);
KLong value = *address;
compareAndSwap(&lock64, 1, 0);
return value;
#else
return getImpl<KLong>(thiz);
#endif
}
KNativePtr Kotlin_AtomicNativePtr_compareAndSwap(KRef thiz, KNativePtr expectedValue, KNativePtr newValue) {
return compareAndSwapImpl(thiz, expectedValue, newValue);
}
KBoolean Kotlin_AtomicNativePtr_compareAndSet(KRef thiz, KNativePtr expectedValue, KNativePtr newValue) {
return compareAndSetImpl(thiz, expectedValue, newValue);
}
void Kotlin_AtomicNativePtr_set(KRef thiz, KNativePtr newValue) {
setImpl(thiz, newValue);
}
KNativePtr Kotlin_AtomicNativePtr_get(KRef thiz) {
return getImpl<KNativePtr>(thiz);
}
void Kotlin_AtomicReference_checkIfFrozen(KRef value) {
if (!kotlin::compiler::freezingEnabled()) {
@@ -247,6 +247,12 @@ void ZeroStackRef(ObjHeader** location) RUNTIME_NOTHROW;
void UpdateStackRef(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW;
// Updates heap/static data location.
void UpdateHeapRef(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW;
// Updates volatile heap/static data location.
void UpdateVolatileHeapRef(ObjHeader** location, const ObjHeader* object) RUNTIME_NOTHROW;
OBJ_GETTER(CompareAndSwapVolatileHeapRef, ObjHeader** location, ObjHeader* expectedValue, ObjHeader* newValue) RUNTIME_NOTHROW;
bool CompareAndSetVolatileHeapRef(ObjHeader** location, ObjHeader* expectedValue, ObjHeader* newValue) RUNTIME_NOTHROW;
OBJ_GETTER(GetAndSetVolatileHeapRef, ObjHeader** location, ObjHeader* newValue) RUNTIME_NOTHROW;
// Updates heap/static data in one array.
void UpdateHeapRefsInsideOneArray(const ArrayHeader* array, int fromIndex, int toIndex, int count) RUNTIME_NOTHROW;
// Updates location if it is null, atomically.