ART: clear dirty cards of alloc space in pause phase

Clear the dirty cards of alloc spaces when scanning them in pause phase,
the dirty cards of image or zygote space will not be cleared in order to
track the references to the other spaces.

Change-Id: I519f071d954a589aa33dbce0cdba405f2d2cef71
Signed-off-by: Lei Li <lei.l.li@intel.com>
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 80f7968..04fb694 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -687,12 +687,12 @@
   CardScanTask(ThreadPool* thread_pool, MarkSweep* mark_sweep,
                accounting::ContinuousSpaceBitmap* bitmap,
                uint8_t* begin, uint8_t* end, uint8_t minimum_age, size_t mark_stack_size,
-               Object** mark_stack_obj)
+               Object** mark_stack_obj, bool clear_card)
       : MarkStackTask<false>(thread_pool, mark_sweep, mark_stack_size, mark_stack_obj),
         bitmap_(bitmap),
         begin_(begin),
         end_(end),
-        minimum_age_(minimum_age) {
+        minimum_age_(minimum_age), clear_card_(clear_card) {
   }
 
  protected:
@@ -700,6 +700,7 @@
   uint8_t* const begin_;
   uint8_t* const end_;
   const uint8_t minimum_age_;
+  const bool clear_card_;
 
   virtual void Finalize() {
     delete this;
@@ -708,7 +709,9 @@
   virtual void Run(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
     ScanObjectParallelVisitor visitor(this);
     accounting::CardTable* card_table = mark_sweep_->GetHeap()->GetCardTable();
-    size_t cards_scanned = card_table->Scan(bitmap_, begin_, end_, visitor, minimum_age_);
+    size_t cards_scanned = clear_card_ ?
+                           card_table->Scan<true>(bitmap_, begin_, end_, visitor, minimum_age_) :
+                           card_table->Scan<false>(bitmap_, begin_, end_, visitor, minimum_age_);
     VLOG(heap) << "Parallel scanning cards " << reinterpret_cast<void*>(begin_) << " - "
         << reinterpret_cast<void*>(end_) << " = " << cards_scanned;
     // Finish by emptying our local mark stack.
@@ -763,6 +766,11 @@
       // Calculate how much address range each task gets.
       const size_t card_delta = RoundUp(address_range / thread_count + 1,
                                         accounting::CardTable::kCardSize);
+      // If paused and the space is neither zygote nor image space, we could clear the dirty
+      // cards to avoid accumulating them to increase card scanning load in the following GC
+      // cycles. We need to keep dirty cards of image space and zygote space in order to track
+      // references to the other spaces.
+      bool clear_card = paused && !space->IsZygoteSpace() && !space->IsImageSpace();
       // Create the worker tasks for this space.
       while (card_begin != card_end) {
         // Add a range of cards.
@@ -777,7 +785,7 @@
         // Add the new task to the thread pool.
         auto* task = new CardScanTask(thread_pool, this, space->GetMarkBitmap(), card_begin,
                                       card_begin + card_increment, minimum_age,
-                                      mark_stack_increment, mark_stack_end);
+                                      mark_stack_increment, mark_stack_end, clear_card);
         thread_pool->AddTask(self, task);
         card_begin += card_increment;
       }
@@ -811,8 +819,14 @@
         }
         TimingLogger::ScopedTiming t(name, GetTimings());
         ScanObjectVisitor visitor(this);
-        card_table->Scan(space->GetMarkBitmap(), space->Begin(), space->End(), visitor,
-                         minimum_age);
+        bool clear_card = paused && !space->IsZygoteSpace() && !space->IsImageSpace();
+        if (clear_card) {
+          card_table->Scan<true>(space->GetMarkBitmap(), space->Begin(), space->End(), visitor,
+                                 minimum_age);
+        } else {
+          card_table->Scan<false>(space->GetMarkBitmap(), space->Begin(), space->End(), visitor,
+                                  minimum_age);
+        }
       }
     }
   }