summaryrefslogtreecommitdiff
path: root/runtime/java_vm_ext.cc
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2015-09-02 03:03:01 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2015-09-02 03:03:01 +0000
commit91a359fc20f82adbe46154ca17db3cb14cd747a1 (patch)
tree4bd24888ed58827dabe40d849639100205d83e2a /runtime/java_vm_ext.cc
parent4d169121fa7c09be2e4d314c1699c3639973ac49 (diff)
parent30b5e27083913bb711fca0ca89a941797fcf3d5d (diff)
Merge "Enable lockless decoding of weak globals"
Diffstat (limited to 'runtime/java_vm_ext.cc')
-rw-r--r--runtime/java_vm_ext.cc43
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);