ObjPtr<>-ify Monitor/-Pool.
Test: m test-art-host-gtest
Test: testrunner.py --host
Bug: 31113334
Change-Id: I2d2ebc5ef56e73e5678e0cfcd84c479611dfcca8
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc
index b41edc5..2c5ebfe 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 @@
}
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 5e934df..b96c92a 100644
--- a/openjdkjvmti/ti_stack.cc
+++ b/openjdkjvmti/ti_stack.cc
@@ -844,18 +844,17 @@
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 5ed3acc..0cc7d29 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -141,6 +141,7 @@
"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 a38c9ab..c5b111f 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -900,7 +900,7 @@
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 @@
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 4bcce21..87286cf 100644
--- a/runtime/entrypoints/quick/quick_lock_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_lock_entrypoints.cc
@@ -29,8 +29,8 @@
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 @@
<< "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 e203658..56e1807 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -79,11 +79,11 @@
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 2d69206..fea6eb5 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -153,11 +153,11 @@
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 0000000..e8ffafa
--- /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 6abc8d7..676bceb 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
}
}
-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 @@
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 @@
}
// 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 @@
}
}
-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 @@
}
}
-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 @@
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 @@
}
}
-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 @@
}
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 c1f84e9..4187f27 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 @@
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 @@
// 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 @@
#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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 0000000..61f4159
--- /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 3968239..8e148aa 100644
--- a/runtime/monitor_objects_stack_visitor.h
+++ b/runtime/monitor_objects_stack_visitor.h
@@ -54,70 +54,7 @@
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 @@
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 cf5934b..b2b0024 100644
--- a/runtime/monitor_pool.cc
+++ b/runtime/monitor_pool.cc
@@ -105,7 +105,9 @@
}
}
-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 c6b0b0b..4521a22 100644
--- a/runtime/monitor_pool.h
+++ b/runtime/monitor_pool.h
@@ -42,7 +42,10 @@
#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 @@
// 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 a4f3df2..4a60c04 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 @@
}
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 @@
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 @@
{
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 bdbb697..ffdea8a 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2014,17 +2014,17 @@
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 @@
}
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 @@
// 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 @@
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 8955f5a..f72b577 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 @@
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;