diff options
author | 2015-09-02 03:03:01 +0000 | |
---|---|---|
committer | 2015-09-02 03:03:01 +0000 | |
commit | 91a359fc20f82adbe46154ca17db3cb14cd747a1 (patch) | |
tree | 4bd24888ed58827dabe40d849639100205d83e2a /runtime/java_vm_ext.cc | |
parent | 4d169121fa7c09be2e4d314c1699c3639973ac49 (diff) | |
parent | 30b5e27083913bb711fca0ca89a941797fcf3d5d (diff) |
Merge "Enable lockless decoding of weak globals"
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); |