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_) {
diff --git a/runtime/monitor_pool.h b/runtime/monitor_pool.h
index de553fc..875b3fe 100644
--- a/runtime/monitor_pool.h
+++ b/runtime/monitor_pool.h
@@ -104,6 +104,12 @@
#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 @@
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_);