ART: Release all resource on MonitorPool destruction

To be valgrind-clean, we need to release the current metadata and
all chunks on destruction.

Bug: 27156726
Change-Id: Ia51cea139a6e9669975b6ac045f5223cd68f1f6a
diff --git a/runtime/monitor_pool.cc b/runtime/monitor_pool.cc
index 9e78cda..ce38e4f 100644
--- a/runtime/monitor_pool.cc
+++ b/runtime/monitor_pool.cc
@@ -42,11 +42,12 @@
     if (capacity_ == 0U) {
       // Initialization.
       capacity_ = kInitialChunkStorage;
-      uintptr_t* new_backing = new uintptr_t[capacity_];
+      uintptr_t* new_backing = new uintptr_t[capacity_]();
+      DCHECK(monitor_chunks_.LoadRelaxed() == nullptr);
       monitor_chunks_.StoreRelaxed(new_backing);
     } else {
       size_t new_capacity = 2 * capacity_;
-      uintptr_t* new_backing = new uintptr_t[new_capacity];
+      uintptr_t* new_backing = new uintptr_t[new_capacity]();
       uintptr_t* old_backing = monitor_chunks_.LoadRelaxed();
       memcpy(new_backing, old_backing, sizeof(uintptr_t) * capacity_);
       monitor_chunks_.StoreRelaxed(new_backing);
@@ -88,6 +89,25 @@
   first_free_ = last;
 }
 
+void MonitorPool::FreeInternal() {
+  // This is on shutdown with NO_THREAD_SAFETY_ANALYSIS, can't/don't need to lock.
+  uintptr_t* backing = monitor_chunks_.LoadRelaxed();
+  DCHECK(backing != nullptr);
+  DCHECK_GT(capacity_, 0U);
+  DCHECK_GT(num_chunks_, 0U);
+
+  for (size_t i = 0; i < capacity_; ++i) {
+    if (i < num_chunks_) {
+      DCHECK_NE(backing[i], 0U);
+      allocator_.deallocate(reinterpret_cast<uint8_t*>(backing[i]), kChunkSize);
+    } else {
+      DCHECK_EQ(backing[i], 0U);
+    }
+  }
+
+  delete[] backing;
+}
+
 Monitor* MonitorPool::CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj,
                                           int32_t hash_code)
     SHARED_REQUIRES(Locks::mutator_lock_) {