summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2015-01-23 03:51:17 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-01-23 03:51:18 +0000
commit4dfe58d8f2d398963f31831a57fbd12e282e1196 (patch)
tree2cb59da016a53da400c31743a4513cf8e7d7d34f
parentce841e0930f19abe5a37bb7f39a30a2179152ade (diff)
parent727b294b4091cf3cc2f8137cd654552f477fe46a (diff)
downloadart-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.h11
-rw-r--r--runtime/gc/accounting/card_table.h2
-rw-r--r--runtime/gc/collector/mark_sweep.cc26
-rw-r--r--runtime/gc/heap.cc4
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.