Fix infinite loop in GenerateIdentityHashCode
Root Cause:
If no one changes the seed, it will become infinite loop due to below condition
(expected_value & LockWord::kHashMask) == 0
Solution:
Changes the seed before entering the next loop
Added test.
Bug: 19046417
Change-Id: I7d1c377dd1bda780681514b24d61ebc776bc80ab
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 8bccd9e..6914f38 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -39,6 +39,8 @@
namespace art {
namespace mirror {
+Atomic<uint32_t> Object::hash_code_seed(987654321U + std::time(nullptr));
+
class CopyReferenceFieldsWithReadBarrierVisitor {
public:
explicit CopyReferenceFieldsWithReadBarrierVisitor(Object* dest_obj)
@@ -136,16 +138,19 @@
}
uint32_t Object::GenerateIdentityHashCode() {
- static Atomic<uint32_t> seed(987654321U + std::time(nullptr));
uint32_t expected_value, new_value;
do {
- expected_value = seed.LoadRelaxed();
+ expected_value = hash_code_seed.LoadRelaxed();
new_value = expected_value * 1103515245 + 12345;
- } while ((expected_value & LockWord::kHashMask) == 0 ||
- !seed.CompareExchangeWeakRelaxed(expected_value, new_value));
+ } while (!hash_code_seed.CompareExchangeWeakRelaxed(expected_value, new_value) ||
+ (expected_value & LockWord::kHashMask) == 0);
return expected_value & LockWord::kHashMask;
}
+void Object::SetHashCodeSeed(uint32_t new_seed) {
+ hash_code_seed.StoreRelaxed(new_seed);
+}
+
int32_t Object::IdentityHashCode() const {
mirror::Object* current_this = const_cast<mirror::Object*>(this);
while (true) {