Tidy up memory barriers.
Change-Id: I937ea93e6df1835ecfe2d4bb7d84c24fe7fc097b
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 7ac2c8c..9161bc5 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -253,11 +253,40 @@
return result;
}
+inline uint32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) const {
+ VerifyObject(this);
+ const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
+ const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
+ if (UNLIKELY(is_volatile)) {
+ int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr)));
+ QuasiAtomic::MembarLoadLoad();
+ return result;
+ } else {
+ return *word_addr;
+ }
+}
+
+inline void Object::SetField32(MemberOffset field_offset, uint32_t new_value, bool is_volatile,
+ bool this_is_valid) {
+ if (this_is_valid) {
+ VerifyObject(this);
+ }
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ uint32_t* word_addr = reinterpret_cast<uint32_t*>(raw_addr);
+ if (UNLIKELY(is_volatile)) {
+ QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
+ *word_addr = new_value;
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ } else {
+ *word_addr = new_value;
+ }
+}
+
inline bool Object::CasField32(MemberOffset field_offset, uint32_t old_value, uint32_t new_value) {
VerifyObject(this);
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
- int32_t* addr = reinterpret_cast<int32_t*>(raw_addr);
- return android_atomic_release_cas(old_value, new_value, addr) == 0;
+ volatile uint32_t* addr = reinterpret_cast<volatile uint32_t*>(raw_addr);
+ return __sync_bool_compare_and_swap(addr, old_value, new_value);
}
inline uint64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) const {
@@ -266,7 +295,7 @@
const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
uint64_t result = QuasiAtomic::Read64(addr);
- ANDROID_MEMBAR_FULL();
+ QuasiAtomic::MembarLoadLoad();
return result;
} else {
return *addr;
@@ -278,9 +307,13 @@
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
- ANDROID_MEMBAR_STORE();
+ QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
QuasiAtomic::Write64(addr, new_value);
- // Post-store barrier not required due to use of atomic op or mutex.
+ if (!QuasiAtomic::LongAtomicsUseMutexes()) {
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ } else {
+ // Fence from from mutex is enough.
+ }
} else {
*addr = new_value;
}
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 008a173..bdb3250 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -89,10 +89,10 @@
static AtomicInteger seed(987654321 + std::time(nullptr));
int32_t expected_value, new_value;
do {
- expected_value = static_cast<uint32_t>(seed.load());
+ expected_value = static_cast<uint32_t>(seed.Load());
new_value = expected_value * 1103515245 + 12345;
} while ((expected_value & LockWord::kHashMask) == 0 ||
- !seed.compare_and_swap(expected_value, new_value));
+ !seed.CompareAndSwap(expected_value, new_value));
return expected_value & LockWord::kHashMask;
}
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index fe89b7e..058aee7 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -187,37 +187,10 @@
return reinterpret_cast<Object**>(reinterpret_cast<byte*>(this) + field_offset.Int32Value());
}
- uint32_t GetField32(MemberOffset field_offset, bool is_volatile) const {
- VerifyObject(this);
- const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
- const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
- if (UNLIKELY(is_volatile)) {
- return android_atomic_acquire_load(word_addr);
- } else {
- return *word_addr;
- }
- }
+ uint32_t GetField32(MemberOffset field_offset, bool is_volatile) const;
void SetField32(MemberOffset field_offset, uint32_t new_value, bool is_volatile,
- bool this_is_valid = true) {
- if (this_is_valid) {
- VerifyObject(this);
- }
- byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
- uint32_t* word_addr = reinterpret_cast<uint32_t*>(raw_addr);
- if (UNLIKELY(is_volatile)) {
- /*
- * TODO: add an android_atomic_synchronization_store() function and
- * use it in the 32-bit volatile set handlers. On some platforms we
- * can use a fast atomic instruction and avoid the barriers.
- */
- ANDROID_MEMBAR_STORE();
- *word_addr = new_value;
- ANDROID_MEMBAR_FULL();
- } else {
- *word_addr = new_value;
- }
- }
+ bool this_is_valid = true);
bool CasField32(MemberOffset field_offset, uint32_t old_value, uint32_t new_value);