[K/N] Support of @Volatile annotation
^KT-54944
This commit is contained in:
committed by
Space Team
parent
a29c418b63
commit
9dea349752
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user