Trim reference tables when we trim the heap

Before:
System server:
 virtual                     shared   shared  private  private
  size      RSS      PSS    clean    dirty    clean    dirty    # object
2200      300      229        0       80        0      220   77 /dev/ashmem/dalvik-indirect ref table (deleted)
Location:
1896      128      102        0       28        0      100   39 /dev/ashmem/dalvik-indirect ref table (deleted)

After:
 virtual                     shared   shared  private  private
  size      RSS      PSS    clean    dirty    clean    dirty    # object
System server:
2216       64       64        0        0        0       64   79 /dev/ashmem/dalvik-indirect ref table (deleted)
Location:
2120       48       48        0        0        0       48   67 /dev/ashmem/dalvik-indirect ref table (deleted)

No pause time regression measured in memalloc test.

(cherry picked from commit 84dc99d2fa67e5dff018685661cb2bff62132989)

Change-Id: I80d9bd3b98e888fa8f77d03df69f8479ed209986
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 0cceaa4..7b679ea 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -977,6 +977,22 @@
   Trim();
 }
 
+class TrimIndirectReferenceTableClosure : public Closure {
+ public:
+  explicit TrimIndirectReferenceTableClosure(Barrier* barrier) : barrier_(barrier) {
+  }
+  virtual void Run(Thread* thread) OVERRIDE NO_THREAD_SAFETY_ANALYSIS {
+    ATRACE_BEGIN("Trimming reference table");
+    thread->GetJniEnv()->locals.Trim();
+    ATRACE_END();
+    barrier_->Pass(Thread::Current());
+  }
+
+ private:
+  Barrier* const barrier_;
+};
+
+
 void Heap::Trim() {
   Thread* self = Thread::Current();
   {
@@ -998,6 +1014,19 @@
     WaitForGcToCompleteLocked(kGcCauseTrim, self);
     collector_type_running_ = kCollectorTypeHeapTrim;
   }
+  // Trim reference tables.
+  {
+    ScopedObjectAccess soa(self);
+    JavaVMExt* vm = soa.Vm();
+    // Trim globals indirect reference table.
+    vm->TrimGlobals();
+    // Trim locals indirect reference tables.
+    Barrier barrier(0);
+    TrimIndirectReferenceTableClosure closure(&barrier);
+    ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);
+    size_t barrier_count = Runtime::Current()->GetThreadList()->RunCheckpoint(&closure);
+    barrier.Increment(self, barrier_count);
+  }
   uint64_t start_ns = NanoTime();
   // Trim the managed spaces.
   uint64_t total_alloc_space_allocated = 0;