diff options
author | Mathieu Chartier <mathieuc@google.com> | 2013-10-31 10:35:05 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2013-10-31 13:33:51 -0700 |
commit | 4e6a31eb97f22f4480827474b30b9e64f396eace (patch) | |
tree | 3afe222c60314a22be8bb8de61cb245e1af2dc92 /runtime/monitor.cc | |
parent | 1b8cb967143d5c46db1db8ac940a73d111be3628 (diff) | |
download | art-4e6a31eb97f22f4480827474b30b9e64f396eace.zip art-4e6a31eb97f22f4480827474b30b9e64f396eace.tar.gz art-4e6a31eb97f22f4480827474b30b9e64f396eace.tar.bz2 |
Lazily compute object identity hash codes.
Before, we computed identity hashcodes whenever we inflated a monitor.
This caused issues since it meant that we would have all of these
hash codes in the image, causing locks to excessively inflate during
application run time.
This change makes it so that we lazily compute hash codes. When a
thin lock gets inflated, we assign a hash code of 0 assigned to it.
This value signifies no hash code. When we try to get the identity
hash code of an object with an inflated monitor, it gets computed if
it is 0.
Change-Id: Iae6acd1960515a36e74644e5b1323ff336731806
Diffstat (limited to 'runtime/monitor.cc')
-rw-r--r-- | runtime/monitor.cc | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/runtime/monitor.cc b/runtime/monitor.cc index aa47bda..2abfd3d 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -79,7 +79,7 @@ void Monitor::Init(uint32_t lock_profiling_threshold, bool (*is_sensitive_thread is_sensitive_thread_hook_ = is_sensitive_thread_hook; } -Monitor::Monitor(Thread* owner, mirror::Object* obj, uint32_t hash_code) +Monitor::Monitor(Thread* owner, mirror::Object* obj, int32_t hash_code) : monitor_lock_("a monitor lock", kMonitorLock), monitor_contenders_("monitor contenders", monitor_lock_), owner_(owner), @@ -95,6 +95,16 @@ Monitor::Monitor(Thread* owner, mirror::Object* obj, uint32_t hash_code) // The identity hash code is set for the life time of the monitor. } +int32_t Monitor::GetHashCode() { + while (!HasHashCode()) { + if (hash_code_.compare_and_swap(0, mirror::Object::GenerateIdentityHashCode())) { + break; + } + } + DCHECK(HasHashCode()); + return hash_code_.load(); +} + bool Monitor::Install(Thread* self) { MutexLock mu(self, monitor_lock_); // Uncontended mutex acquisition as monitor isn't yet public. CHECK(owner_ == nullptr || owner_ == self || owner_->IsSuspended()); @@ -107,7 +117,7 @@ bool Monitor::Install(Thread* self) { break; } case LockWord::kHashCode: { - CHECK_EQ(hash_code_, lw.GetHashCode()); + CHECK_EQ(hash_code_, static_cast<int32_t>(lw.GetHashCode())); break; } case LockWord::kFatLocked: { @@ -622,7 +632,7 @@ void Monitor::MonitorEnter(Thread* self, mirror::Object* obj) { return; // Success! } else { // We'd overflow the recursion count, so inflate the monitor. - InflateThinLocked(self, obj, lock_word, mirror::Object::GenerateIdentityHashCode()); + InflateThinLocked(self, obj, lock_word, 0); } } else { // Contention. @@ -632,7 +642,7 @@ void Monitor::MonitorEnter(Thread* self, mirror::Object* obj) { NanoSleep(1000); // Sleep for 1us and re-attempt. } else { contention_count = 0; - InflateThinLocked(self, obj, lock_word, mirror::Object::GenerateIdentityHashCode()); + InflateThinLocked(self, obj, lock_word, 0); } } continue; // Start from the beginning. @@ -716,7 +726,7 @@ void Monitor::Wait(Thread* self, mirror::Object *obj, int64_t ms, int32_t ns, return; // Failure. } else { // We own the lock, inflate to enqueue ourself on the Monitor. - Inflate(self, self, obj, mirror::Object::GenerateIdentityHashCode()); + Inflate(self, self, obj, 0); lock_word = obj->GetLockWord(); } break; |