Compute "scanned bytes" GC metrics in ART's CMC collector.

Test: ART_USE_READ_BARRIER=false \
        m test-art-host-gtest-art_runtime_tests
Bug: 270957146
Bug: 270391874
Change-Id: Ie64ed1c89774676af58a47caa7e697474bbeaaf4
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index 03e8bdd..3c2606a 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -587,6 +587,7 @@
   moving_first_objs_count_ = 0;
   non_moving_first_objs_count_ = 0;
   black_page_count_ = 0;
+  bytes_scanned_ = 0;
   freed_objects_ = 0;
   // The first buffer is used by gc-thread.
   compaction_buffer_counter_ = 1;
@@ -2266,7 +2267,9 @@
              && obj->GetClass<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr) {
         // Try to keep instructions which access class instance together to
         // avoid reloading the pointer from object.
-        size_t obj_size = RoundUp(obj->SizeOf(), kAlignment);
+        size_t obj_size = obj->SizeOf();
+        bytes_scanned_ += obj_size;
+        obj_size = RoundUp(obj_size, kAlignment);
         UpdateClassAfterObjectMap(obj);
         if (first_obj == nullptr) {
           first_obj = obj;
@@ -3921,11 +3924,12 @@
   return words * kAlignment;
 }
 
-void MarkCompact::UpdateLivenessInfo(mirror::Object* obj) {
+void MarkCompact::UpdateLivenessInfo(mirror::Object* obj, size_t obj_size) {
   DCHECK(obj != nullptr);
+  DCHECK_EQ(obj_size, obj->SizeOf<kDefaultVerifyFlags>());
   uintptr_t obj_begin = reinterpret_cast<uintptr_t>(obj);
   UpdateClassAfterObjectMap(obj);
-  size_t size = RoundUp(obj->SizeOf<kDefaultVerifyFlags>(), kAlignment);
+  size_t size = RoundUp(obj_size, kAlignment);
   uintptr_t bit_index = live_words_bitmap_->SetLiveWords(obj_begin, size);
   size_t chunk_idx = (obj_begin - live_words_bitmap_->Begin()) / kOffsetChunkSize;
   // Compute the bit-index within the chunk-info vector word.
@@ -3944,10 +3948,16 @@
 
 template <bool kUpdateLiveWords>
 void MarkCompact::ScanObject(mirror::Object* obj) {
+  // The size of `obj` is used both here (to update `bytes_scanned_`) and in
+  // `UpdateLivenessInfo`. As fetching this value can be expensive, do it once
+  // here and pass that information to `UpdateLivenessInfo`.
+  size_t obj_size = obj->SizeOf<kDefaultVerifyFlags>();
+  bytes_scanned_ += obj_size;
+
   RefFieldsVisitor visitor(this);
   DCHECK(IsMarked(obj)) << "Scanning marked object " << obj << "\n" << heap_->DumpSpaces();
   if (kUpdateLiveWords && moving_space_bitmap_->HasAddress(obj)) {
-    UpdateLivenessInfo(obj);
+    UpdateLivenessInfo(obj, obj_size);
   }
   obj->VisitReferences(visitor, visitor);
 }
@@ -4132,6 +4142,7 @@
 }
 
 void MarkCompact::FinishPhase() {
+  GetCurrentIteration()->SetScannedBytes(bytes_scanned_);
   bool is_zygote = Runtime::Current()->IsZygote();
   compacting_ = false;
   minor_fault_initialized_ = !is_zygote && uffd_minor_fault_supported_;
diff --git a/runtime/gc/collector/mark_compact.h b/runtime/gc/collector/mark_compact.h
index 3504ad3..d73f40d 100644
--- a/runtime/gc/collector/mark_compact.h
+++ b/runtime/gc/collector/mark_compact.h
@@ -422,7 +422,8 @@
   // Update the live-words bitmap as well as add the object size to the
   // chunk-info vector. Both are required for computation of post-compact addresses.
   // Also updates freed_objects_ counter.
-  void UpdateLivenessInfo(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+  void UpdateLivenessInfo(mirror::Object* obj, size_t obj_size)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   void ProcessReferences(Thread* self)
       REQUIRES_SHARED(Locks::mutator_lock_)
@@ -655,6 +656,8 @@
   size_t vector_length_;
   size_t live_stack_freeze_size_;
 
+  uint64_t bytes_scanned_;
+
   // For every page in the to-space (post-compact heap) we need to know the
   // first object from which we must compact and/or update references. This is
   // for both non-moving and moving space. Additionally, for the moving-space,
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc
index 5e64ae2..b569241 100644
--- a/runtime/gc/heap_test.cc
+++ b/runtime/gc/heap_test.cc
@@ -201,12 +201,8 @@
       EXPECT_FALSE(full_gc_tracing_throughput->IsNull());
       EXPECT_FALSE(full_gc_throughput_avg->IsNull());
       EXPECT_FALSE(full_gc_tracing_throughput_avg->IsNull());
-      if (fg_collector_type != kCollectorTypeCMC) {
-        // TODO(b/270957146): For some reason, these metrics are still null
-        // after running the Concurrent Mark-Compact collector; investigate why.
-        EXPECT_FALSE(full_gc_scanned_bytes->IsNull());
-        EXPECT_FALSE(full_gc_scanned_bytes_delta->IsNull());
-      }
+      EXPECT_FALSE(full_gc_scanned_bytes->IsNull());
+      EXPECT_FALSE(full_gc_scanned_bytes_delta->IsNull());
       EXPECT_FALSE(full_gc_freed_bytes->IsNull());
       EXPECT_FALSE(full_gc_freed_bytes_delta->IsNull());
       EXPECT_FALSE(full_gc_duration->IsNull());