ART: add dump region info runtime option

Introduce two new runtime options, DumpRegionInfoBeforeGC and
DumpRegionInfoAfterGC, for printing the live bytes ratio for non-free
regions before and after each GC cycle.

Test: Run art with -XX:DumpRegionInfoBeforeGC and -XX:DumpRegionInfoAfterGC on some benchmarks.
Bug: 119486919
Change-Id: I0d6f210669b85d94034178815f6cae6fd19ca397
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 861f0d3..2c80f93 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -700,7 +700,7 @@
 // Switch threads that from from-space to to-space refs. Forward/mark the thread roots.
 void ConcurrentCopying::FlipThreadRoots() {
   TimingLogger::ScopedTiming split("FlipThreadRoots", GetTimings());
-  if (kVerboseMode) {
+  if (kVerboseMode || heap_->dump_region_info_before_gc_) {
     LOG(INFO) << "time=" << region_space_->Time();
     region_space_->DumpNonFreeRegions(LOG_STREAM(INFO));
   }
@@ -2566,6 +2566,11 @@
 
   CheckEmptyMarkStack();
 
+  if (heap_->dump_region_info_after_gc_) {
+    LOG(INFO) << "time=" << region_space_->Time();
+    region_space_->DumpNonFreeRegions(LOG_STREAM(INFO));
+  }
+
   if (kVerboseMode) {
     LOG(INFO) << "GC end of ReclaimPhase";
   }
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index d47aca9..d868aba 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -201,7 +201,9 @@
            bool gc_stress_mode,
            bool measure_gc_performance,
            bool use_homogeneous_space_compaction_for_oom,
-           uint64_t min_interval_homogeneous_space_compaction_by_oom)
+           uint64_t min_interval_homogeneous_space_compaction_by_oom,
+           bool dump_region_info_before_gc,
+           bool dump_region_info_after_gc)
     : non_moving_space_(nullptr),
       rosalloc_space_(nullptr),
       dlmalloc_space_(nullptr),
@@ -300,7 +302,9 @@
       backtrace_lock_(nullptr),
       seen_backtrace_count_(0u),
       unique_backtrace_count_(0u),
-      gc_disabled_for_shutdown_(false) {
+      gc_disabled_for_shutdown_(false),
+      dump_region_info_before_gc_(dump_region_info_before_gc),
+      dump_region_info_after_gc_(dump_region_info_after_gc) {
   if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
     LOG(INFO) << "Heap() entering";
   }
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index de65f02..aa09cbe 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -207,7 +207,9 @@
        bool gc_stress_mode,
        bool measure_gc_performance,
        bool use_homogeneous_space_compaction,
-       uint64_t min_interval_homogeneous_space_compaction_by_oom);
+       uint64_t min_interval_homogeneous_space_compaction_by_oom,
+       bool dump_region_info_before_gc,
+       bool dump_region_info_after_gc);
 
   ~Heap();
 
@@ -1506,6 +1508,11 @@
   // allocating.
   bool gc_disabled_for_shutdown_ GUARDED_BY(gc_complete_lock_);
 
+  // Turned on by -XX:DumpRegionInfoBeforeGC and -XX:DumpRegionInfoAfterGC to
+  // emit region info before and after each GC cycle.
+  bool dump_region_info_before_gc_;
+  bool dump_region_info_after_gc_;
+
   // Boot image spaces.
   std::vector<space::ImageSpace*> boot_image_spaces_;
 
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index 98b140e..07783ba 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -835,8 +835,14 @@
      << " type=" << type_
      << " objects_allocated=" << objects_allocated_
      << " alloc_time=" << alloc_time_
-     << " live_bytes=" << live_bytes_
-     << " is_newly_allocated=" << std::boolalpha << is_newly_allocated_ << std::noboolalpha
+     << " live_bytes=" << live_bytes_;
+
+  if (live_bytes_ != static_cast<size_t>(-1)) {
+    os << " ratio over allocated bytes="
+       << (static_cast<float>(live_bytes_) / RoundUp(BytesAllocated(), kRegionSize));
+  }
+
+  os << " is_newly_allocated=" << std::boolalpha << is_newly_allocated_ << std::noboolalpha
      << " is_a_tlab=" << std::boolalpha << is_a_tlab_ << std::noboolalpha
      << " thread=" << thread_ << '\n';
 }
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 17ff3a2..4a04259 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -151,6 +151,10 @@
           .IntoKey(M::LongGCLogThreshold)
       .Define("-XX:DumpGCPerformanceOnShutdown")
           .IntoKey(M::DumpGCPerformanceOnShutdown)
+      .Define("-XX:DumpRegionInfoBeforeGC")
+          .IntoKey(M::DumpRegionInfoBeforeGC)
+      .Define("-XX:DumpRegionInfoAfterGC")
+          .IntoKey(M::DumpRegionInfoAfterGC)
       .Define("-XX:DumpJITInfoOnShutdown")
           .IntoKey(M::DumpJITInfoOnShutdown)
       .Define("-XX:IgnoreMaxFootprint")
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 55bc2ec..7eac3d9 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1249,7 +1249,9 @@
                        xgc_option.gcstress_,
                        xgc_option.measure_,
                        runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM),
-                       runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs));
+                       runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs),
+                       runtime_options.Exists(Opt::DumpRegionInfoBeforeGC),
+                       runtime_options.Exists(Opt::DumpRegionInfoAfterGC));
 
   if (!heap_->HasBootImageSpace() && !allow_dex_file_fallback_) {
     LOG(ERROR) << "Dex file fallback disabled, cannot continue without image.";
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index 2b2919e..222c821 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -64,6 +64,8 @@
 RUNTIME_OPTIONS_KEY (MillisecondsToNanoseconds, \
                                           ThreadSuspendTimeout,           ThreadList::kDefaultThreadSuspendTimeout)
 RUNTIME_OPTIONS_KEY (Unit,                DumpGCPerformanceOnShutdown)
+RUNTIME_OPTIONS_KEY (Unit,                DumpRegionInfoBeforeGC)
+RUNTIME_OPTIONS_KEY (Unit,                DumpRegionInfoAfterGC)
 RUNTIME_OPTIONS_KEY (Unit,                DumpJITInfoOnShutdown)
 RUNTIME_OPTIONS_KEY (Unit,                IgnoreMaxFootprint)
 RUNTIME_OPTIONS_KEY (Unit,                LowMemoryMode)