Fix a crash with -XX:DumpGCPerformanceOnShutdown.

DumpGcPerformanceInfo() could call RosAllocSpace::InspectAllRosAlloc()
which needs the thread list to be still alive. Fix by moving the
DumpGcPerformanceInfo() call from the Heap destructor up to the
beginning of the Runtime destructor so that the thread list is still
alive when it's called.

Bug: 11830901
Change-Id: Ib094d60916943c8cb1d4b769d805b4ca03269f90
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 24ee31c..d1784fa 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -78,7 +78,7 @@
            double target_utilization, size_t capacity, const std::string& image_file_name,
            bool concurrent_gc, size_t parallel_gc_threads, size_t conc_gc_threads,
            bool low_memory_mode, size_t long_pause_log_threshold, size_t long_gc_log_threshold,
-           bool dump_gc_performance_on_shutdown, bool ignore_max_footprint)
+           bool ignore_max_footprint)
     : non_moving_space_(nullptr),
       concurrent_gc_(concurrent_gc),
       parallel_gc_threads_(parallel_gc_threads),
@@ -86,7 +86,6 @@
       low_memory_mode_(low_memory_mode),
       long_pause_log_threshold_(long_pause_log_threshold),
       long_gc_log_threshold_(long_gc_log_threshold),
-      dump_gc_performance_on_shutdown_(dump_gc_performance_on_shutdown),
       ignore_max_footprint_(ignore_max_footprint),
       have_zygote_space_(false),
       soft_reference_queue_(this),
@@ -610,9 +609,6 @@
 
 Heap::~Heap() {
   VLOG(heap) << "Starting ~Heap()";
-  if (dump_gc_performance_on_shutdown_) {
-    DumpGcPerformanceInfo(LOG(INFO));
-  }
   STLDeleteElements(&garbage_collectors_);
   // If we don't reset then the mark stack complains in its destructor.
   allocation_stack_->Reset();
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 30b7eb1..877df48 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -146,7 +146,7 @@
                 const std::string& original_image_file_name, bool concurrent_gc,
                 size_t parallel_gc_threads, size_t conc_gc_threads, bool low_memory_mode,
                 size_t long_pause_threshold, size_t long_gc_threshold,
-                bool dump_gc_performance_on_shutdown, bool ignore_max_footprint);
+                bool ignore_max_footprint);
 
   ~Heap();
 
@@ -648,9 +648,6 @@
   // If we get a GC longer than long GC log threshold, then we print out the GC after it finishes.
   const size_t long_gc_log_threshold_;
 
-  // If true, then we dump the GC cumulative timings on shutdown.
-  const bool dump_gc_performance_on_shutdown_;
-
   // If we ignore the max footprint it lets the heap grow until it hits the heap capacity, this is
   // useful for benchmarking since it reduces time spent in GC to a low %.
   const bool ignore_max_footprint_;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 71ad252..896f7ff 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -109,6 +109,13 @@
 }
 
 Runtime::~Runtime() {
+  if (dump_gc_performance_on_shutdown_) {
+    // This can't be called from the Heap destructor below because it
+    // could call RosAlloc::InspectAll() which needs the thread_list
+    // to be still alive.
+    heap_->DumpGcPerformanceInfo(LOG(INFO));
+  }
+
   Thread* self = Thread::Current();
   {
     MutexLock mu(self, *Locks::runtime_shutdown_lock_);
@@ -915,9 +922,10 @@
                        options->low_memory_mode_,
                        options->long_pause_log_threshold_,
                        options->long_gc_log_threshold_,
-                       options->dump_gc_performance_on_shutdown_,
                        options->ignore_max_footprint_);
 
+  dump_gc_performance_on_shutdown_ = options->dump_gc_performance_on_shutdown_;
+
   BlockSignals();
   InitPlatformSignalHandlers();
 
diff --git a/runtime/runtime.h b/runtime/runtime.h
index d5ad299..0140ddb 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -562,6 +562,9 @@
   // As returned by ClassLoader.getSystemClassLoader().
   jobject system_class_loader_;
 
+  // If true, then we dump the GC cumulative timings on shutdown.
+  bool dump_gc_performance_on_shutdown_;
+
   DISALLOW_COPY_AND_ASSIGN(Runtime);
 };