diff options
author | 2019-03-29 12:33:02 +0000 | |
---|---|---|
committer | 2019-04-01 09:37:59 +0000 | |
commit | f52d92fce224c86491d9b0fd6fca805564119426 (patch) | |
tree | fbf38f272a980e965627918d9dc6bbb536395c00 | |
parent | e660f7232a19a2c173f562b8e0987755a78ee298 (diff) |
ObjPtr<>-ify Monitor/-Pool.
Test: m test-art-host-gtest
Test: testrunner.py --host
Bug: 31113334
Change-Id: I2d2ebc5ef56e73e5678e0cfcd84c479611dfcca8
-rw-r--r-- | openjdkjvmti/events.cc | 4 | ||||
-rw-r--r-- | openjdkjvmti/ti_stack.cc | 7 | ||||
-rw-r--r-- | runtime/Android.bp | 1 | ||||
-rw-r--r-- | runtime/debugger.cc | 4 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_lock_entrypoints.cc | 8 | ||||
-rw-r--r-- | runtime/mirror/object-inl.h | 4 | ||||
-rw-r--r-- | runtime/mirror/object.h | 4 | ||||
-rw-r--r-- | runtime/monitor-inl.h | 34 | ||||
-rw-r--r-- | runtime/monitor.cc | 77 | ||||
-rw-r--r-- | runtime/monitor.h | 58 | ||||
-rw-r--r-- | runtime/monitor_objects_stack_visitor.cc | 103 | ||||
-rw-r--r-- | runtime/monitor_objects_stack_visitor.h | 90 | ||||
-rw-r--r-- | runtime/monitor_pool.cc | 4 | ||||
-rw-r--r-- | runtime/monitor_pool.h | 10 | ||||
-rw-r--r-- | runtime/runtime_callbacks_test.cc | 14 | ||||
-rw-r--r-- | runtime/thread.cc | 20 | ||||
-rw-r--r-- | test/167-visit-locks/visit_locks.cc | 3 |
17 files changed, 270 insertions, 175 deletions
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc index b41edc5e8c..2c5ebfe3e1 100644 --- a/openjdkjvmti/events.cc +++ b/openjdkjvmti/events.cc @@ -50,7 +50,7 @@ #include "jni/jni_internal.h" #include "mirror/class.h" #include "mirror/object-inl.h" -#include "monitor.h" +#include "monitor-inl.h" #include "nativehelper/scoped_local_ref.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" @@ -236,7 +236,7 @@ static bool IsThreadControllable(ArtJvmtiEvent event) { } template<typename Type> -static Type AddLocalRef(art::JNIEnvExt* e, art::mirror::Object* obj) +static Type AddLocalRef(art::JNIEnvExt* e, art::ObjPtr<art::mirror::Object> obj) REQUIRES_SHARED(art::Locks::mutator_lock_) { return (obj == nullptr) ? nullptr : e->AddLocalReference<Type>(obj); } diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc index 5e934df42c..b96c92aac7 100644 --- a/openjdkjvmti/ti_stack.cc +++ b/openjdkjvmti/ti_stack.cc @@ -844,18 +844,17 @@ struct MonitorVisitor : public art::StackVisitor, public art::SingleRootVisitor return true; } - static void AppendOwnedMonitors(art::mirror::Object* owned_monitor, void* arg) + static void AppendOwnedMonitors(art::ObjPtr<art::mirror::Object> owned_monitor, void* arg) REQUIRES_SHARED(art::Locks::mutator_lock_) { art::Locks::mutator_lock_->AssertSharedHeld(art::Thread::Current()); MonitorVisitor* visitor = reinterpret_cast<MonitorVisitor*>(arg); - art::ObjPtr<art::mirror::Object> mon(owned_monitor); // Filter out duplicates. for (const art::Handle<art::mirror::Object>& monitor : visitor->monitors) { - if (monitor.Get() == mon.Ptr()) { + if (monitor.Get() == owned_monitor) { return; } } - visitor->monitors.push_back(visitor->hs.NewHandle(mon)); + visitor->monitors.push_back(visitor->hs.NewHandle(owned_monitor)); visitor->stack_depths.push_back(visitor->current_stack_depth); } diff --git a/runtime/Android.bp b/runtime/Android.bp index 5ed3acc4fa..0cc7d298d6 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -141,6 +141,7 @@ libart_cc_defaults { "mirror/throwable.cc", "mirror/var_handle.cc", "monitor.cc", + "monitor_objects_stack_visitor.cc", "native_bridge_art_interface.cc", "native_stack_dump.cc", "native/dalvik_system_DexFile.cc", diff --git a/runtime/debugger.cc b/runtime/debugger.cc index a38c9abfb8..c5b111f804 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -900,7 +900,7 @@ JDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id, return true; } - static void AppendOwnedMonitors(mirror::Object* owned_monitor, void* arg) + static void AppendOwnedMonitors(ObjPtr<mirror::Object> owned_monitor, void* arg) REQUIRES_SHARED(Locks::mutator_lock_) { OwnedMonitorVisitor* visitor = reinterpret_cast<OwnedMonitorVisitor*>(arg); visitor->monitors->push_back(gRegistry->Add(owned_monitor)); @@ -939,7 +939,7 @@ JDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id, if (!IsSuspendedForDebugger(soa, thread)) { return JDWP::ERR_THREAD_NOT_SUSPENDED; } - mirror::Object* contended_monitor_obj = Monitor::GetContendedMonitor(thread); + ObjPtr<mirror::Object> contended_monitor_obj = Monitor::GetContendedMonitor(thread); // Add() requires the thread_list_lock_ not held to avoid the lock // level violation. *contended_monitor = gRegistry->Add(contended_monitor_obj); diff --git a/runtime/entrypoints/quick/quick_lock_entrypoints.cc b/runtime/entrypoints/quick/quick_lock_entrypoints.cc index 4bcce217d6..87286cf651 100644 --- a/runtime/entrypoints/quick/quick_lock_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_lock_entrypoints.cc @@ -29,8 +29,8 @@ extern "C" int artLockObjectFromCode(mirror::Object* obj, Thread* self) ThrowNullPointerException("Null reference used for synchronization (monitor-enter)"); return -1; // Failure. } else { - obj = obj->MonitorEnter(self); // May block - DCHECK(self->HoldsLock(obj)); + ObjPtr<mirror::Object> object = obj->MonitorEnter(self); // May block + DCHECK(self->HoldsLock(object)); // Exceptions can be thrown by monitor event listeners. This is expected to be rare however. if (UNLIKELY(self->IsExceptionPending())) { // TODO Remove this DCHECK if we expand the use of monitor callbacks. @@ -38,11 +38,11 @@ extern "C" int artLockObjectFromCode(mirror::Object* obj, Thread* self) << "Exceptions are only expected to be thrown by plugin code which doesn't seem to be " << "loaded."; // We need to get rid of the lock - bool unlocked = obj->MonitorExit(self); + bool unlocked = object->MonitorExit(self); DCHECK(unlocked); return -1; // Failure. } else { - DCHECK(self->HoldsLock(obj)); + DCHECK(self->HoldsLock(object)); return 0; // Success. } } diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h index e203658b90..56e1807e41 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -79,11 +79,11 @@ inline uint32_t Object::GetLockOwnerThreadId() { return Monitor::GetLockOwnerThreadId(this); } -inline mirror::Object* Object::MonitorEnter(Thread* self) { +inline ObjPtr<mirror::Object> Object::MonitorEnter(Thread* self) { return Monitor::MonitorEnter(self, this, /*trylock=*/false); } -inline mirror::Object* Object::MonitorTryEnter(Thread* self) { +inline ObjPtr<mirror::Object> Object::MonitorTryEnter(Thread* self) { return Monitor::MonitorEnter(self, this, /*trylock=*/true); } diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h index 2d692064fd..fea6eb5ed2 100644 --- a/runtime/mirror/object.h +++ b/runtime/mirror/object.h @@ -153,11 +153,11 @@ class MANAGED LOCKABLE Object { uint32_t GetLockOwnerThreadId(); // Try to enter the monitor, returns non null if we succeeded. - mirror::Object* MonitorTryEnter(Thread* self) + ObjPtr<mirror::Object> MonitorTryEnter(Thread* self) EXCLUSIVE_LOCK_FUNCTION() REQUIRES(!Roles::uninterruptible_) REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* MonitorEnter(Thread* self) + ObjPtr<mirror::Object> MonitorEnter(Thread* self) EXCLUSIVE_LOCK_FUNCTION() REQUIRES(!Roles::uninterruptible_) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/monitor-inl.h b/runtime/monitor-inl.h new file mode 100644 index 0000000000..e8ffafad43 --- /dev/null +++ b/runtime/monitor-inl.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_MONITOR_INL_H_ +#define ART_RUNTIME_MONITOR_INL_H_ + +#include "monitor.h" + +#include "gc_root-inl.h" +#include "obj_ptr-inl.h" + +namespace art { + +template<ReadBarrierOption kReadBarrierOption> +inline ObjPtr<mirror::Object> Monitor::GetObject() REQUIRES_SHARED(Locks::mutator_lock_) { + return obj_.Read<kReadBarrierOption>(); +} + +} // namespace art + +#endif // ART_RUNTIME_MONITOR_INL_H_ diff --git a/runtime/monitor.cc b/runtime/monitor.cc index 6abc8d7f8c..676bceb766 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "monitor.h" +#include "monitor-inl.h" #include <vector> @@ -89,7 +89,7 @@ void Monitor::Init(uint32_t lock_profiling_threshold, stack_dump_lock_profiling_threshold * kDebugThresholdFudgeFactor; } -Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) +Monitor::Monitor(Thread* self, Thread* owner, ObjPtr<mirror::Object> obj, int32_t hash_code) : monitor_lock_("a monitor lock", kMonitorLock), monitor_contenders_("monitor contenders", monitor_lock_), num_waiters_(0), @@ -112,7 +112,10 @@ Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_ // The identity hash code is set for the life time of the monitor. } -Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code, +Monitor::Monitor(Thread* self, + Thread* owner, + ObjPtr<mirror::Object> obj, + int32_t hash_code, MonitorId id) : monitor_lock_("a monitor lock", kMonitorLock), monitor_contenders_("monitor contenders", monitor_lock_), @@ -273,19 +276,19 @@ void Monitor::RemoveFromWaitSet(Thread *thread) { remove(wake_set_); } -void Monitor::SetObject(mirror::Object* object) { +void Monitor::SetObject(ObjPtr<mirror::Object> object) { obj_ = GcRoot<mirror::Object>(object); } // This function is inlined and just helps to not have the VLOG and ATRACE check at all the // potential tracing points. -void Monitor::AtraceMonitorLock(Thread* self, mirror::Object* obj, bool is_wait) { +void Monitor::AtraceMonitorLock(Thread* self, ObjPtr<mirror::Object> obj, bool is_wait) { if (UNLIKELY(VLOG_IS_ON(systrace_lock_logging) && ATraceEnabled())) { AtraceMonitorLockImpl(self, obj, is_wait); } } -void Monitor::AtraceMonitorLockImpl(Thread* self, mirror::Object* obj, bool is_wait) { +void Monitor::AtraceMonitorLockImpl(Thread* self, ObjPtr<mirror::Object> obj, bool is_wait) { // Wait() requires a deeper call stack to be useful. Otherwise you'll see "Waiting at // Object.java". Assume that we'll wait a nontrivial amount, so it's OK to do a longer // stack walk than if !is_wait. @@ -335,7 +338,7 @@ void Monitor::AtraceMonitorLockImpl(Thread* self, mirror::Object* obj, bool is_w // also do not have to be stable, as the monitor may be deflated. std::string tmp = StringPrintf("%s %d at %s:%d", prefix, - (obj == nullptr ? -1 : static_cast<int32_t>(reinterpret_cast<uintptr_t>(obj))), + (obj == nullptr ? -1 : static_cast<int32_t>(reinterpret_cast<uintptr_t>(obj.Ptr()))), (filename != nullptr ? filename : "null"), line_number); ATraceBegin(tmp.c_str()); @@ -462,7 +465,7 @@ void Monitor::Lock(Thread* self) { called_monitors_callback = true; Runtime::Current()->GetRuntimeCallbacks()->MonitorContendedLocking(this); } - self->SetMonitorEnterObject(GetObject()); + self->SetMonitorEnterObject(GetObject().Ptr()); { ScopedThreadSuspension tsc(self, kBlocked); // Change to blocked and give up mutator_lock_. uint32_t original_owner_thread_id = 0u; @@ -627,7 +630,7 @@ static std::string ThreadToString(Thread* thread) { return oss.str(); } -void Monitor::FailedUnlock(mirror::Object* o, +void Monitor::FailedUnlock(ObjPtr<mirror::Object> o, uint32_t expected_owner_thread_id, uint32_t found_owner_thread_id, Monitor* monitor) { @@ -957,7 +960,7 @@ void Monitor::NotifyAll(Thread* self) { } } -bool Monitor::Deflate(Thread* self, mirror::Object* obj) { +bool Monitor::Deflate(Thread* self, ObjPtr<mirror::Object> obj) { DCHECK(obj != nullptr); // Don't need volatile since we only deflate with mutators suspended. LockWord lw(obj->GetLockWord(false)); @@ -1007,7 +1010,7 @@ bool Monitor::Deflate(Thread* self, mirror::Object* obj) { return true; } -void Monitor::Inflate(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) { +void Monitor::Inflate(Thread* self, Thread* owner, ObjPtr<mirror::Object> obj, int32_t hash_code) { DCHECK(self != nullptr); DCHECK(obj != nullptr); // Allocate and acquire a new monitor. @@ -1063,18 +1066,20 @@ void Monitor::InflateThinLocked(Thread* self, Handle<mirror::Object> obj, LockWo } // Fool annotalysis into thinking that the lock on obj is acquired. -static mirror::Object* FakeLock(mirror::Object* obj) - EXCLUSIVE_LOCK_FUNCTION(obj) NO_THREAD_SAFETY_ANALYSIS { +static ObjPtr<mirror::Object> FakeLock(ObjPtr<mirror::Object> obj) + EXCLUSIVE_LOCK_FUNCTION(obj.Ptr()) NO_THREAD_SAFETY_ANALYSIS { return obj; } // Fool annotalysis into thinking that the lock on obj is release. -static mirror::Object* FakeUnlock(mirror::Object* obj) - UNLOCK_FUNCTION(obj) NO_THREAD_SAFETY_ANALYSIS { +static ObjPtr<mirror::Object> FakeUnlock(ObjPtr<mirror::Object> obj) + UNLOCK_FUNCTION(obj.Ptr()) NO_THREAD_SAFETY_ANALYSIS { return obj; } -mirror::Object* Monitor::MonitorEnter(Thread* self, mirror::Object* obj, bool trylock) { +ObjPtr<mirror::Object> Monitor::MonitorEnter(Thread* self, + ObjPtr<mirror::Object> obj, + bool trylock) { DCHECK(self != nullptr); DCHECK(obj != nullptr); self->AssertThreadSuspensionIsAllowable(); @@ -1180,7 +1185,7 @@ mirror::Object* Monitor::MonitorEnter(Thread* self, mirror::Object* obj, bool tr } } -bool Monitor::MonitorExit(Thread* self, mirror::Object* obj) { +bool Monitor::MonitorExit(Thread* self, ObjPtr<mirror::Object> obj) { DCHECK(self != nullptr); DCHECK(obj != nullptr); self->AssertThreadSuspensionIsAllowable(); @@ -1242,8 +1247,12 @@ bool Monitor::MonitorExit(Thread* self, mirror::Object* obj) { } } -void Monitor::Wait(Thread* self, mirror::Object *obj, int64_t ms, int32_t ns, - bool interruptShouldThrow, ThreadState why) { +void Monitor::Wait(Thread* self, + ObjPtr<mirror::Object> obj, + int64_t ms, + int32_t ns, + bool interruptShouldThrow, + ThreadState why) { DCHECK(self != nullptr); DCHECK(obj != nullptr); StackHandleScope<1> hs(self); @@ -1288,7 +1297,7 @@ void Monitor::Wait(Thread* self, mirror::Object *obj, int64_t ms, int32_t ns, mon->Wait(self, ms, ns, interruptShouldThrow, why); } -void Monitor::DoNotify(Thread* self, mirror::Object* obj, bool notify_all) { +void Monitor::DoNotify(Thread* self, ObjPtr<mirror::Object> obj, bool notify_all) { DCHECK(self != nullptr); DCHECK(obj != nullptr); LockWord lock_word = obj->GetLockWord(true); @@ -1325,7 +1334,7 @@ void Monitor::DoNotify(Thread* self, mirror::Object* obj, bool notify_all) { } } -uint32_t Monitor::GetLockOwnerThreadId(mirror::Object* obj) { +uint32_t Monitor::GetLockOwnerThreadId(ObjPtr<mirror::Object> obj) { DCHECK(obj != nullptr); LockWord lock_word = obj->GetLockWord(true); switch (lock_word.GetState()) { @@ -1347,7 +1356,7 @@ uint32_t Monitor::GetLockOwnerThreadId(mirror::Object* obj) { } ThreadState Monitor::FetchState(const Thread* thread, - /* out */ mirror::Object** monitor_object, + /* out */ ObjPtr<mirror::Object>* monitor_object, /* out */ uint32_t* lock_owner_tid) { DCHECK(monitor_object != nullptr); DCHECK(lock_owner_tid != nullptr); @@ -1374,14 +1383,14 @@ ThreadState Monitor::FetchState(const Thread* thread, case kBlocked: case kWaitingForLockInflation: { - mirror::Object* lock_object = thread->GetMonitorEnterObject(); + ObjPtr<mirror::Object> lock_object = thread->GetMonitorEnterObject(); if (lock_object != nullptr) { if (kUseReadBarrier && Thread::Current()->GetIsGcMarking()) { // We may call Thread::Dump() in the middle of the CC thread flip and this thread's stack // may have not been flipped yet and "pretty_object" may be a from-space (stale) ref, in // which case the GetLockOwnerThreadId() call below will crash. So explicitly mark/forward // it here. - lock_object = ReadBarrier::Mark(lock_object); + lock_object = ReadBarrier::Mark(lock_object.Ptr()); } *monitor_object = lock_object; *lock_owner_tid = lock_object->GetLockOwnerThreadId(); @@ -1396,10 +1405,10 @@ ThreadState Monitor::FetchState(const Thread* thread, return state; } -mirror::Object* Monitor::GetContendedMonitor(Thread* thread) { +ObjPtr<mirror::Object> Monitor::GetContendedMonitor(Thread* thread) { // This is used to implement JDWP's ThreadReference.CurrentContendedMonitor, and has a bizarre // definition of contended that includes a monitor a thread is trying to enter... - mirror::Object* result = thread->GetMonitorEnterObject(); + ObjPtr<mirror::Object> result = thread->GetMonitorEnterObject(); if (result == nullptr) { // ...but also a monitor that the thread is waiting on. MutexLock mu(Thread::Current(), *thread->GetWaitMutex()); @@ -1411,8 +1420,10 @@ mirror::Object* Monitor::GetContendedMonitor(Thread* thread) { return result; } -void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::Object*, void*), - void* callback_context, bool abort_on_failure) { +void Monitor::VisitLocks(StackVisitor* stack_visitor, + void (*callback)(ObjPtr<mirror::Object>, void*), + void* callback_context, + bool abort_on_failure) { ArtMethod* m = stack_visitor->GetMethod(); CHECK(m != nullptr); @@ -1420,7 +1431,7 @@ void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::O // TODO: use the JNI implementation's table of explicit MonitorEnter calls and dump those too. if (m->IsNative()) { if (m->IsSynchronized()) { - mirror::Object* jni_this = + ObjPtr<mirror::Object> jni_this = stack_visitor->GetCurrentHandleScope(sizeof(void*))->GetReference(0); callback(jni_this, callback_context); } @@ -1472,7 +1483,7 @@ void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::O uint32_t value; success = stack_visitor->GetVReg(m, dex_reg, kReferenceVReg, &value); if (success) { - mirror::Object* o = reinterpret_cast<mirror::Object*>(value); + ObjPtr<mirror::Object> o = reinterpret_cast<mirror::Object*>(value); callback(o, callback_context); break; } @@ -1603,9 +1614,9 @@ void MonitorList::SweepMonitorList(IsMarkedVisitor* visitor) { for (auto it = list_.begin(); it != list_.end(); ) { Monitor* m = *it; // Disable the read barrier in GetObject() as this is called by GC. - mirror::Object* obj = m->GetObject<kWithoutReadBarrier>(); + ObjPtr<mirror::Object> obj = m->GetObject<kWithoutReadBarrier>(); // The object of a monitor can be null if we have deflated it. - mirror::Object* new_obj = obj != nullptr ? visitor->IsMarked(obj) : nullptr; + ObjPtr<mirror::Object> new_obj = obj != nullptr ? visitor->IsMarked(obj.Ptr()) : nullptr; if (new_obj == nullptr) { VLOG(monitor) << "freeing monitor " << m << " belonging to unmarked object " << obj; @@ -1650,7 +1661,7 @@ size_t MonitorList::DeflateMonitors() { return visitor.deflate_count_; } -MonitorInfo::MonitorInfo(mirror::Object* obj) : owner_(nullptr), entry_count_(0) { +MonitorInfo::MonitorInfo(ObjPtr<mirror::Object> obj) : owner_(nullptr), entry_count_(0) { DCHECK(obj != nullptr); LockWord lock_word = obj->GetLockWord(true); switch (lock_word.GetState()) { diff --git a/runtime/monitor.h b/runtime/monitor.h index c1f84e92bf..4187f27c94 100644 --- a/runtime/monitor.h +++ b/runtime/monitor.h @@ -30,6 +30,7 @@ #include "base/mutex.h" #include "gc_root.h" #include "lock_word.h" +#include "obj_ptr.h" #include "read_barrier_option.h" #include "runtime_callbacks.h" #include "thread_state.h" @@ -64,62 +65,69 @@ class Monitor { static void Init(uint32_t lock_profiling_threshold, uint32_t stack_dump_lock_profiling_threshold); // Return the thread id of the lock owner or 0 when there is no owner. - static uint32_t GetLockOwnerThreadId(mirror::Object* obj) + static uint32_t GetLockOwnerThreadId(ObjPtr<mirror::Object> obj) NO_THREAD_SAFETY_ANALYSIS; // TODO: Reading lock owner without holding lock is racy. // NO_THREAD_SAFETY_ANALYSIS for mon->Lock. - static mirror::Object* MonitorEnter(Thread* thread, mirror::Object* obj, bool trylock) - EXCLUSIVE_LOCK_FUNCTION(obj) + static ObjPtr<mirror::Object> MonitorEnter(Thread* thread, + ObjPtr<mirror::Object> obj, + bool trylock) + EXCLUSIVE_LOCK_FUNCTION(obj.Ptr()) NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_) REQUIRES_SHARED(Locks::mutator_lock_); // NO_THREAD_SAFETY_ANALYSIS for mon->Unlock. - static bool MonitorExit(Thread* thread, mirror::Object* obj) + static bool MonitorExit(Thread* thread, ObjPtr<mirror::Object> obj) NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_) REQUIRES_SHARED(Locks::mutator_lock_) - UNLOCK_FUNCTION(obj); + UNLOCK_FUNCTION(obj.Ptr()); - static void Notify(Thread* self, mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) { + static void Notify(Thread* self, ObjPtr<mirror::Object> obj) + REQUIRES_SHARED(Locks::mutator_lock_) { DoNotify(self, obj, false); } - static void NotifyAll(Thread* self, mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) { + static void NotifyAll(Thread* self, ObjPtr<mirror::Object> obj) + REQUIRES_SHARED(Locks::mutator_lock_) { DoNotify(self, obj, true); } // Object.wait(). Also called for class init. // NO_THREAD_SAFETY_ANALYSIS for mon->Wait. - static void Wait(Thread* self, mirror::Object* obj, int64_t ms, int32_t ns, + static void Wait(Thread* self, + ObjPtr<mirror::Object> obj, + int64_t ms, + int32_t ns, bool interruptShouldThrow, ThreadState why) REQUIRES_SHARED(Locks::mutator_lock_) NO_THREAD_SAFETY_ANALYSIS; static ThreadState FetchState(const Thread* thread, - /* out */ mirror::Object** monitor_object, + /* out */ ObjPtr<mirror::Object>* monitor_object, /* out */ uint32_t* lock_owner_tid) REQUIRES(!Locks::thread_suspend_count_lock_) REQUIRES_SHARED(Locks::mutator_lock_); // Used to implement JDWP's ThreadReference.CurrentContendedMonitor. - static mirror::Object* GetContendedMonitor(Thread* thread) + static ObjPtr<mirror::Object> GetContendedMonitor(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_); // Calls 'callback' once for each lock held in the single stack frame represented by // the current state of 'stack_visitor'. // The abort_on_failure flag allows to not die when the state of the runtime is unorderly. This // is necessary when we have already aborted but want to dump the stack as much as we can. - static void VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::Object*, void*), - void* callback_context, bool abort_on_failure = true) + static void VisitLocks(StackVisitor* stack_visitor, + void (*callback)(ObjPtr<mirror::Object>, void*), + void* callback_context, + bool abort_on_failure = true) REQUIRES_SHARED(Locks::mutator_lock_); static bool IsValidLockWord(LockWord lock_word); template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - mirror::Object* GetObject() REQUIRES_SHARED(Locks::mutator_lock_) { - return obj_.Read<kReadBarrierOption>(); - } + ObjPtr<mirror::Object> GetObject() REQUIRES_SHARED(Locks::mutator_lock_); - void SetObject(mirror::Object* object); + void SetObject(ObjPtr<mirror::Object> object); Thread* GetOwner() const NO_THREAD_SAFETY_ANALYSIS { return owner_; @@ -144,7 +152,7 @@ class Monitor { // Not exclusive because ImageWriter calls this during a Heap::VisitObjects() that // does not allow a thread suspension in the middle. TODO: maybe make this exclusive. // NO_THREAD_SAFETY_ANALYSIS for monitor->monitor_lock_. - static bool Deflate(Thread* self, mirror::Object* obj) + static bool Deflate(Thread* self, ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) NO_THREAD_SAFETY_ANALYSIS; #ifndef __LP64__ @@ -162,9 +170,9 @@ class Monitor { #endif private: - Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) + Monitor(Thread* self, Thread* owner, ObjPtr<mirror::Object> obj, int32_t hash_code) REQUIRES_SHARED(Locks::mutator_lock_); - Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code, MonitorId id) + Monitor(Thread* self, Thread* owner, ObjPtr<mirror::Object> obj, int32_t hash_code, MonitorId id) REQUIRES_SHARED(Locks::mutator_lock_); // Install the monitor into its object, may fail if another thread installs a different monitor @@ -187,7 +195,7 @@ class Monitor { // calling thread must own the lock or the owner must be suspended. There's a race with other // threads inflating the lock, installing hash codes and spurious failures. The caller should // re-read the lock word following the call. - static void Inflate(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) + static void Inflate(Thread* self, Thread* owner, ObjPtr<mirror::Object> obj, int32_t hash_code) REQUIRES_SHARED(Locks::mutator_lock_) NO_THREAD_SAFETY_ANALYSIS; // For m->Install(self) @@ -198,7 +206,7 @@ class Monitor { uint32_t owner_dex_pc) REQUIRES_SHARED(Locks::mutator_lock_); - static void FailedUnlock(mirror::Object* obj, + static void FailedUnlock(ObjPtr<mirror::Object> obj, uint32_t expected_owner_thread_id, uint32_t found_owner_thread_id, Monitor* mon) @@ -224,7 +232,7 @@ class Monitor { REQUIRES(!monitor_lock_) REQUIRES_SHARED(Locks::mutator_lock_); - static void DoNotify(Thread* self, mirror::Object* obj, bool notify_all) + static void DoNotify(Thread* self, ObjPtr<mirror::Object> obj, bool notify_all) REQUIRES_SHARED(Locks::mutator_lock_) NO_THREAD_SAFETY_ANALYSIS; // For mon->Notify. void Notify(Thread* self) @@ -275,11 +283,11 @@ class Monitor { // Support for systrace output of monitor operations. ALWAYS_INLINE static void AtraceMonitorLock(Thread* self, - mirror::Object* obj, + ObjPtr<mirror::Object> obj, bool is_wait) REQUIRES_SHARED(Locks::mutator_lock_); static void AtraceMonitorLockImpl(Thread* self, - mirror::Object* obj, + ObjPtr<mirror::Object> obj, bool is_wait) REQUIRES_SHARED(Locks::mutator_lock_); ALWAYS_INLINE static void AtraceMonitorUnlock(); @@ -375,7 +383,7 @@ class MonitorInfo { MonitorInfo() : owner_(nullptr), entry_count_(0) {} MonitorInfo(const MonitorInfo&) = default; MonitorInfo& operator=(const MonitorInfo&) = default; - explicit MonitorInfo(mirror::Object* o) REQUIRES(Locks::mutator_lock_); + explicit MonitorInfo(ObjPtr<mirror::Object> o) REQUIRES(Locks::mutator_lock_); Thread* owner_; size_t entry_count_; diff --git a/runtime/monitor_objects_stack_visitor.cc b/runtime/monitor_objects_stack_visitor.cc new file mode 100644 index 0000000000..61f4159a90 --- /dev/null +++ b/runtime/monitor_objects_stack_visitor.cc @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "monitor_objects_stack_visitor.h" + +#include "obj_ptr-inl.h" +#include "read_barrier-inl.h" +#include "thread-current-inl.h" + +namespace art { + +bool MonitorObjectsStackVisitor::VisitFrame() { + ArtMethod* m = GetMethod(); + if (m->IsRuntimeMethod()) { + return true; + } + + VisitMethodResult vmrEntry = StartMethod(m, frame_count); + switch (vmrEntry) { + case VisitMethodResult::kContinueMethod: + break; + case VisitMethodResult::kSkipMethod: + return true; + case VisitMethodResult::kEndStackWalk: + return false; + } + + if (frame_count == 0) { + // Top frame, check for blocked state. + + ObjPtr<mirror::Object> monitor_object; + uint32_t lock_owner_tid; + ThreadState state = Monitor::FetchState(GetThread(), + &monitor_object, + &lock_owner_tid); + switch (state) { + case kWaiting: + case kTimedWaiting: + VisitWaitingObject(monitor_object, state); + break; + case kSleeping: + VisitSleepingObject(monitor_object); + break; + + case kBlocked: + case kWaitingForLockInflation: + VisitBlockedOnObject(monitor_object, state, lock_owner_tid); + break; + + default: + break; + } + } + + if (dump_locks) { + // Visit locks, but do not abort on errors. This could trigger a nested abort. + // Skip visiting locks if dump_locks is false as it would cause a bad_mutexes_held in + // RegTypeCache::RegTypeCache due to thread_list_lock. + Monitor::VisitLocks(this, VisitLockedObject, this, false); + } + + ++frame_count; + + VisitMethodResult vmrExit = EndMethod(m); + switch (vmrExit) { + case VisitMethodResult::kContinueMethod: + case VisitMethodResult::kSkipMethod: + return true; + + case VisitMethodResult::kEndStackWalk: + return false; + } + LOG(FATAL) << "Unreachable"; + UNREACHABLE(); +} + +void MonitorObjectsStackVisitor::VisitLockedObject(ObjPtr<mirror::Object> o, void* context) { + MonitorObjectsStackVisitor* self = reinterpret_cast<MonitorObjectsStackVisitor*>(context); + if (o != nullptr) { + if (kUseReadBarrier && Thread::Current()->GetIsGcMarking()) { + // We may call Thread::Dump() in the middle of the CC thread flip and this thread's stack + // may have not been flipped yet and "o" may be a from-space (stale) ref, in which case the + // IdentityHashCode call below will crash. So explicitly mark/forward it here. + o = ReadBarrier::Mark(o.Ptr()); + } + } + self->VisitLockedObject(o); +} + +} // namespace art diff --git a/runtime/monitor_objects_stack_visitor.h b/runtime/monitor_objects_stack_visitor.h index 3968239e8d..8e148aa746 100644 --- a/runtime/monitor_objects_stack_visitor.h +++ b/runtime/monitor_objects_stack_visitor.h @@ -54,70 +54,7 @@ class MonitorObjectsStackVisitor : public StackVisitor { kEndStackWalk, }; - bool VisitFrame() final REQUIRES_SHARED(Locks::mutator_lock_) { - ArtMethod* m = GetMethod(); - if (m->IsRuntimeMethod()) { - return true; - } - - VisitMethodResult vmrEntry = StartMethod(m, frame_count); - switch (vmrEntry) { - case VisitMethodResult::kContinueMethod: - break; - case VisitMethodResult::kSkipMethod: - return true; - case VisitMethodResult::kEndStackWalk: - return false; - } - - if (frame_count == 0) { - // Top frame, check for blocked state. - - mirror::Object* monitor_object; - uint32_t lock_owner_tid; - ThreadState state = Monitor::FetchState(GetThread(), - &monitor_object, - &lock_owner_tid); - switch (state) { - case kWaiting: - case kTimedWaiting: - VisitWaitingObject(monitor_object, state); - break; - case kSleeping: - VisitSleepingObject(monitor_object); - break; - - case kBlocked: - case kWaitingForLockInflation: - VisitBlockedOnObject(monitor_object, state, lock_owner_tid); - break; - - default: - break; - } - } - - if (dump_locks) { - // Visit locks, but do not abort on errors. This could trigger a nested abort. - // Skip visiting locks if dump_locks is false as it would cause a bad_mutexes_held in - // RegTypeCache::RegTypeCache due to thread_list_lock. - Monitor::VisitLocks(this, VisitLockedObject, this, false); - } - - ++frame_count; - - VisitMethodResult vmrExit = EndMethod(m); - switch (vmrExit) { - case VisitMethodResult::kContinueMethod: - case VisitMethodResult::kSkipMethod: - return true; - - case VisitMethodResult::kEndStackWalk: - return false; - } - LOG(FATAL) << "Unreachable"; - UNREACHABLE(); - } + bool VisitFrame() final REQUIRES_SHARED(Locks::mutator_lock_); protected: virtual VisitMethodResult StartMethod(ArtMethod* m, size_t frame_nr) @@ -125,31 +62,22 @@ class MonitorObjectsStackVisitor : public StackVisitor { virtual VisitMethodResult EndMethod(ArtMethod* m) REQUIRES_SHARED(Locks::mutator_lock_) = 0; - virtual void VisitWaitingObject(mirror::Object* obj, ThreadState state) + virtual void VisitWaitingObject(ObjPtr<mirror::Object> obj, ThreadState state) REQUIRES_SHARED(Locks::mutator_lock_) = 0; - virtual void VisitSleepingObject(mirror::Object* obj) + virtual void VisitSleepingObject(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) = 0; - virtual void VisitBlockedOnObject(mirror::Object* obj, ThreadState state, uint32_t owner_tid) + virtual void VisitBlockedOnObject(ObjPtr<mirror::Object> obj, + ThreadState state, + uint32_t owner_tid) REQUIRES_SHARED(Locks::mutator_lock_) = 0; - virtual void VisitLockedObject(mirror::Object* obj) + virtual void VisitLockedObject(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) = 0; size_t frame_count; private: - static void VisitLockedObject(mirror::Object* o, void* context) - REQUIRES_SHARED(Locks::mutator_lock_) { - MonitorObjectsStackVisitor* self = reinterpret_cast<MonitorObjectsStackVisitor*>(context); - if (o != nullptr) { - if (kUseReadBarrier && Thread::Current()->GetIsGcMarking()) { - // We may call Thread::Dump() in the middle of the CC thread flip and this thread's stack - // may have not been flipped yet and "o" may be a from-space (stale) ref, in which case the - // IdentityHashCode call below will crash. So explicitly mark/forward it here. - o = ReadBarrier::Mark(o); - } - } - self->VisitLockedObject(o); - } + static void VisitLockedObject(ObjPtr<mirror::Object> o, void* context) + REQUIRES_SHARED(Locks::mutator_lock_); const bool dump_locks; }; diff --git a/runtime/monitor_pool.cc b/runtime/monitor_pool.cc index cf5934b6a0..b2b00242a7 100644 --- a/runtime/monitor_pool.cc +++ b/runtime/monitor_pool.cc @@ -105,7 +105,9 @@ void MonitorPool::FreeInternal() { } } -Monitor* MonitorPool::CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, +Monitor* MonitorPool::CreateMonitorInPool(Thread* self, + Thread* owner, + ObjPtr<mirror::Object> obj, int32_t hash_code) REQUIRES_SHARED(Locks::mutator_lock_) { // We are gonna allocate, so acquire the writer lock. diff --git a/runtime/monitor_pool.h b/runtime/monitor_pool.h index c6b0b0b86e..4521a22c6f 100644 --- a/runtime/monitor_pool.h +++ b/runtime/monitor_pool.h @@ -42,7 +42,10 @@ class MonitorPool { #endif } - static Monitor* CreateMonitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) + static Monitor* CreateMonitor(Thread* self, + Thread* owner, + ObjPtr<mirror::Object> obj, + int32_t hash_code) REQUIRES_SHARED(Locks::mutator_lock_) { #ifndef __LP64__ Monitor* mon = new Monitor(self, owner, obj, hash_code); @@ -122,7 +125,10 @@ class MonitorPool { // so ignore thead-safety analysis. void FreeInternal() NO_THREAD_SAFETY_ANALYSIS; - Monitor* CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) + Monitor* CreateMonitorInPool(Thread* self, + Thread* owner, + ObjPtr<mirror::Object> obj, + int32_t hash_code) REQUIRES_SHARED(Locks::mutator_lock_); void ReleaseMonitorToPool(Thread* self, Monitor* monitor); diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc index a4f3df29c9..4a60c045cc 100644 --- a/runtime/runtime_callbacks_test.cc +++ b/runtime/runtime_callbacks_test.cc @@ -37,9 +37,9 @@ #include "handle_scope-inl.h" #include "mirror/class-inl.h" #include "mirror/class_loader.h" -#include "monitor.h" +#include "monitor-inl.h" #include "nativehelper/scoped_local_ref.h" -#include "obj_ptr.h" +#include "obj_ptr-inl.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" #include "thread-inl.h" @@ -443,7 +443,8 @@ class MonitorWaitCallbacksTest : public RuntimeCallbacksTest { } struct Callback : public MonitorCallback { - bool IsInterestingObject(mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) { + bool IsInterestingObject(ObjPtr<mirror::Object> obj) + REQUIRES_SHARED(art::Locks::mutator_lock_) { if (!obj->IsClass()) { return false; } @@ -453,7 +454,8 @@ class MonitorWaitCallbacksTest : public RuntimeCallbacksTest { return ref_ == test; } - void SetInterestingObject(mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) { + void SetInterestingObject(ObjPtr<mirror::Object> obj) + REQUIRES_SHARED(art::Locks::mutator_lock_) { std::lock_guard<std::mutex> lock(ref_guard_); ObjPtr<mirror::Class> k = obj->AsClass(); ref_ = { &k->GetDexFile(), k->GetDexClassDefIndex() }; @@ -501,11 +503,11 @@ TEST_F(MonitorWaitCallbacksTest, WaitUnlocked) { { ScopedObjectAccess soa(self); cb_.SetInterestingObject( - soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections).Ptr()); + soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections)); Monitor::Wait( self, // Just a random class - soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections).Ptr(), + soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections), /*ms=*/0, /*ns=*/0, /*interruptShouldThrow=*/false, diff --git a/runtime/thread.cc b/runtime/thread.cc index bdbb69777d..ffdea8a047 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -2014,17 +2014,17 @@ struct StackDumpVisitor : public MonitorObjectsStackVisitor { return VisitMethodResult::kContinueMethod; } - void VisitWaitingObject(mirror::Object* obj, ThreadState state ATTRIBUTE_UNUSED) + void VisitWaitingObject(ObjPtr<mirror::Object> obj, ThreadState state ATTRIBUTE_UNUSED) override REQUIRES_SHARED(Locks::mutator_lock_) { PrintObject(obj, " - waiting on ", ThreadList::kInvalidThreadId); } - void VisitSleepingObject(mirror::Object* obj) + void VisitSleepingObject(ObjPtr<mirror::Object> obj) override REQUIRES_SHARED(Locks::mutator_lock_) { PrintObject(obj, " - sleeping on ", ThreadList::kInvalidThreadId); } - void VisitBlockedOnObject(mirror::Object* obj, + void VisitBlockedOnObject(ObjPtr<mirror::Object> obj, ThreadState state, uint32_t owner_tid) override @@ -2045,13 +2045,13 @@ struct StackDumpVisitor : public MonitorObjectsStackVisitor { } PrintObject(obj, msg, owner_tid); } - void VisitLockedObject(mirror::Object* obj) + void VisitLockedObject(ObjPtr<mirror::Object> obj) override REQUIRES_SHARED(Locks::mutator_lock_) { PrintObject(obj, " - locked ", ThreadList::kInvalidThreadId); } - void PrintObject(mirror::Object* obj, + void PrintObject(ObjPtr<mirror::Object> obj, const char* msg, uint32_t owner_tid) REQUIRES_SHARED(Locks::mutator_lock_) { if (obj == nullptr) { @@ -2062,7 +2062,7 @@ struct StackDumpVisitor : public MonitorObjectsStackVisitor { // Getting the identity hashcode here would result in lock inflation and suspension of the // current thread, which isn't safe if this is the only runnable thread. os << msg << StringPrintf("<@addr=0x%" PRIxPTR "> (a %s)", - reinterpret_cast<intptr_t>(obj), + reinterpret_cast<intptr_t>(obj.Ptr()), obj->PrettyTypeOf().c_str()); } else { // - waiting on <0x6008c468> (a java.lang.Class<java.lang.ref.ReferenceQueue>) @@ -3006,24 +3006,24 @@ jobjectArray Thread::CreateAnnotatedStackTrace(const ScopedObjectAccessAlreadyRu return VisitMethodResult::kContinueMethod; } - void VisitWaitingObject(mirror::Object* obj, ThreadState state ATTRIBUTE_UNUSED) + void VisitWaitingObject(ObjPtr<mirror::Object> obj, ThreadState state ATTRIBUTE_UNUSED) override REQUIRES_SHARED(Locks::mutator_lock_) { wait_jobject_.reset(soaa_.AddLocalReference<jobject>(obj)); } - void VisitSleepingObject(mirror::Object* obj) + void VisitSleepingObject(ObjPtr<mirror::Object> obj) override REQUIRES_SHARED(Locks::mutator_lock_) { wait_jobject_.reset(soaa_.AddLocalReference<jobject>(obj)); } - void VisitBlockedOnObject(mirror::Object* obj, + void VisitBlockedOnObject(ObjPtr<mirror::Object> obj, ThreadState state ATTRIBUTE_UNUSED, uint32_t owner_tid ATTRIBUTE_UNUSED) override REQUIRES_SHARED(Locks::mutator_lock_) { block_jobject_.reset(soaa_.AddLocalReference<jobject>(obj)); } - void VisitLockedObject(mirror::Object* obj) + void VisitLockedObject(ObjPtr<mirror::Object> obj) override REQUIRES_SHARED(Locks::mutator_lock_) { frame_lock_objects_.emplace_back(soaa_.Env(), soaa_.AddLocalReference<jobject>(obj)); diff --git a/test/167-visit-locks/visit_locks.cc b/test/167-visit-locks/visit_locks.cc index 8955f5a08e..f72b5771ac 100644 --- a/test/167-visit-locks/visit_locks.cc +++ b/test/167-visit-locks/visit_locks.cc @@ -27,6 +27,7 @@ #include "mirror/object-inl.h" #include "mirror/string.h" #include "monitor.h" +#include "obj_ptr-inl.h" #include "scoped_thread_state_change-inl.h" #include "stack.h" #include "thread-current-inl.h" @@ -59,7 +60,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testVisitLocks(JNIEnv*, jclass) { return true; } - static void Callback(mirror::Object* obj, void*) REQUIRES_SHARED(Locks::mutator_lock_) { + static void Callback(ObjPtr<mirror::Object> obj, void*) REQUIRES_SHARED(Locks::mutator_lock_) { CHECK(obj != nullptr); CHECK(obj->IsString()); std::cerr << obj->AsString()->ToModifiedUtf8() << std::endl; |