Global lock levels.
Introduce the notion of the mutators/GC being a shared-exclusive (aka
reader-writer) lock. Introduce globally ordered locks, analysable by
annotalysis, statically at compile time. Add locking attributes to
methods.
More subtly, remove the heap_lock_ and split between various locks that
are held for smaller periods (where work doesn't get blocked). Remove
buggy Dalvik style thread transitions. Make GC use CMS in all cases when
concurrent is enabled. Fix bug where suspend counts rather than debug
suspend counts were sent to JDWP. Move the PathClassLoader to
WellKnownClasses. In debugger refactor calls to send request and
possibly suspend. Break apart different VmWait thread states. Move
identity hash code to a shared method.
Change-Id: Icdbfc3ce3fcccd14341860ac7305d8e97b51f5c6
diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc
index d806d71..d0c87be 100644
--- a/src/hprof/hprof.cc
+++ b/src/hprof/hprof.cc
@@ -47,7 +47,7 @@
#include "object_utils.h"
#include "os.h"
#include "safe_map.h"
-#include "scoped_heap_lock.h"
+#include "scoped_thread_state_change.h"
#include "space.h"
#include "stringprintf.h"
#include "thread_list.h"
@@ -165,8 +165,8 @@
typedef HprofId HprofStringId;
typedef HprofId HprofObjectId;
typedef HprofId HprofClassObjectId;
-typedef std::set<const Class*> ClassSet;
-typedef std::set<const Class*>::iterator ClassSetIterator;
+typedef std::set<Class*> ClassSet;
+typedef std::set<Class*>::iterator ClassSetIterator;
typedef SafeMap<std::string, size_t> StringMap;
typedef SafeMap<std::string, size_t>::iterator StringMapIterator;
@@ -401,11 +401,16 @@
free(body_data_ptr_);
}
- void Dump() {
+ void Dump()
+ EXCLUSIVE_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_)
+ LOCKS_EXCLUDED(GlobalSynchronization::heap_bitmap_lock_) {
// Walk the roots and the heap.
current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
Runtime::Current()->VisitRoots(RootVisitor, this);
- Runtime::Current()->GetHeap()->GetLiveBitmap()->Walk(HeapBitmapCallback, this);
+ {
+ ReaderMutexLock mu(*GlobalSynchronization::heap_bitmap_lock_);
+ Runtime::Current()->GetHeap()->GetLiveBitmap()->Walk(HeapBitmapCallback, this);
+ }
current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_END, HPROF_TIME);
current_record_.Flush();
fflush(body_fp_);
@@ -464,27 +469,29 @@
}
private:
- static void RootVisitor(const Object* obj, void* arg) {
+ static void RootVisitor(const Object* obj, void* arg)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
CHECK(arg != NULL);
Hprof* hprof = reinterpret_cast<Hprof*>(arg);
hprof->VisitRoot(obj);
}
- static void HeapBitmapCallback(Object* obj, void* arg) {
+ static void HeapBitmapCallback(Object* obj, void* arg)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
CHECK(obj != NULL);
CHECK(arg != NULL);
Hprof* hprof = reinterpret_cast<Hprof*>(arg);
hprof->DumpHeapObject(obj);
}
- void VisitRoot(const Object* obj);
+ void VisitRoot(const Object* obj) SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
- int DumpHeapObject(const Object* obj);
+ int DumpHeapObject(Object* obj) SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
void Finish() {
}
- int WriteClassTable() {
+ int WriteClassTable() SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
HprofRecord* rec = ¤t_record_;
uint32_t nextSerialNumber = 1;
@@ -551,7 +558,8 @@
int MarkRootObject(const Object* obj, jobject jniObj);
- HprofClassObjectId LookupClassId(const Class* c) {
+ HprofClassObjectId LookupClassId(Class* c)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
if (c == NULL) {
// c is the superclass of java.lang.Object or a primitive
return (HprofClassObjectId)0;
@@ -585,7 +593,8 @@
return id;
}
- HprofStringId LookupClassNameId(const Class* c) {
+ HprofStringId LookupClassNameId(const Class* c)
+ SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
return LookupStringId(PrettyDescriptor(c));
}
@@ -807,7 +816,7 @@
return HPROF_NULL_STACK_TRACE;
}
-int Hprof::DumpHeapObject(const Object* obj) {
+int Hprof::DumpHeapObject(Object* obj) {
HprofRecord* rec = ¤t_record_;
HprofHeapId desiredHeap = false ? HPROF_HEAP_ZYGOTE : HPROF_HEAP_APP; // TODO: zygote objects?
@@ -847,7 +856,7 @@
// allocated which hasn't been initialized yet.
} else {
if (obj->IsClass()) {
- const Class* thisClass = obj->AsClass();
+ Class* thisClass = obj->AsClass();
// obj is a ClassObject.
size_t sFieldCount = thisClass->NumStaticFields();
if (sFieldCount != 0) {
@@ -1053,15 +1062,11 @@
// Otherwise, "filename" is used to create an output file.
void DumpHeap(const char* filename, int fd, bool direct_to_ddms) {
CHECK(filename != NULL);
- ScopedHeapLock heap_lock;
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- ThreadList* thread_list = Runtime::Current()->GetThreadList();
- thread_list->SuspendAll();
-
+ Runtime::Current()->GetThreadList()->SuspendAll();
Hprof hprof(filename, fd, direct_to_ddms);
hprof.Dump();
- thread_list->ResumeAll();
+ Runtime::Current()->GetThreadList()->ResumeAll();
}
} // namespace hprof