diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-02-07 12:18:39 -0800 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2014-02-08 15:23:36 -0800 |
commit | 412c7fced915fc8d4d5e4166e977d55c809168a6 (patch) | |
tree | b8efee7f46a440f3e89765b1e9b2aa6454839c87 /runtime/debugger.cc | |
parent | 109e2b34799a377a0407781fc32ec1ec607d6c41 (diff) | |
download | art-412c7fced915fc8d4d5e4166e977d55c809168a6.tar.gz art-412c7fced915fc8d4d5e4166e977d55c809168a6.tar.bz2 art-412c7fced915fc8d4d5e4166e977d55c809168a6.zip |
Make debugger / jdwp compaction safe.
Fixed GetInstances, GetReferringObjects, CountInstances to use
VisitObjects instead of the live bitmap.
We now treat the object registry as system weaks and update the
objects when/if they move. Also added the recent_allocation_records_
as roots.
Bug: 12936165
Change-Id: I615c289efbf2977ceab5c4ffa73d216d799e6e33
Diffstat (limited to 'runtime/debugger.cc')
-rw-r--r-- | runtime/debugger.cc | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 99e7867ffb..8280c7c9a6 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -63,6 +63,9 @@ struct AllocRecordStackTraceElement { mirror::ArtMethod* method; uint32_t dex_pc; + AllocRecordStackTraceElement() : method(nullptr), dex_pc(0) { + } + int32_t LineNumber() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return MethodHelper(method).GetLineNumFromDexPC(dex_pc); } @@ -81,6 +84,20 @@ struct AllocRecord { } return depth; } + + void UpdateObjectPointers(RootVisitor* visitor, void* arg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (type != nullptr) { + type = down_cast<mirror::Class*>(visitor(type, arg)); + } + for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) { + mirror::ArtMethod*& m = stack[stack_frame].method; + if (m == nullptr) { + break; + } + m = down_cast<mirror::ArtMethod*>(visitor(m, arg)); + } + } }; struct Breakpoint { @@ -775,6 +792,8 @@ JDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id, JDWP::ObjectI JDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids, std::vector<uint64_t>& counts) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + gc::Heap* heap = Runtime::Current()->GetHeap(); + heap->CollectGarbage(false); std::vector<mirror::Class*> classes; counts.clear(); for (size_t i = 0; i < class_ids.size(); ++i) { @@ -786,19 +805,20 @@ JDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class classes.push_back(c); counts.push_back(0); } - - Runtime::Current()->GetHeap()->CountInstances(classes, false, &counts[0]); + heap->CountInstances(classes, false, &counts[0]); return JDWP::ERR_NONE; } JDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, std::vector<JDWP::ObjectId>& instances) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + gc::Heap* heap = Runtime::Current()->GetHeap(); + // We only want reachable instances, so do a GC. + heap->CollectGarbage(false); JDWP::JdwpError status; mirror::Class* c = DecodeClass(class_id, status); - if (c == NULL) { + if (c == nullptr) { return status; } - std::vector<mirror::Object*> raw_instances; Runtime::Current()->GetHeap()->GetInstances(c, max_count, raw_instances); for (size_t i = 0; i < raw_instances.size(); ++i) { @@ -810,13 +830,14 @@ JDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, s JDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count, std::vector<JDWP::ObjectId>& referring_objects) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + gc::Heap* heap = Runtime::Current()->GetHeap(); + heap->CollectGarbage(false); mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id); if (o == NULL || o == ObjectRegistry::kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } - std::vector<mirror::Object*> raw_instances; - Runtime::Current()->GetHeap()->GetReferringObjects(o, max_count, raw_instances); + heap->GetReferringObjects(o, max_count, raw_instances); for (size_t i = 0; i < raw_instances.size(); ++i) { referring_objects.push_back(gRegistry->Add(raw_instances[i])); } @@ -3772,6 +3793,37 @@ void Dbg::DumpRecentAllocations() { } } +void Dbg::UpdateObjectPointers(RootVisitor* visitor, void* arg) { + { + MutexLock mu(Thread::Current(), gAllocTrackerLock); + if (recent_allocation_records_ != nullptr) { + size_t i = HeadIndex(); + size_t count = gAllocRecordCount; + while (count--) { + AllocRecord* record = &recent_allocation_records_[i]; + DCHECK(record != nullptr); + record->UpdateObjectPointers(visitor, arg); + i = (i + 1) & (gAllocRecordMax - 1); + } + } + } + if (gRegistry != nullptr) { + gRegistry->UpdateObjectPointers(visitor, arg); + } +} + +void Dbg::AllowNewObjectRegistryObjects() { + if (gRegistry != nullptr) { + gRegistry->AllowNewObjects(); + } +} + +void Dbg::DisallowNewObjectRegistryObjects() { + if (gRegistry != nullptr) { + gRegistry->DisallowNewObjects(); + } +} + class StringTable { public: StringTable() { |