Commit bfefce1e authored by mlippautz's avatar mlippautz Committed by Commit bot

[heap] Buffer counter updates for new space evacuation.

* Buffer counter updates in the corresponding visitor to allow parallel
  processing of pages.
* Fix a bug where we don't keep live bytes in sync when marking is already
  finished.

LOG=N
BUG=524425

Review URL: https://codereview.chromium.org/1559873004

Cr-Commit-Position: refs/heads/master@{#33170}
parent 0a808704
...@@ -165,6 +165,7 @@ Heap::Heap() ...@@ -165,6 +165,7 @@ Heap::Heap()
deserialization_complete_(false), deserialization_complete_(false),
strong_roots_list_(NULL), strong_roots_list_(NULL),
array_buffer_tracker_(NULL), array_buffer_tracker_(NULL),
heap_iterator_depth_(0),
force_oom_(false) { force_oom_(false) {
// Allow build-time customization of the max semispace size. Building // Allow build-time customization of the max semispace size. Building
// V8 with snapshots and a non-default max semispace size is much // V8 with snapshots and a non-default max semispace size is much
...@@ -3102,7 +3103,11 @@ bool Heap::CanMoveObjectStart(HeapObject* object) { ...@@ -3102,7 +3103,11 @@ bool Heap::CanMoveObjectStart(HeapObject* object) {
void Heap::AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode) { void Heap::AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode) {
if (incremental_marking()->IsMarking() && // As long as the inspected object is black and we are currently not iterating
// the heap using HeapIterator, we can update the live byte count. We cannot
// update while using HeapIterator because the iterator is temporarily
// marking the whole object graph, without updating live bytes.
if (!in_heap_iterator() &&
Marking::IsBlack(Marking::MarkBitFrom(object->address()))) { Marking::IsBlack(Marking::MarkBitFrom(object->address()))) {
if (mode == SEQUENTIAL_TO_SWEEPER) { if (mode == SEQUENTIAL_TO_SWEEPER) {
MemoryChunk::IncrementLiveBytesFromGC(object, by); MemoryChunk::IncrementLiveBytesFromGC(object, by);
...@@ -5659,6 +5664,7 @@ HeapIterator::HeapIterator(Heap* heap, ...@@ -5659,6 +5664,7 @@ HeapIterator::HeapIterator(Heap* heap,
filter_(nullptr), filter_(nullptr),
space_iterator_(nullptr), space_iterator_(nullptr),
object_iterator_(nullptr) { object_iterator_(nullptr) {
heap_->heap_iterator_start();
// Start the iteration. // Start the iteration.
space_iterator_ = new SpaceIterator(heap_); space_iterator_ = new SpaceIterator(heap_);
switch (filtering_) { switch (filtering_) {
...@@ -5673,6 +5679,7 @@ HeapIterator::HeapIterator(Heap* heap, ...@@ -5673,6 +5679,7 @@ HeapIterator::HeapIterator(Heap* heap,
HeapIterator::~HeapIterator() { HeapIterator::~HeapIterator() {
heap_->heap_iterator_end();
#ifdef DEBUG #ifdef DEBUG
// Assert that in filtering mode we have iterated through all // Assert that in filtering mode we have iterated through all
// objects. Otherwise, heap will be left in an inconsistent state. // objects. Otherwise, heap will be left in an inconsistent state.
......
...@@ -1415,13 +1415,13 @@ class Heap { ...@@ -1415,13 +1415,13 @@ class Heap {
void UpdateSurvivalStatistics(int start_new_space_size); void UpdateSurvivalStatistics(int start_new_space_size);
inline void IncrementPromotedObjectsSize(int object_size) { inline void IncrementPromotedObjectsSize(int object_size) {
DCHECK(object_size > 0); DCHECK_GE(object_size, 0);
promoted_objects_size_ += object_size; promoted_objects_size_ += object_size;
} }
inline intptr_t promoted_objects_size() { return promoted_objects_size_; } inline intptr_t promoted_objects_size() { return promoted_objects_size_; }
inline void IncrementSemiSpaceCopiedObjectSize(int object_size) { inline void IncrementSemiSpaceCopiedObjectSize(int object_size) {
DCHECK(object_size > 0); DCHECK_GE(object_size, 0);
semi_space_copied_object_size_ += object_size; semi_space_copied_object_size_ += object_size;
} }
inline intptr_t semi_space_copied_object_size() { inline intptr_t semi_space_copied_object_size() {
...@@ -1930,6 +1930,16 @@ class Heap { ...@@ -1930,6 +1930,16 @@ class Heap {
bool RecentIdleNotificationHappened(); bool RecentIdleNotificationHappened();
void ScheduleIdleScavengeIfNeeded(int bytes_allocated); void ScheduleIdleScavengeIfNeeded(int bytes_allocated);
// ===========================================================================
// HeapIterator helpers. =====================================================
// ===========================================================================
void heap_iterator_start() { heap_iterator_depth_++; }
void heap_iterator_end() { heap_iterator_depth_--; }
bool in_heap_iterator() { return heap_iterator_depth_ > 0; }
// =========================================================================== // ===========================================================================
// Allocation methods. ======================================================= // Allocation methods. =======================================================
// =========================================================================== // ===========================================================================
...@@ -2383,6 +2393,9 @@ class Heap { ...@@ -2383,6 +2393,9 @@ class Heap {
ArrayBufferTracker* array_buffer_tracker_; ArrayBufferTracker* array_buffer_tracker_;
// The depth of HeapIterator nestings.
int heap_iterator_depth_;
// Used for testing purposes. // Used for testing purposes.
bool force_oom_; bool force_oom_;
......
...@@ -1617,7 +1617,9 @@ class MarkCompactCollector::EvacuateNewSpaceVisitor final ...@@ -1617,7 +1617,9 @@ class MarkCompactCollector::EvacuateNewSpaceVisitor final
SlotsBuffer** evacuation_slots_buffer) SlotsBuffer** evacuation_slots_buffer)
: EvacuateVisitorBase(heap, evacuation_slots_buffer), : EvacuateVisitorBase(heap, evacuation_slots_buffer),
buffer_(LocalAllocationBuffer::InvalidBuffer()), buffer_(LocalAllocationBuffer::InvalidBuffer()),
space_to_allocate_(NEW_SPACE) {} space_to_allocate_(NEW_SPACE),
promoted_size_(0),
semispace_copied_size_(0) {}
bool Visit(HeapObject* object) override { bool Visit(HeapObject* object) override {
Heap::UpdateAllocationSiteFeedback(object, Heap::RECORD_SCRATCHPAD_SLOT); Heap::UpdateAllocationSiteFeedback(object, Heap::RECORD_SCRATCHPAD_SLOT);
...@@ -1630,7 +1632,7 @@ class MarkCompactCollector::EvacuateNewSpaceVisitor final ...@@ -1630,7 +1632,7 @@ class MarkCompactCollector::EvacuateNewSpaceVisitor final
heap_->array_buffer_tracker()->Promote( heap_->array_buffer_tracker()->Promote(
JSArrayBuffer::cast(target_object)); JSArrayBuffer::cast(target_object));
} }
heap_->IncrementPromotedObjectsSize(size); promoted_size_ += size;
return true; return true;
} }
HeapObject* target = nullptr; HeapObject* target = nullptr;
...@@ -1641,10 +1643,13 @@ class MarkCompactCollector::EvacuateNewSpaceVisitor final ...@@ -1641,10 +1643,13 @@ class MarkCompactCollector::EvacuateNewSpaceVisitor final
if (V8_UNLIKELY(target->IsJSArrayBuffer())) { if (V8_UNLIKELY(target->IsJSArrayBuffer())) {
heap_->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(target)); heap_->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(target));
} }
heap_->IncrementSemiSpaceCopiedObjectSize(size); semispace_copied_size_ += size;
return true; return true;
} }
intptr_t promoted_size() { return promoted_size_; }
intptr_t semispace_copied_size() { return semispace_copied_size_; }
private: private:
enum NewSpaceAllocationMode { enum NewSpaceAllocationMode {
kNonstickyBailoutOldSpace, kNonstickyBailoutOldSpace,
...@@ -1742,6 +1747,8 @@ class MarkCompactCollector::EvacuateNewSpaceVisitor final ...@@ -1742,6 +1747,8 @@ class MarkCompactCollector::EvacuateNewSpaceVisitor final
LocalAllocationBuffer buffer_; LocalAllocationBuffer buffer_;
AllocationSpace space_to_allocate_; AllocationSpace space_to_allocate_;
intptr_t promoted_size_;
intptr_t semispace_copied_size_;
}; };
...@@ -3096,8 +3103,6 @@ void MarkCompactCollector::EvacuateNewSpace() { ...@@ -3096,8 +3103,6 @@ void MarkCompactCollector::EvacuateNewSpace() {
new_space->Flip(); new_space->Flip();
new_space->ResetAllocationInfo(); new_space->ResetAllocationInfo();
int survivors_size = 0;
// First pass: traverse all objects in inactive semispace, remove marks, // First pass: traverse all objects in inactive semispace, remove marks,
// migrate live objects and write forwarding addresses. This stage puts // migrate live objects and write forwarding addresses. This stage puts
// new entries in the store buffer and may cause some pages to be marked // new entries in the store buffer and may cause some pages to be marked
...@@ -3106,13 +3111,17 @@ void MarkCompactCollector::EvacuateNewSpace() { ...@@ -3106,13 +3111,17 @@ void MarkCompactCollector::EvacuateNewSpace() {
EvacuateNewSpaceVisitor new_space_visitor(heap(), &migration_slots_buffer_); EvacuateNewSpaceVisitor new_space_visitor(heap(), &migration_slots_buffer_);
while (it.has_next()) { while (it.has_next()) {
NewSpacePage* p = it.next(); NewSpacePage* p = it.next();
survivors_size += p->LiveBytes();
bool ok = VisitLiveObjects(p, &new_space_visitor, kClearMarkbits); bool ok = VisitLiveObjects(p, &new_space_visitor, kClearMarkbits);
USE(ok); USE(ok);
DCHECK(ok); DCHECK(ok);
} }
heap_->IncrementPromotedObjectsSize(
heap_->IncrementYoungSurvivorsCounter(survivors_size); static_cast<int>(new_space_visitor.promoted_size()));
heap_->IncrementSemiSpaceCopiedObjectSize(
static_cast<int>(new_space_visitor.semispace_copied_size()));
heap_->IncrementYoungSurvivorsCounter(
static_cast<int>(new_space_visitor.promoted_size()) +
static_cast<int>(new_space_visitor.semispace_copied_size()));
new_space->set_age_mark(new_space->top()); new_space->set_age_mark(new_space->top());
} }
......
...@@ -595,6 +595,7 @@ class MemoryChunk { ...@@ -595,6 +595,7 @@ class MemoryChunk {
} }
live_byte_count_ = 0; live_byte_count_ = 0;
} }
void IncrementLiveBytes(int by) { void IncrementLiveBytes(int by) {
if (FLAG_gc_verbose) { if (FLAG_gc_verbose) {
printf("UpdateLiveBytes:%p:%x%c=%x->%x\n", static_cast<void*>(this), printf("UpdateLiveBytes:%p:%x%c=%x->%x\n", static_cast<void*>(this),
...@@ -602,10 +603,12 @@ class MemoryChunk { ...@@ -602,10 +603,12 @@ class MemoryChunk {
live_byte_count_ + by); live_byte_count_ + by);
} }
live_byte_count_ += by; live_byte_count_ += by;
DCHECK_GE(live_byte_count_, 0);
DCHECK_LE(static_cast<unsigned>(live_byte_count_), size_); DCHECK_LE(static_cast<unsigned>(live_byte_count_), size_);
} }
int LiveBytes() { int LiveBytes() {
DCHECK(static_cast<unsigned>(live_byte_count_) <= size_); DCHECK_LE(static_cast<unsigned>(live_byte_count_), size_);
return live_byte_count_; return live_byte_count_;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment