void ConcurrentCopying::RunPhases() {
is_active_ = true;
Thread* self = Thread::Current();
thread_running_gc_ = self;
Locks::mutator_lock_->AssertNotHeld(self);
{
ReaderMutexLock mu(self, *Locks::mutator_lock_);
InitializePhase();
// In case of forced evacuation, all regions are evacuated and hence no
// need to compute live_bytes.
if (use_generational_cc_ && !young_gen_ && !force_evacuate_all_) {
MarkingPhase();
}
}
if (kUseBakerReadBarrier && kGrayDirtyImmuneObjects) {
// Switch to read barrier mark entrypoints before we gray the objects. This is required in case
// a mutator sees a gray bit and dispatches on the entrypoint. (b/37876887).
ActivateReadBarrierEntrypoints();
// Gray dirty immune objects concurrently to reduce GC pause times. We re-process gray cards in
// the pause.
ReaderMutexLock mu(self, *Locks::mutator_lock_);
GrayAllDirtyImmuneObjects();
}
FlipThreadRoots();
{
ReaderMutexLock mu(self, *Locks::mutator_lock_);
CopyingPhase();
}
{
ReaderMutexLock mu(self, *Locks::mutator_lock_);
ReclaimPhase();
}
FinishPhase();
is_active_ = false;
thread_running_gc_ = nullptr;
}
void ConcurrentCopying::BindBitmaps() {
Thread* self = Thread::Current();
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
// Mark all of the spaces we never collect as immune.
for (const auto& space : heap_->GetContinuousSpaces()) {
if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyNeverCollect ||
space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect) {
CHECK(space->IsZygoteSpace() || space->IsImageSpace());
immune_spaces_.AddSpace(space);
} else {
CHECK(space == region_space_ || space == heap_->non_moving_space_);
if (use_generational_cc_) {
if (space == region_space_) {
region_space_bitmap_ = region_space_->GetMarkBitmap();
} else if (young_gen_ && space->IsContinuousMemMapAllocSpace()) {
DCHECK_EQ(space->GetGcRetentionPolicy(), space::kGcRetentionPolicyAlwaysCollect);
space->AsContinuousMemMapAllocSpace()->BindLiveToMarkBitmap();
}
if (young_gen_) {
// Age all of the cards for the region space so that we know which evac regions to scan.
heap_->GetCardTable()->ModifyCardsAtomic(space->Begin(),
space->End(),
AgeCardVisitor(),
VoidFunctor());
} else {
// In a full-heap GC cycle, the card-table corresponding to region-space and
// non-moving space can be cleared, because this cycle only needs to
// capture writes during the marking phase of this cycle to catch
// objects that skipped marking due to heap mutation. Furthermore,
// if the next GC is a young-gen cycle, then it only needs writes to
// be captured after the thread-flip of this GC cycle, as that is when
// the young-gen for the next GC cycle starts getting populated.
heap_->GetCardTable()->ClearCardRange(space->Begin(), space->Limit());
}
} else {
if (space == region_space_) {
// It is OK to clear the bitmap with mutators running since the only place it is read is
// VisitObjects which has exclusion with CC.
region_space_bitmap_ = region_space_->GetMarkBitmap();
region_space_bitmap_->Clear();
}
}
}
}
if (use_generational_cc_ && young_gen_) {
for (const auto& space : GetHeap()->GetDiscontinuousSpaces()) {
CHECK(space->IsLargeObjectSpace());
space->AsLargeObjectSpace()->CopyLiveToMarked();
}
}
}