summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/gc/collector/concurrent_copying.cc88
-rw-r--r--runtime/gc/collector/concurrent_copying.h6
-rw-r--r--runtime/gc/heap.cc5
3 files changed, 67 insertions, 32 deletions
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index f7f3a8d628..e95b135565 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -95,7 +95,8 @@ ConcurrentCopying::ConcurrentCopying(Heap* heap,
weak_ref_access_enabled_(true),
copied_live_bytes_ratio_sum_(0.f),
gc_count_(0),
- inter_region_bitmap_(nullptr),
+ region_space_inter_region_bitmap_(nullptr),
+ non_moving_space_inter_region_bitmap_(nullptr),
reclaimed_bytes_ratio_sum_(0.f),
young_gen_(young_gen),
skipped_blocks_lock_("concurrent copying bytes blocks lock", kMarkSweepMarkStackLock),
@@ -286,12 +287,32 @@ void ConcurrentCopying::ActivateReadBarrierEntrypoints() {
gc_barrier_->Increment(self, barrier_count);
}
+void ConcurrentCopying::CreateInterRegionRefBitmaps() {
+ DCHECK(kEnableGenerationalConcurrentCopyingCollection);
+ DCHECK(region_space_inter_region_bitmap_ == nullptr);
+ DCHECK(non_moving_space_inter_region_bitmap_ == nullptr);
+ DCHECK(region_space_ != nullptr);
+ DCHECK(heap_->non_moving_space_ != nullptr);
+ // Region-space
+ region_space_inter_region_bitmap_ = accounting::ContinuousSpaceBitmap::Create(
+ "region-space inter region ref bitmap",
+ reinterpret_cast<uint8_t*>(region_space_->Begin()),
+ region_space_->Limit() - region_space_->Begin());
+ CHECK(region_space_inter_region_bitmap_ != nullptr)
+ << "Couldn't allocate region-space inter region ref bitmap";
+
+ // non-moving-space
+ non_moving_space_inter_region_bitmap_ = accounting::ContinuousSpaceBitmap::Create(
+ "non-moving-space inter region ref bitmap",
+ reinterpret_cast<uint8_t*>(heap_->non_moving_space_->Begin()),
+ heap_->non_moving_space_->Limit() - heap_->non_moving_space_->Begin());
+ CHECK(non_moving_space_inter_region_bitmap_ != nullptr)
+ << "Couldn't allocate non-moving-space inter region ref bitmap";
+}
+
void ConcurrentCopying::BindBitmaps() {
Thread* self = Thread::Current();
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
- uintptr_t continuous_spaces_begin = UINTPTR_MAX;
- uintptr_t continuous_spaces_limit = 0;
- DCHECK(inter_region_bitmap_ == nullptr);
// Mark all of the spaces we never collect as immune.
for (const auto& space : heap_->GetContinuousSpaces()) {
if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyNeverCollect ||
@@ -301,6 +322,7 @@ void ConcurrentCopying::BindBitmaps() {
} else {
CHECK(!space->IsZygoteSpace());
CHECK(!space->IsImageSpace());
+ CHECK(space == region_space_ || space == heap_->non_moving_space_);
if (kEnableGenerationalConcurrentCopyingCollection) {
if (space == region_space_) {
region_space_bitmap_ = region_space_->GetMarkBitmap();
@@ -323,11 +345,6 @@ void ConcurrentCopying::BindBitmaps() {
// 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());
-
- continuous_spaces_begin =
- std::min(continuous_spaces_begin, reinterpret_cast<uintptr_t>(space->Begin()));
- continuous_spaces_limit =
- std::max(continuous_spaces_limit, reinterpret_cast<uintptr_t>(space->Limit()));
}
} else {
if (space == region_space_) {
@@ -339,18 +356,10 @@ void ConcurrentCopying::BindBitmaps() {
}
}
}
- if (kEnableGenerationalConcurrentCopyingCollection) {
- if (young_gen_) {
- for (const auto& space : GetHeap()->GetDiscontinuousSpaces()) {
- CHECK(space->IsLargeObjectSpace());
- space->AsLargeObjectSpace()->CopyLiveToMarked();
- }
- } else {
- inter_region_bitmap_.reset(accounting::ContinuousSpaceBitmap::Create(
- "inter region ref bitmap",
- reinterpret_cast<uint8_t*>(continuous_spaces_begin),
- continuous_spaces_limit - continuous_spaces_begin));
- CHECK(inter_region_bitmap_ != nullptr) << "Couldn't allocate inter region ref bitmap";
+ if (kEnableGenerationalConcurrentCopyingCollection && young_gen_) {
+ for (const auto& space : GetHeap()->GetDiscontinuousSpaces()) {
+ CHECK(space->IsLargeObjectSpace());
+ space->AsLargeObjectSpace()->CopyLiveToMarked();
}
}
}
@@ -1112,12 +1121,22 @@ void ConcurrentCopying::AddLiveBytesAndScanRef(mirror::Object* ref) {
}
ComputeLiveBytesAndMarkRefFieldsVisitor</*kHandleInterRegionRefs*/ true>
visitor(this, obj_region_idx);
- ref->VisitReferences</*kVisitNativeRoots=*/true, kDefaultVerifyFlags, kWithoutReadBarrier>(
+ ref->VisitReferences</*kVisitNativeRoots=*/ true, kDefaultVerifyFlags, kWithoutReadBarrier>(
visitor, visitor);
// Mark the corresponding card dirty if the object contains any
// inter-region reference.
if (visitor.ContainsInterRegionRefs()) {
- inter_region_bitmap_->Set(ref);
+ if (obj_region_idx == static_cast<size_t>(-1)) {
+ // If an inter-region ref has been found in a non-region-space, then it
+ // must be non-moving-space. This is because this function cannot be
+ // called on a immune-space object, and a large-object-space object has
+ // only class object reference, which is either in some immune-space, or
+ // in non-moving-space.
+ DCHECK(heap_->non_moving_space_->HasAddress(ref));
+ non_moving_space_inter_region_bitmap_->Set(ref);
+ } else {
+ region_space_inter_region_bitmap_->Set(ref);
+ }
}
}
@@ -1427,11 +1446,15 @@ void ConcurrentCopying::CopyingPhase() {
}
}
ScanDirtyObject</*kNoUnEvac*/ true>(obj);
- } else if (space != region_space_ || region_space_->IsInUnevacFromSpace(obj)) {
+ } else if (space != region_space_) {
+ DCHECK(space == heap_->non_moving_space_);
// We need to process un-evac references as they may be unprocessed,
// if they skipped the marking phase due to heap mutation.
ScanDirtyObject</*kNoUnEvac*/ false>(obj);
- inter_region_bitmap_->Clear(obj);
+ non_moving_space_inter_region_bitmap_->Clear(obj);
+ } else if (region_space_->IsInUnevacFromSpace(obj)) {
+ ScanDirtyObject</*kNoUnEvac*/ false>(obj);
+ region_space_inter_region_bitmap_->Clear(obj);
}
},
accounting::CardTable::kCardAged);
@@ -1443,16 +1466,20 @@ void ConcurrentCopying::CopyingPhase() {
ScanDirtyObject</*kNoUnEvac*/ true>(obj);
};
if (space == region_space_) {
- region_space_->ScanUnevacFromSpace(inter_region_bitmap_.get(), visitor);
+ region_space_->ScanUnevacFromSpace(region_space_inter_region_bitmap_, visitor);
} else {
- inter_region_bitmap_->VisitMarkedRange(reinterpret_cast<uintptr_t>(space->Begin()),
- reinterpret_cast<uintptr_t>(space->End()),
- visitor);
+ DCHECK(space == heap_->non_moving_space_);
+ non_moving_space_inter_region_bitmap_->VisitMarkedRange(
+ reinterpret_cast<uintptr_t>(space->Begin()),
+ reinterpret_cast<uintptr_t>(space->End()),
+ visitor);
}
}
}
// Done scanning unevac space.
done_scanning_.store(true, std::memory_order_release);
+ // NOTE: inter-region-ref bitmaps can be cleared here to release memory, if needed.
+ // Currently we do it in ReclaimPhase().
if (kVerboseMode) {
LOG(INFO) << "GC end of ScanCardsForSpace";
}
@@ -3527,7 +3554,8 @@ void ConcurrentCopying::FinishPhase() {
// We do not currently use the region space cards at all, madvise them away to save ram.
heap_->GetCardTable()->ClearCardRange(region_space_->Begin(), region_space_->Limit());
} else if (kEnableGenerationalConcurrentCopyingCollection && !young_gen_) {
- inter_region_bitmap_.reset();
+ region_space_inter_region_bitmap_->Clear();
+ non_moving_space_inter_region_bitmap_->Clear();
}
{
MutexLock mu(self, skipped_blocks_lock_);
diff --git a/runtime/gc/collector/concurrent_copying.h b/runtime/gc/collector/concurrent_copying.h
index aabfc8e154..70d2624a4f 100644
--- a/runtime/gc/collector/concurrent_copying.h
+++ b/runtime/gc/collector/concurrent_copying.h
@@ -98,6 +98,9 @@ class ConcurrentCopying : public GarbageCollector {
return kCollectorTypeCC;
}
void RevokeAllThreadLocalBuffers() override;
+ // Creates inter-region ref bitmaps for region-space and non-moving-space.
+ // Gets called in Heap construction after the two spaces are created.
+ void CreateInterRegionRefBitmaps();
void SetRegionSpace(space::RegionSpace* region_space) {
DCHECK(region_space != nullptr);
region_space_ = region_space;
@@ -391,7 +394,8 @@ class ConcurrentCopying : public GarbageCollector {
size_t gc_count_;
// Bit is set if the corresponding object has inter-region references that
// were found during the marking phase of two-phase full-heap GC cycle.
- std::unique_ptr<accounting::ContinuousSpaceBitmap> inter_region_bitmap_;
+ accounting::ContinuousSpaceBitmap* region_space_inter_region_bitmap_;
+ accounting::ContinuousSpaceBitmap* non_moving_space_inter_region_bitmap_;
// reclaimed_bytes_ratio = reclaimed_bytes/num_allocated_bytes per GC cycle
float reclaimed_bytes_ratio_sum_;
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index d868aba767..bf8aaaeba7 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -666,6 +666,9 @@ Heap::Heap(size_t initial_size,
concurrent_copying_collector_->SetRegionSpace(region_space_);
if (kEnableGenerationalConcurrentCopyingCollection) {
young_concurrent_copying_collector_->SetRegionSpace(region_space_);
+ // At this point, non-moving space should be created.
+ DCHECK(non_moving_space_ != nullptr);
+ concurrent_copying_collector_->CreateInterRegionRefBitmaps();
}
garbage_collectors_.push_back(concurrent_copying_collector_);
if (kEnableGenerationalConcurrentCopyingCollection) {
@@ -2736,7 +2739,7 @@ collector::GcType Heap::CollectGarbageInternal(collector::GcType gc_type,
// active_concurrent_copying_collector_. So we should not concurrency here.
active_concurrent_copying_collector_ = (gc_type == collector::kGcTypeSticky) ?
young_concurrent_copying_collector_ : concurrent_copying_collector_;
- active_concurrent_copying_collector_->SetRegionSpace(region_space_);
+ DCHECK(active_concurrent_copying_collector_->RegionSpace() == region_space_);
}
collector = active_concurrent_copying_collector_;
break;