Implement as much of VMDebug as we can reasonably do right now.
No hprof and no method tracing, but everything else.
Change-Id: Ifccd1f08e31f34b947c30f1211db788aae674d81
diff --git a/src/heap.cc b/src/heap.cc
index 094790a..4d8d176 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -40,6 +40,8 @@
Mutex* Heap::lock_ = NULL;
+bool Heap::verify_objects_ = false;
+
class ScopedHeapLock {
public:
ScopedHeapLock() {
@@ -169,8 +171,6 @@
return true;
}
-bool Heap::verify_objects_ = false;
-
#if VERIFY_OBJECT_ENABLED
void Heap::VerifyObject(const Object* obj) {
if (!verify_objects_) {
@@ -237,6 +237,16 @@
DCHECK_NE(size, 0u);
num_bytes_allocated_ += size;
num_objects_allocated_ += 1;
+
+ if (Runtime::Current()->HasStatsEnabled()) {
+ RuntimeStats* global_stats = Runtime::Current()->GetStats();
+ RuntimeStats* thread_stats = Thread::Current()->GetStats();
+ ++global_stats->allocated_objects;
+ ++thread_stats->allocated_objects;
+ global_stats->allocated_bytes += size;
+ thread_stats->allocated_bytes += size;
+ }
+
live_bitmap_->Set(obj);
}
@@ -253,6 +263,15 @@
if (num_objects_allocated_ > 0) {
num_objects_allocated_ -= 1;
}
+
+ if (Runtime::Current()->HasStatsEnabled()) {
+ RuntimeStats* global_stats = Runtime::Current()->GetStats();
+ RuntimeStats* thread_stats = Thread::Current()->GetStats();
+ ++global_stats->freed_objects;
+ ++thread_stats->freed_objects;
+ global_stats->freed_bytes += size;
+ thread_stats->freed_bytes += size;
+ }
}
void Heap::RecordImageAllocations(Space* space) {
@@ -307,6 +326,10 @@
// Another failure. Our thread was starved or there may be too many
// live objects. Try a foreground GC. This will have no effect if
// the concurrent GC is already running.
+ if (Runtime::Current()->HasStatsEnabled()) {
+ ++Runtime::Current()->GetStats()->gc_for_alloc_count;
+ ++Thread::Current()->GetStats()->gc_for_alloc_count;
+ }
CollectGarbageInternal();
ptr = space->AllocWithoutGrowth(size);
if (ptr != NULL) {
@@ -365,6 +388,46 @@
return 0;
}
+class InstanceCounter {
+ public:
+ InstanceCounter(Class* c, bool count_assignable)
+ : class_(c), count_assignable_(count_assignable), count_(0) {
+ }
+
+ size_t GetCount() {
+ return count_;
+ }
+
+ static void Callback(Object* o, void* arg) {
+ reinterpret_cast<InstanceCounter*>(arg)->VisitInstance(o);
+ }
+
+ private:
+ void VisitInstance(Object* o) {
+ Class* instance_class = o->GetClass();
+ if (count_assignable_) {
+ if (instance_class == class_) {
+ ++count_;
+ }
+ } else {
+ if (instance_class != NULL && class_->IsAssignableFrom(instance_class)) {
+ ++count_;
+ }
+ }
+ }
+
+ Class* class_;
+ bool count_assignable_;
+ size_t count_;
+};
+
+int64_t Heap::CountInstances(Class* c, bool count_assignable) {
+ ScopedHeapLock lock;
+ InstanceCounter counter(c, count_assignable);
+ live_bitmap_->Walk(InstanceCounter::Callback, &counter);
+ return counter.GetCount();
+}
+
void Heap::CollectGarbage() {
ScopedHeapLock lock;
CollectGarbageInternal();