diff options
| author | 2015-09-01 11:14:34 -0700 | |
|---|---|---|
| committer | 2015-09-01 19:46:40 -0700 | |
| commit | 30b5e27083913bb711fca0ca89a941797fcf3d5d (patch) | |
| tree | c0b5229955f580d8ef928433c5e7bc372c70c3aa /runtime/java_vm_ext.cc | |
| parent | b52cfcb3868d08102b4c971974a7b1443861a90c (diff) | |
Enable lockless decoding of weak globals
Will help speed up decoding weak DexCache roots.
Change-Id: I9a68beb4106cbd383111a30e249c9b0149064e78
Diffstat (limited to 'runtime/java_vm_ext.cc')
| -rw-r--r-- | runtime/java_vm_ext.cc | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index ef7a924c63..8060e3dff0 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -375,7 +375,7 @@ JavaVMExt::JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options unchecked_functions_(&gJniInvokeInterface), weak_globals_lock_("JNI weak global reference table lock", kJniWeakGlobalsLock), weak_globals_(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal), - allow_new_weak_globals_(true), + allow_accessing_weak_globals_(true), weak_globals_add_condition_("weak globals add condition", weak_globals_lock_) { functions = unchecked_functions_; SetCheckJniEnabled(runtime_options.Exists(RuntimeArgumentMap::CheckJni)); @@ -473,8 +473,7 @@ jweak JavaVMExt::AddWeakGlobalRef(Thread* self, mirror::Object* obj) { return nullptr; } MutexLock mu(self, weak_globals_lock_); - while (UNLIKELY((!kUseReadBarrier && !allow_new_weak_globals_) || - (kUseReadBarrier && !self->GetWeakRefAccessEnabled()))) { + while (UNLIKELY(!MayAccessWeakGlobals(self))) { weak_globals_add_condition_.WaitHoldingLocks(self); } IndirectRef ref = weak_globals_.Add(IRT_FIRST_SEGMENT, obj); @@ -542,14 +541,19 @@ void JavaVMExt::DumpForSigQuit(std::ostream& os) { } void JavaVMExt::DisallowNewWeakGlobals() { - MutexLock mu(Thread::Current(), weak_globals_lock_); - allow_new_weak_globals_ = false; + Thread* const self = Thread::Current(); + MutexLock mu(self, weak_globals_lock_); + // DisallowNewWeakGlobals is only called by CMS during the pause. It is required to have the + // mutator lock exclusively held so that we don't have any threads in the middle of + // DecodeWeakGlobal. + Locks::mutator_lock_->AssertExclusiveHeld(self); + allow_accessing_weak_globals_.StoreSequentiallyConsistent(false); } void JavaVMExt::AllowNewWeakGlobals() { Thread* self = Thread::Current(); MutexLock mu(self, weak_globals_lock_); - allow_new_weak_globals_ = true; + allow_accessing_weak_globals_.StoreSequentiallyConsistent(true); weak_globals_add_condition_.Broadcast(self); } @@ -557,7 +561,7 @@ void JavaVMExt::EnsureNewWeakGlobalsDisallowed() { // Lock and unlock once to ensure that no threads are still in the // middle of adding new weak globals. MutexLock mu(Thread::Current(), weak_globals_lock_); - CHECK(!allow_new_weak_globals_); + CHECK(!allow_accessing_weak_globals_.LoadSequentiallyConsistent()); } void JavaVMExt::BroadcastForNewWeakGlobals() { @@ -567,8 +571,8 @@ void JavaVMExt::BroadcastForNewWeakGlobals() { weak_globals_add_condition_.Broadcast(self); } -mirror::Object* JavaVMExt::DecodeGlobal(Thread* self, IndirectRef ref) { - return globals_.SynchronizedGet(self, &globals_lock_, ref); +mirror::Object* JavaVMExt::DecodeGlobal(IndirectRef ref) { + return globals_.SynchronizedGet(ref); } void JavaVMExt::UpdateGlobal(Thread* self, IndirectRef ref, mirror::Object* result) { @@ -576,7 +580,25 @@ void JavaVMExt::UpdateGlobal(Thread* self, IndirectRef ref, mirror::Object* resu globals_.Update(ref, result); } +inline bool JavaVMExt::MayAccessWeakGlobals(Thread* self) const { + return MayAccessWeakGlobalsUnlocked(self); +} + +inline bool JavaVMExt::MayAccessWeakGlobalsUnlocked(Thread* self) const { + return kUseReadBarrier ? self->GetWeakRefAccessEnabled() : + allow_accessing_weak_globals_.LoadSequentiallyConsistent(); +} + mirror::Object* JavaVMExt::DecodeWeakGlobal(Thread* self, IndirectRef ref) { + // It is safe to access GetWeakRefAccessEnabled without the lock since CC uses checkpoints to call + // SetWeakRefAccessEnabled, and the other collectors only modify allow_accessing_weak_globals_ + // when the mutators are paused. + // This only applies in the case where MayAccessWeakGlobals goes from false to true. In the other + // case, it may be racy, this is benign since DecodeWeakGlobalLocked does the correct behavior + // if MayAccessWeakGlobals is false. + if (LIKELY(MayAccessWeakGlobalsUnlocked(self))) { + return weak_globals_.SynchronizedGet(ref); + } MutexLock mu(self, weak_globals_lock_); return DecodeWeakGlobalLocked(self, ref); } @@ -585,8 +607,7 @@ mirror::Object* JavaVMExt::DecodeWeakGlobalLocked(Thread* self, IndirectRef ref) if (kDebugLocking) { weak_globals_lock_.AssertHeld(self); } - while (UNLIKELY((!kUseReadBarrier && !allow_new_weak_globals_) || - (kUseReadBarrier && !self->GetWeakRefAccessEnabled()))) { + while (UNLIKELY(!MayAccessWeakGlobals(self))) { weak_globals_add_condition_.WaitHoldingLocks(self); } return weak_globals_.Get(ref); |