diff options
| -rw-r--r-- | runtime/gc/collector/semi_space.cc | 62 | ||||
| -rw-r--r-- | runtime/gc/collector/semi_space.h | 9 |
2 files changed, 67 insertions, 4 deletions
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc index 393935474a..31a3f35dcb 100644 --- a/runtime/gc/collector/semi_space.cc +++ b/runtime/gc/collector/semi_space.cc @@ -78,6 +78,8 @@ namespace collector { static constexpr bool kProtectFromSpace = true; static constexpr bool kResetFromSpace = true; +// TODO: move this to a new file as a new garbage collector? +static constexpr bool kEnableSimplePromo = false; // TODO: Unduplicate logic. void SemiSpace::ImmuneSpace(space::ContinuousSpace* space) { @@ -134,7 +136,9 @@ SemiSpace::SemiSpace(Heap* heap, const std::string& name_prefix) finalizer_reference_list_(nullptr), phantom_reference_list_(nullptr), cleared_reference_list_(nullptr), - self_(nullptr) { + self_(nullptr), + last_gc_to_space_end_(nullptr), + bytes_promoted_(0) { } void SemiSpace::InitializePhase() { @@ -169,6 +173,17 @@ void SemiSpace::MarkingPhase() { // Need to do this with mutators paused so that somebody doesn't accidentally allocate into the // wrong space. heap_->SwapSemiSpaces(); + if (kEnableSimplePromo) { + // If last_gc_to_space_end_ is out of the bounds of the from-space + // (the to-space from last GC), then point it to the beginning of + // the from-space. For example, the very first GC or the + // pre-zygote compaction. + if (!from_space_->HasAddress(reinterpret_cast<mirror::Object*>(last_gc_to_space_end_))) { + last_gc_to_space_end_ = from_space_->Begin(); + } + // Reset this before the marking starts below. + bytes_promoted_ = 0; + } // Assume the cleared space is already empty. BindBitmaps(); // Process dirty cards and add dirty cards to mod-union tables. @@ -268,6 +283,13 @@ void SemiSpace::ReclaimPhase() { } else { mprotect(from_space_->Begin(), from_space_->Capacity(), PROT_READ); } + + if (kEnableSimplePromo) { + // Record the end (top) of the to space so we can distinguish + // between objects that were allocated since the last GC and the + // older objects. + last_gc_to_space_end_ = to_space_->End(); + } } void SemiSpace::ResizeMarkStack(size_t new_size) { @@ -308,11 +330,38 @@ Object* SemiSpace::MarkObject(Object* obj) { if (from_space_->HasAddress(obj)) { mirror::Object* forward_address = GetForwardingAddressInFromSpace(obj); // If the object has already been moved, return the new forward address. - if (!to_space_->HasAddress(forward_address)) { + if (forward_address == nullptr) { // Otherwise, we need to move the object and add it to the markstack for processing. size_t object_size = obj->SizeOf(); size_t dummy = 0; - forward_address = to_space_->Alloc(self_, object_size, &dummy); + if (kEnableSimplePromo && reinterpret_cast<byte*>(obj) < last_gc_to_space_end_) { + // If it's allocated before the last GC (older), move (pseudo-promote) it to + // the non-moving space (as sort of an old generation.) + size_t bytes_promoted; + space::MallocSpace* non_moving_space = GetHeap()->GetNonMovingSpace(); + forward_address = non_moving_space->Alloc(self_, object_size, &bytes_promoted); + if (forward_address == nullptr) { + // If out of space, fall back to the to-space. + forward_address = to_space_->Alloc(self_, object_size, &dummy); + } else { + GetHeap()->num_bytes_allocated_.fetch_add(bytes_promoted); + bytes_promoted_ += bytes_promoted; + // Mark forward_address on the live bit map. + accounting::SpaceBitmap* live_bitmap = non_moving_space->GetLiveBitmap(); + DCHECK(live_bitmap != nullptr); + DCHECK(!live_bitmap->Test(forward_address)); + live_bitmap->Set(forward_address); + // Mark forward_address on the mark bit map. + accounting::SpaceBitmap* mark_bitmap = non_moving_space->GetMarkBitmap(); + DCHECK(mark_bitmap != nullptr); + DCHECK(!mark_bitmap->Test(forward_address)); + mark_bitmap->Set(forward_address); + } + DCHECK(forward_address != nullptr); + } else { + // If it's allocated after the last GC (younger), copy it to the to-space. + forward_address = to_space_->Alloc(self_, object_size, &dummy); + } // Copy over the object and add it to the mark stack since we still need to update it's // references. memcpy(reinterpret_cast<void*>(forward_address), obj, object_size); @@ -322,6 +371,9 @@ Object* SemiSpace::MarkObject(Object* obj) { monitor_size_must_be_same_as_object); obj->SetLockWord(LockWord::FromForwardingAddress(reinterpret_cast<size_t>(forward_address))); MarkStackPush(forward_address); + } else { + DCHECK(to_space_->HasAddress(forward_address) || + (kEnableSimplePromo && GetHeap()->GetNonMovingSpace()->HasAddress(forward_address))); } ret = forward_address; // TODO: Do we need this if in the else statement? @@ -535,7 +587,9 @@ inline Object* SemiSpace::GetMarkedForwardAddress(mirror::Object* obj) const if (from_space_->HasAddress(obj)) { mirror::Object* forwarding_address = GetForwardingAddressInFromSpace(const_cast<Object*>(obj)); // If the object is forwarded then it MUST be marked. - if (to_space_->HasAddress(forwarding_address)) { + DCHECK(forwarding_address == nullptr || to_space_->HasAddress(forwarding_address) || + (kEnableSimplePromo && GetHeap()->GetNonMovingSpace()->HasAddress(forwarding_address))); + if (forwarding_address != nullptr) { return forwarding_address; } // Must not be marked, return nullptr; diff --git a/runtime/gc/collector/semi_space.h b/runtime/gc/collector/semi_space.h index 0f0cae1966..b0724f9c0c 100644 --- a/runtime/gc/collector/semi_space.h +++ b/runtime/gc/collector/semi_space.h @@ -281,6 +281,15 @@ class SemiSpace : public GarbageCollector { Thread* self_; + // Used for kEnableSimplePromo. The end/top of the bump pointer + // space at the end of the last collection. + byte* last_gc_to_space_end_; + + // Used for kEnableSimplePromo. During a collection, keeps track of + // how many bytes of objects have been copied so far from the bump + // pointer space to the non-moving space. + uint64_t bytes_promoted_; + private: DISALLOW_COPY_AND_ASSIGN(SemiSpace); }; |