OSDN Git Service

ART: Release all resource on MonitorPool destruction
authorAndreas Gampe <agampe@google.com>
Thu, 10 Mar 2016 16:33:45 +0000 (08:33 -0800)
committerAndreas Gampe <agampe@google.com>
Thu, 10 Mar 2016 20:03:55 +0000 (12:03 -0800)
To be valgrind-clean, we need to release the current metadata and
all chunks on destruction.

Bug: 27156726
Change-Id: Ia51cea139a6e9669975b6ac045f5223cd68f1f6a

runtime/monitor_pool.cc
runtime/monitor_pool.h

index 9e78cda..ce38e4f 100644 (file)
@@ -42,11 +42,12 @@ void MonitorPool::AllocateChunk() {
     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 @@ void MonitorPool::AllocateChunk() {
   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_) {
index de553fc..875b3fe 100644 (file)
@@ -104,6 +104,12 @@ class MonitorPool {
 #endif
   }
 
+  ~MonitorPool() {
+#ifdef __LP64__
+    FreeInternal();
+#endif
+  }
+
  private:
 #ifdef __LP64__
   // When we create a monitor pool, threads have not been initialized, yet, so ignore thread-safety
@@ -112,6 +118,10 @@ class MonitorPool {
 
   void AllocateChunk() REQUIRES(Locks::allocated_monitor_ids_lock_);
 
+  // Release all chunks and metadata. This is done on shutdown, where threads have been destroyed,
+  // so ignore thead-safety analysis.
+  void FreeInternal() NO_THREAD_SAFETY_ANALYSIS;
+
   Monitor* CreateMonitorInPool(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code)
       SHARED_REQUIRES(Locks::mutator_lock_);