Make it easier to run an optimized build, turn the GC timings back on, and remove some unnecessary code.
The Class* field is a regular instance field now, so no need to scan it twice.
We do our null checking in ScanObject, so we don't need to duplicate the checks
in each child.
Also count the number of class, array, and other objects we scan.
Change-Id: I9034708d5e0e1edffaccf3cad4785c5fccf3b38e
diff --git a/src/heap.cc b/src/heap.cc
index 40bc673..d87c79c 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -61,7 +61,7 @@
is_verbose_gc_ = is_verbose_gc;
const Runtime* runtime = Runtime::Current();
- if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
+ if (Heap::IsVerboseHeap() || runtime->IsVerboseStartup()) {
LOG(INFO) << "Heap::Init entering";
}
@@ -133,7 +133,7 @@
// make it clear that you can't use locks during heap initialization.
lock_ = new Mutex("Heap lock");
- if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
+ if (Heap::IsVerboseHeap() || runtime->IsVerboseStartup()) {
LOG(INFO) << "Heap::Init exiting";
}
}
@@ -289,7 +289,7 @@
void Heap::RecordImageAllocations(Space* space) {
const Runtime* runtime = Runtime::Current();
- if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
+ if (Heap::IsVerboseHeap() || runtime->IsVerboseStartup()) {
LOG(INFO) << "Heap::RecordImageAllocations entering";
}
DCHECK(!Runtime::Current()->IsStarted());
@@ -302,7 +302,7 @@
live_bitmap_->Set(obj);
current += RoundUp(obj->SizeOf(), kObjectAlignment);
}
- if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
+ if (Heap::IsVerboseHeap() || runtime->IsVerboseStartup()) {
LOG(INFO) << "Heap::RecordImageAllocations exiting";
}
}
@@ -369,7 +369,7 @@
// OLD-TODO: may want to grow a little bit more so that the amount of
// free space is equal to the old free space + the
// utilization slop for the new allocation.
- if (is_verbose_gc_) {
+ if (Heap::IsVerboseGc()) {
LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB
<< " for " << size << "-byte allocation";
}
@@ -383,7 +383,7 @@
// cleared before throwing an OOME.
// OLD-TODO: wait for the finalizers from the previous GC to finish
- if (is_verbose_gc_) {
+ if (Heap::IsVerboseGc()) {
LOG(INFO) << "Forcing collection of SoftReferences for "
<< size << "-byte allocation";
}
@@ -521,14 +521,14 @@
size_t percentFree = 100 - static_cast<size_t>(100.0f * float(num_bytes_allocated_) / total);
uint32_t duration = (t1 - t0)/1000/1000;
- if (is_verbose_gc_) {
+ if (Heap::IsVerboseGc()) {
LOG(INFO) << "GC freed " << (is_small ? "<" : "") << kib_freed << "KiB, "
<< percentFree << "% free "
<< (num_bytes_allocated_/1024) << "KiB/" << (total/1024) << "KiB, "
<< "paused " << duration << "ms";
}
Dbg::GcDidFinish();
- if (is_verbose_heap_) {
+ if (Heap::IsVerboseHeap()) {
timings.Dump();
}
}
@@ -568,7 +568,7 @@
void Heap::SetIdealFootprint(size_t max_allowed_footprint)
{
if (max_allowed_footprint > Heap::growth_size_) {
- if (is_verbose_gc_) {
+ if (Heap::IsVerboseGc()) {
LOG(INFO) << "Clamp target GC heap from " << max_allowed_footprint
<< " to " << Heap::growth_size_;
}
diff --git a/src/heap.h b/src/heap.h
index 829bbb2..932d490 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -52,7 +52,7 @@
static void Destroy();
static bool IsVerboseHeap() {
- return is_verbose_heap_;
+ return is_verbose_heap_ || is_verbose_gc_ /* TODO: remove when pause times are down */;
}
static bool IsVerboseGc() {
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index 4cc6b22..6b565a1 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -218,6 +218,9 @@
// Scans the header, static field references, and interface pointers
// of a class object.
inline void MarkSweep::ScanClass(const Object* obj) {
+#ifndef NDEBUG
+ ++class_count_;
+#endif
ScanInstanceFields(obj);
ScanStaticFields(obj->AsClass());
}
@@ -225,8 +228,9 @@
// Scans the header of all array objects. If the array object is
// specialized to a reference type, scans the array data as well.
inline void MarkSweep::ScanArray(const Object* obj) {
- DCHECK(obj != NULL);
- DCHECK(obj->GetClass() != NULL);
+#ifndef NDEBUG
+ ++array_count_;
+#endif
MarkObject(obj->GetClass());
if (obj->IsObjectArray()) {
const ObjectArray<Object>* array = obj->AsObjectArray<Object>();
@@ -267,12 +271,11 @@
// scanned object is a reference subclass, it is scheduled for later
// processing.
inline void MarkSweep::ScanOther(const Object* obj) {
- DCHECK(obj != NULL);
- Class* klass = obj->GetClass();
- DCHECK(klass != NULL);
- MarkObject(klass);
+#ifndef NDEBUG
+ ++other_count_;
+#endif
ScanInstanceFields(obj);
- if (klass->IsReferenceClass()) {
+ if (obj->GetClass()->IsReferenceClass()) {
DelayReferenceReferent(const_cast<Object*>(obj));
}
}
@@ -423,6 +426,11 @@
}
MarkSweep::~MarkSweep() {
+#ifndef NDEBUG
+ if (Heap::IsVerboseHeap()) {
+ LOG(INFO) << "MarkSweep scanned classes=" << class_count_ << " arrays=" << array_count_ << " other=" << other_count_;
+ }
+#endif
delete mark_stack_;
mark_bitmap_->Clear();
}
diff --git a/src/mark_sweep.h b/src/mark_sweep.h
index 8c37456..22aad15 100644
--- a/src/mark_sweep.h
+++ b/src/mark_sweep.h
@@ -22,7 +22,8 @@
weak_reference_list_(NULL),
finalizer_reference_list_(NULL),
phantom_reference_list_(NULL),
- cleared_reference_list_(NULL) {
+ cleared_reference_list_(NULL),
+ class_count_(0), array_count_(0), other_count_(0) {
}
~MarkSweep();
@@ -138,6 +139,10 @@
Object* cleared_reference_list_;
+ size_t class_count_;
+ size_t array_count_;
+ size_t other_count_;
+
friend class InternTableEntryIsUnmarked;
DISALLOW_COPY_AND_ASSIGN(MarkSweep);