ART: Fix string data leak in image writer

The string intern data is a large object, so it will be recognized
as leaking under valgrind.

Bug: 18628623
Change-Id: I9090db119a50eebd806a82369bd46527c4e7dbf0
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index a45c2d1..eb1b5db 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -548,6 +548,7 @@
   }
   // Create character array, copy characters and point the strings there.
   mirror::CharArray* array = mirror::CharArray::Alloc(self, num_chars);
+  string_data_array_ = array;
   uint16_t* array_data = array->GetData();
   size_t pos = 0u;
   prev_s = nullptr;
@@ -1234,4 +1235,13 @@
   return lockword_ & ~kBinMask;
 }
 
+void ImageWriter::FreeStringDataArray() {
+  if (string_data_array_ != nullptr) {
+    gc::space::LargeObjectSpace* los = Runtime::Current()->GetHeap()->GetLargeObjectsSpace();
+    if (los != nullptr) {
+      los->Free(Thread::Current(), reinterpret_cast<mirror::Object*>(string_data_array_));
+    }
+  }
+}
+
 }  // namespace art
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index 8c84b68..4418879 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -18,6 +18,7 @@
 #define ART_COMPILER_IMAGE_WRITER_H_
 
 #include <stdint.h>
+#include <valgrind.h>
 
 #include <cstddef>
 #include <memory>
@@ -56,7 +57,15 @@
     CHECK_NE(image_begin, 0U);
   }
 
-  ~ImageWriter() {}
+  ~ImageWriter() {
+    // For interned strings a large array is allocated to hold all the character data and avoid
+    // overhead. However, no GC is run anymore at this point. As the array is likely large, it
+    // will be allocated in the large object space, where valgrind can track every single
+    // allocation. Not explicitly freeing that array will be recognized as a leak.
+    if (RUNNING_ON_VALGRIND != 0) {
+      FreeStringDataArray();
+    }
+  }
 
   bool PrepareImageAddressSpace();
 
@@ -254,6 +263,9 @@
   // Calculate the sum total of the bin slot sizes in [0, up_to). Defaults to all bins.
   size_t GetBinSizeSum(Bin up_to = kBinSize) const;
 
+  // Release the string_data_array_.
+  void FreeStringDataArray();
+
   const CompilerDriver& compiler_driver_;
 
   // Beginning target image address for the output image.
@@ -306,6 +318,8 @@
   size_t bin_slot_sizes_[kBinSize];  // Number of bytes in a bin
   size_t bin_slot_count_[kBinSize];  // Number of objects in a bin
 
+  void* string_data_array_;  // The backing for the interned strings.
+
   friend class FixupVisitor;
   friend class FixupClassVisitor;
   DISALLOW_COPY_AND_ASSIGN(ImageWriter);