Merge "Avoid a long alloc space lock contention during sticky GC sweep." into dalvik-dev
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 374d3f4..7b78720 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -63,6 +63,7 @@
 static const bool kParallelMarkStack = true;
 static const bool kDisableFinger = true;  // TODO: Fix, bit rotten.
 static const bool kUseMarkStackPrefetch = true;
+static const size_t kSweepArrayChunkFreeSize = 1024;
 
 // Profiling and information flags.
 static const bool kCountClassesMarked = false;
@@ -916,10 +917,12 @@
     std::swap(large_live_objects, large_mark_objects);
   }
 
+  size_t freed_objects = 0;
   size_t freed_large_objects = 0;
   size_t count = allocations->Size();
   Object** objects = const_cast<Object**>(allocations->Begin());
   Object** out = objects;
+  Object** objects_to_chunk_free = out;
 
   // Empty the allocation stack.
   Thread* self = Thread::Current();
@@ -930,18 +933,37 @@
       if (!mark_bitmap->Test(obj)) {
         // Don't bother un-marking since we clear the mark bitmap anyways.
         *(out++) = obj;
+        // Free objects in chunks.
+        DCHECK_GE(out, objects_to_chunk_free);
+        DCHECK_LE(static_cast<size_t>(out - objects_to_chunk_free), kSweepArrayChunkFreeSize);
+        if (static_cast<size_t>(out - objects_to_chunk_free) == kSweepArrayChunkFreeSize) {
+          timings_.StartSplit("FreeList");
+          size_t chunk_freed_objects = out - objects_to_chunk_free;
+          freed_objects += chunk_freed_objects;
+          freed_bytes += space->FreeList(self, chunk_freed_objects, objects_to_chunk_free);
+          objects_to_chunk_free = out;
+          timings_.EndSplit();
+        }
       }
     } else if (!large_mark_objects->Test(obj)) {
       ++freed_large_objects;
       freed_bytes += large_object_space->Free(self, obj);
     }
   }
+  // Free the remaining objects in chunks.
+  DCHECK_GE(out, objects_to_chunk_free);
+  DCHECK_LE(static_cast<size_t>(out - objects_to_chunk_free), kSweepArrayChunkFreeSize);
+  if (out - objects_to_chunk_free > 0) {
+    timings_.StartSplit("FreeList");
+    size_t chunk_freed_objects = out - objects_to_chunk_free;
+    freed_objects += chunk_freed_objects;
+    freed_bytes += space->FreeList(self, chunk_freed_objects, objects_to_chunk_free);
+    timings_.EndSplit();
+  }
   CHECK_EQ(count, allocations->Size());
   timings_.EndSplit();
 
-  timings_.StartSplit("FreeList");
-  size_t freed_objects = out - objects;
-  freed_bytes += space->FreeList(self, freed_objects, objects);
+  timings_.StartSplit("RecordFree");
   VLOG(heap) << "Freed " << freed_objects << "/" << count
              << " objects with size " << PrettySize(freed_bytes);
   heap_->RecordFree(freed_objects + freed_large_objects, freed_bytes);