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/Android.mk b/Android.mk
index c556081..d0d83e6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -69,6 +69,9 @@
 
 ART_TARGET_TEST_DEPENDENCIES += $(TARGET_OUT_EXECUTABLES)/oat_process $(TARGET_OUT_EXECUTABLES)/oat_processd
 
+# Switch this to "oat_process" to run an optimized build.
+OAT_PROCESS=oat_processd
+
 ########################################################################
 # host test targets
 
@@ -144,7 +147,7 @@
 test-art-target-oat-process-am: $(call art-cache-oat,system/framework/am.jar) test-art-target-sync
 	adb remount
 	adb sync
-	adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process /system/bin com.android.commands.am.Am start http://android.com && touch $(ART_TEST_DIR)/test-art-target-process-am"
+	adb shell sh -c "export CLASSPATH=/system/framework/am.jar && $(OAT_PROCESS) /system/bin/app_process /system/bin com.android.commands.am.Am start http://android.com && touch $(ART_TEST_DIR)/test-art-target-process-am"
 	$(hide) (adb pull $(ART_TEST_DIR)/test-art-target-process-am /tmp/ && echo test-art-target-process-am PASSED) || echo test-art-target-process-am FAILED
 	$(hide) rm /tmp/test-art-target-process-am
 
@@ -156,18 +159,18 @@
 	mv $(TARGET_OUT_DATA)/art-cache/classes.dex $(ART_CACHE_OUT)/system@app@Calculator.apk@classes.dex.`unzip -lv $(TARGET_OUT_APPS)/Calculator.apk classes.dex | grep classes.dex | sed -E 's/.* ([0-9a-f]+)  classes.dex/\1/'` # note this is extracting the crc32 that is needed as the file extension
 	adb remount
 	adb sync
-	if [ "`adb shell getprop wrap.com.android.calculator2 | tr -d '\r'`" = "oat_processd" ]; then \
+	if [ "`adb shell getprop wrap.com.android.calculator2 | tr -d '\r'`" = "$(OAT_PROCESS)" ]; then \
 	  echo wrap.com.android.calculator2 already set; \
 	  adb shell start; \
 	else \
 	  echo Setting wrap.com.android.calculator2 and restarting runtime; \
-	  adb shell setprop wrap.com.android.calculator2 "oat_processd"; \
+	  adb shell setprop wrap.com.android.calculator2 "$(OAT_PROCESS)"; \
 	  adb shell stop; \
 	  adb shell start; \
 	  sleep 30; \
 	fi
 	adb shell kill `adb shell ps | fgrep com.android.calculator2 | sed -e 's/[^ ]* *\([0-9]*\).*/\1/'`
-	adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process /system/bin com.android.commands.am.Am start -a android.intent.action.MAIN -n com.android.calculator2/.Calculator && touch $(ART_TEST_DIR)/test-art-target-process-Calculator"
+	adb shell sh -c "export CLASSPATH=/system/framework/am.jar && $(OAT_PROCESS) /system/bin/app_process /system/bin com.android.commands.am.Am start -a android.intent.action.MAIN -n com.android.calculator2/.Calculator && touch $(ART_TEST_DIR)/test-art-target-process-Calculator"
 	$(hide) (adb pull $(ART_TEST_DIR)/test-art-target-process-Calculator /tmp/ && echo test-art-target-process-Calculator PASSED) || echo test-art-target-process-Calculator FAILED
 	$(hide) rm /tmp/test-art-target-process-Calculator
 
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);