summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2018-06-19 01:09:01 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2018-06-19 01:09:01 +0000
commit2c12bb624e91d8f1282d868fd2f2e33ba3746d6c (patch)
treeb378c9a7051ce84c3c22847be179845a04d76376
parente3435cb810a5c48626a1564dbed0ae4dda89d57b (diff)
parent8bb3c68422ce06f444d7c4e49c7af7b1c5cbeb7c (diff)
Merge "Use strong CAS for identity hash code"
-rw-r--r--runtime/mirror/object-readbarrier-inl.h34
-rw-r--r--runtime/mirror/object.cc4
-rw-r--r--runtime/mirror/object.h10
-rw-r--r--runtime/monitor.cc12
4 files changed, 51 insertions, 9 deletions
diff --git a/runtime/mirror/object-readbarrier-inl.h b/runtime/mirror/object-readbarrier-inl.h
index aeaa850abe..2988d06d96 100644
--- a/runtime/mirror/object-readbarrier-inl.h
+++ b/runtime/mirror/object-readbarrier-inl.h
@@ -39,7 +39,8 @@ inline LockWord Object::GetLockWord(bool as_volatile) {
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasFieldWeakRelaxed32(MemberOffset field_offset,
- int32_t old_value, int32_t new_value) {
+ int32_t old_value,
+ int32_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -55,10 +56,37 @@ inline bool Object::CasFieldWeakRelaxed32(MemberOffset field_offset,
return atomic_addr->CompareAndSetWeakRelaxed(old_value, new_value);
}
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline bool Object::CasFieldStrongRelaxed32(MemberOffset field_offset,
+ int32_t old_value,
+ int32_t new_value) {
+ if (kCheckTransaction) {
+ DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
+ }
+ if (kTransactionActive) {
+ Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
+ }
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
+ AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
+
+ return atomic_addr->CompareAndSetStrongRelaxed(old_value, new_value);
+}
+
inline bool Object::CasLockWordWeakRelaxed(LockWord old_val, LockWord new_val) {
// Force use of non-transactional mode and do not check.
- return CasFieldWeakRelaxed32<false, false>(
- OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
+ return CasFieldWeakRelaxed32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_),
+ old_val.GetValue(),
+ new_val.GetValue());
+}
+
+inline bool Object::CasLockWordStrongRelaxed(LockWord old_val, LockWord new_val) {
+ // Force use of non-transactional mode and do not check.
+ return CasFieldStrongRelaxed32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_),
+ old_val.GetValue(),
+ new_val.GetValue());
}
inline bool Object::CasLockWordWeakRelease(LockWord old_val, LockWord new_val) {
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 4240e702b5..200bc471b8 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -197,7 +197,9 @@ int32_t Object::IdentityHashCode() {
// loop iteration.
LockWord hash_word = LockWord::FromHashCode(GenerateIdentityHashCode(), lw.GCState());
DCHECK_EQ(hash_word.GetState(), LockWord::kHashCode);
- if (current_this->CasLockWordWeakRelaxed(lw, hash_word)) {
+ // Use a strong CAS to prevent spurious failures since these can make the boot image
+ // non-deterministic.
+ if (current_this->CasLockWordStrongRelaxed(lw, hash_word)) {
return hash_word.GetHashCode();
}
break;
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index a89d6323a5..f92ff1e2af 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -159,6 +159,8 @@ class MANAGED LOCKABLE Object {
REQUIRES_SHARED(Locks::mutator_lock_);
bool CasLockWordWeakRelease(LockWord old_val, LockWord new_val)
REQUIRES_SHARED(Locks::mutator_lock_);
+ bool CasLockWordStrongRelaxed(LockWord old_val, LockWord new_val)
+ REQUIRES_SHARED(Locks::mutator_lock_);
uint32_t GetLockOwnerThreadId();
// Try to enter the monitor, returns non null if we succeeded.
@@ -539,6 +541,14 @@ class MANAGED LOCKABLE Object {
template<bool kTransactionActive,
bool kCheckTransaction = true,
VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ ALWAYS_INLINE bool CasFieldStrongRelaxed32(MemberOffset field_offset,
+ int32_t old_value,
+ int32_t new_value)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE bool CasFieldWeakAcquire32(MemberOffset field_offset,
int32_t old_value,
int32_t new_value)
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 2c38de5dae..e723169ac2 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -134,13 +134,15 @@ Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_
}
int32_t Monitor::GetHashCode() {
- while (!HasHashCode()) {
- if (hash_code_.CompareAndSetWeakRelaxed(0, mirror::Object::GenerateIdentityHashCode())) {
- break;
- }
+ int32_t hc = hash_code_.load(std::memory_order_relaxed);
+ if (!HasHashCode()) {
+ // Use a strong CAS to prevent spurious failures since these can make the boot image
+ // non-deterministic.
+ hash_code_.CompareAndSetStrongRelaxed(0, mirror::Object::GenerateIdentityHashCode());
+ hc = hash_code_.load(std::memory_order_relaxed);
}
DCHECK(HasHashCode());
- return hash_code_.load(std::memory_order_relaxed);
+ return hc;
}
bool Monitor::Install(Thread* self) {