diff options
author | Mathieu Chartier <mathieuc@google.com> | 2015-01-23 03:51:17 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-01-23 03:51:18 +0000 |
commit | 4dfe58d8f2d398963f31831a57fbd12e282e1196 (patch) | |
tree | 2cb59da016a53da400c31743a4513cf8e7d7d34f | |
parent | ce841e0930f19abe5a37bb7f39a30a2179152ade (diff) | |
parent | 727b294b4091cf3cc2f8137cd654552f477fe46a (diff) | |
download | art-4dfe58d8f2d398963f31831a57fbd12e282e1196.zip art-4dfe58d8f2d398963f31831a57fbd12e282e1196.tar.gz art-4dfe58d8f2d398963f31831a57fbd12e282e1196.tar.bz2 |
Merge "ART: clear dirty cards of alloc space in pause phase"
-rw-r--r-- | runtime/gc/accounting/card_table-inl.h | 11 | ||||
-rw-r--r-- | runtime/gc/accounting/card_table.h | 2 | ||||
-rw-r--r-- | runtime/gc/collector/mark_sweep.cc | 26 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 4 |
4 files changed, 33 insertions, 10 deletions
diff --git a/runtime/gc/accounting/card_table-inl.h b/runtime/gc/accounting/card_table-inl.h index 15562e5..83ad33e 100644 --- a/runtime/gc/accounting/card_table-inl.h +++ b/runtime/gc/accounting/card_table-inl.h @@ -48,7 +48,7 @@ static inline bool byte_cas(uint8_t old_value, uint8_t new_value, uint8_t* addre #endif } -template <typename Visitor> +template <bool kClearCard, typename Visitor> inline size_t CardTable::Scan(ContinuousSpaceBitmap* bitmap, uint8_t* scan_begin, uint8_t* scan_end, const Visitor& visitor, const uint8_t minimum_age) const { DCHECK_GE(scan_begin, reinterpret_cast<uint8_t*>(bitmap->HeapBegin())); @@ -66,6 +66,9 @@ inline size_t CardTable::Scan(ContinuousSpaceBitmap* bitmap, uint8_t* scan_begin uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card_cur)); bitmap->VisitMarkedRange(start, start + kCardSize, visitor); ++cards_scanned; + if (kClearCard) { + *card_cur = 0; + } } ++card_cur; } @@ -95,6 +98,9 @@ inline size_t CardTable::Scan(ContinuousSpaceBitmap* bitmap, uint8_t* scan_begin << "card " << static_cast<size_t>(*card) << " intptr_t " << (start_word & 0xFF); bitmap->VisitMarkedRange(start, start + kCardSize, visitor); ++cards_scanned; + if (kClearCard) { + *card = 0; + } } start_word >>= 8; start += kCardSize; @@ -109,6 +115,9 @@ inline size_t CardTable::Scan(ContinuousSpaceBitmap* bitmap, uint8_t* scan_begin uintptr_t start = reinterpret_cast<uintptr_t>(AddrFromCard(card_cur)); bitmap->VisitMarkedRange(start, start + kCardSize, visitor); ++cards_scanned; + if (kClearCard) { + *card_cur = 0; + } } ++card_cur; } diff --git a/runtime/gc/accounting/card_table.h b/runtime/gc/accounting/card_table.h index 9bd3fba..a84cf34 100644 --- a/runtime/gc/accounting/card_table.h +++ b/runtime/gc/accounting/card_table.h @@ -101,7 +101,7 @@ class CardTable { // For every dirty at least minumum age between begin and end invoke the visitor with the // specified argument. Returns how many cards the visitor was run on. - template <typename Visitor> + template <bool kClearCard, typename Visitor> size_t Scan(SpaceBitmap<kObjectAlignment>* bitmap, uint8_t* scan_begin, uint8_t* scan_end, const Visitor& visitor, const uint8_t minimum_age = kCardDirty) const 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 @@ class CardScanTask : public MarkStackTask<false> { 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 @@ class CardScanTask : public MarkStackTask<false> { 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 @@ class CardScanTask : public MarkStackTask<false> { 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 @@ void MarkSweep::ScanGrayObjects(bool paused, uint8_t minimum_age) { // 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 @@ void MarkSweep::ScanGrayObjects(bool paused, uint8_t minimum_age) { // 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 @@ void MarkSweep::ScanGrayObjects(bool paused, uint8_t minimum_age) { } 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); + } } } } diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index eed9352..6ba30c6 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -2385,8 +2385,8 @@ class VerifyReferenceVisitor { // Attempt to see if the card table missed the reference. ScanVisitor scan_visitor; uint8_t* byte_cover_begin = reinterpret_cast<uint8_t*>(card_table->AddrFromCard(card_addr)); - card_table->Scan(bitmap, byte_cover_begin, - byte_cover_begin + accounting::CardTable::kCardSize, scan_visitor); + card_table->Scan<false>(bitmap, byte_cover_begin, + byte_cover_begin + accounting::CardTable::kCardSize, scan_visitor); } // Search to see if any of the roots reference our object. |