Commit 33922309 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[heap] Simplify MarkingDeque implementation.

This removes the dependency of the MarkingDeque on the underlying
collector by moving out the live bytes accounting and object color
mutations into a wrapper. The MarkingDeque can now be split into a
separate file.

R=hpayer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#30194}
parent bfbc5e7c
...@@ -202,7 +202,7 @@ class IncrementalMarkingMarkingVisitor ...@@ -202,7 +202,7 @@ class IncrementalMarkingMarkingVisitor
heap->mark_compact_collector()->marking_deque()->UnshiftGrey(object); heap->mark_compact_collector()->marking_deque()->UnshiftGrey(object);
} else { } else {
DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
heap->mark_compact_collector()->marking_deque()->UnshiftBlack(object); heap->mark_compact_collector()->UnshiftBlack(object);
} }
heap->incremental_marking()->NotifyIncompleteScanOfObject( heap->incremental_marking()->NotifyIncompleteScanOfObject(
object_size - (start_offset - already_scanned_offset)); object_size - (start_offset - already_scanned_offset));
......
...@@ -23,13 +23,29 @@ void MarkCompactCollector::SetFlags(int flags) { ...@@ -23,13 +23,29 @@ void MarkCompactCollector::SetFlags(int flags) {
} }
void MarkCompactCollector::PushBlack(HeapObject* obj) {
if (marking_deque_.PushBlack(obj)) {
MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
} else {
Marking::BlackToGrey(obj);
}
}
void MarkCompactCollector::UnshiftBlack(HeapObject* obj) {
if (!marking_deque_.UnshiftBlack(obj)) {
MemoryChunk::IncrementLiveBytesFromGC(obj, -obj->Size());
Marking::BlackToGrey(obj);
}
}
void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) { void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
DCHECK(Marking::MarkBitFrom(obj) == mark_bit); DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
if (Marking::IsWhite(mark_bit)) { if (Marking::IsWhite(mark_bit)) {
Marking::WhiteToBlack(mark_bit); Marking::WhiteToBlack(mark_bit);
MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
DCHECK(obj->GetIsolate()->heap()->Contains(obj)); DCHECK(obj->GetIsolate()->heap()->Contains(obj));
marking_deque_.PushBlack(obj); PushBlack(obj);
} }
} }
......
...@@ -1734,21 +1734,18 @@ class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { ...@@ -1734,21 +1734,18 @@ class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
// iterator. Stop when the marking stack is filled or the end of the space // iterator. Stop when the marking stack is filled or the end of the space
// is reached, whichever comes first. // is reached, whichever comes first.
template <class T> template <class T>
static void DiscoverGreyObjectsWithIterator(Heap* heap, void MarkCompactCollector::DiscoverGreyObjectsWithIterator(T* it) {
MarkingDeque* marking_deque,
T* it) {
// The caller should ensure that the marking stack is initially not full, // The caller should ensure that the marking stack is initially not full,
// so that we don't waste effort pointlessly scanning for objects. // so that we don't waste effort pointlessly scanning for objects.
DCHECK(!marking_deque->IsFull()); DCHECK(!marking_deque()->IsFull());
Map* filler_map = heap->one_pointer_filler_map(); Map* filler_map = heap()->one_pointer_filler_map();
for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) { for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) {
MarkBit markbit = Marking::MarkBitFrom(object); MarkBit markbit = Marking::MarkBitFrom(object);
if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { if ((object->map() != filler_map) && Marking::IsGrey(markbit)) {
Marking::GreyToBlack(markbit); Marking::GreyToBlack(markbit);
MemoryChunk::IncrementLiveBytesFromGC(object, object->Size()); PushBlack(object);
marking_deque->PushBlack(object); if (marking_deque()->IsFull()) return;
if (marking_deque->IsFull()) return;
} }
} }
} }
...@@ -1757,9 +1754,8 @@ static void DiscoverGreyObjectsWithIterator(Heap* heap, ...@@ -1757,9 +1754,8 @@ static void DiscoverGreyObjectsWithIterator(Heap* heap,
static inline int MarkWordToObjectStarts(uint32_t mark_bits, int* starts); static inline int MarkWordToObjectStarts(uint32_t mark_bits, int* starts);
static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque, void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) {
MemoryChunk* p) { DCHECK(!marking_deque()->IsFull());
DCHECK(!marking_deque->IsFull());
DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0);
DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0);
DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0);
...@@ -1791,9 +1787,8 @@ static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque, ...@@ -1791,9 +1787,8 @@ static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque,
Marking::GreyToBlack(markbit); Marking::GreyToBlack(markbit);
Address addr = cell_base + offset * kPointerSize; Address addr = cell_base + offset * kPointerSize;
HeapObject* object = HeapObject::FromAddress(addr); HeapObject* object = HeapObject::FromAddress(addr);
MemoryChunk::IncrementLiveBytesFromGC(object, object->Size()); PushBlack(object);
marking_deque->PushBlack(object); if (marking_deque()->IsFull()) return;
if (marking_deque->IsFull()) return;
offset += 2; offset += 2;
grey_objects >>= 2; grey_objects >>= 2;
} }
...@@ -1866,25 +1861,23 @@ int MarkCompactCollector::DiscoverAndEvacuateBlackObjectsOnPage( ...@@ -1866,25 +1861,23 @@ int MarkCompactCollector::DiscoverAndEvacuateBlackObjectsOnPage(
} }
static void DiscoverGreyObjectsInSpace(Heap* heap, MarkingDeque* marking_deque, void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) {
PagedSpace* space) {
PageIterator it(space); PageIterator it(space);
while (it.has_next()) { while (it.has_next()) {
Page* p = it.next(); Page* p = it.next();
DiscoverGreyObjectsOnPage(marking_deque, p); DiscoverGreyObjectsOnPage(p);
if (marking_deque->IsFull()) return; if (marking_deque()->IsFull()) return;
} }
} }
static void DiscoverGreyObjectsInNewSpace(Heap* heap, void MarkCompactCollector::DiscoverGreyObjectsInNewSpace() {
MarkingDeque* marking_deque) { NewSpace* space = heap()->new_space();
NewSpace* space = heap->new_space();
NewSpacePageIterator it(space->bottom(), space->top()); NewSpacePageIterator it(space->bottom(), space->top());
while (it.has_next()) { while (it.has_next()) {
NewSpacePage* page = it.next(); NewSpacePage* page = it.next();
DiscoverGreyObjectsOnPage(marking_deque, page); DiscoverGreyObjectsOnPage(page);
if (marking_deque->IsFull()) return; if (marking_deque()->IsFull()) return;
} }
} }
...@@ -2009,20 +2002,20 @@ void MarkCompactCollector::RefillMarkingDeque() { ...@@ -2009,20 +2002,20 @@ void MarkCompactCollector::RefillMarkingDeque() {
isolate()->CountUsage(v8::Isolate::UseCounterFeature::kMarkDequeOverflow); isolate()->CountUsage(v8::Isolate::UseCounterFeature::kMarkDequeOverflow);
DCHECK(marking_deque_.overflowed()); DCHECK(marking_deque_.overflowed());
DiscoverGreyObjectsInNewSpace(heap(), &marking_deque_); DiscoverGreyObjectsInNewSpace();
if (marking_deque_.IsFull()) return; if (marking_deque_.IsFull()) return;
DiscoverGreyObjectsInSpace(heap(), &marking_deque_, heap()->old_space()); DiscoverGreyObjectsInSpace(heap()->old_space());
if (marking_deque_.IsFull()) return; if (marking_deque_.IsFull()) return;
DiscoverGreyObjectsInSpace(heap(), &marking_deque_, heap()->code_space()); DiscoverGreyObjectsInSpace(heap()->code_space());
if (marking_deque_.IsFull()) return; if (marking_deque_.IsFull()) return;
DiscoverGreyObjectsInSpace(heap(), &marking_deque_, heap()->map_space()); DiscoverGreyObjectsInSpace(heap()->map_space());
if (marking_deque_.IsFull()) return; if (marking_deque_.IsFull()) return;
LargeObjectIterator lo_it(heap()->lo_space()); LargeObjectIterator lo_it(heap()->lo_space());
DiscoverGreyObjectsWithIterator(heap(), &marking_deque_, &lo_it); DiscoverGreyObjectsWithIterator(&lo_it);
if (marking_deque_.IsFull()) return; if (marking_deque_.IsFull()) return;
marking_deque_.ClearOverflowed(); marking_deque_.ClearOverflowed();
......
...@@ -205,18 +205,17 @@ class MarkingDeque { ...@@ -205,18 +205,17 @@ class MarkingDeque {
void SetOverflowed() { overflowed_ = true; } void SetOverflowed() { overflowed_ = true; }
// Push the (marked) object on the marking stack if there is room, // Push the (marked) object on the marking stack if there is room, otherwise
// otherwise mark the object as overflowed and wait for a rescan of the // mark the deque as overflowed and wait for a rescan of the heap.
// heap. INLINE(bool PushBlack(HeapObject* object)) {
INLINE(void PushBlack(HeapObject* object)) {
DCHECK(object->IsHeapObject()); DCHECK(object->IsHeapObject());
if (IsFull()) { if (IsFull()) {
Marking::BlackToGrey(object);
MemoryChunk::IncrementLiveBytesFromGC(object, -object->Size());
SetOverflowed(); SetOverflowed();
return false;
} else { } else {
array_[top_] = object; array_[top_] = object;
top_ = ((top_ + 1) & mask_); top_ = ((top_ + 1) & mask_);
return true;
} }
} }
...@@ -248,16 +247,16 @@ class MarkingDeque { ...@@ -248,16 +247,16 @@ class MarkingDeque {
} }
} }
INLINE(void UnshiftBlack(HeapObject* object)) { INLINE(bool UnshiftBlack(HeapObject* object)) {
DCHECK(object->IsHeapObject()); DCHECK(object->IsHeapObject());
DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
if (IsFull()) { if (IsFull()) {
Marking::BlackToGrey(object);
MemoryChunk::IncrementLiveBytesFromGC(object, -object->Size());
SetOverflowed(); SetOverflowed();
return false;
} else { } else {
bottom_ = ((bottom_ - 1) & mask_); bottom_ = ((bottom_ - 1) & mask_);
array_[bottom_] = object; array_[bottom_] = object;
return true;
} }
} }
...@@ -761,11 +760,12 @@ class MarkCompactCollector { ...@@ -761,11 +760,12 @@ class MarkCompactCollector {
// //
// After: Live objects are marked and non-live objects are unmarked. // After: Live objects are marked and non-live objects are unmarked.
friend class RootMarkingVisitor;
friend class MarkingVisitor;
friend class MarkCompactMarkingVisitor;
friend class CodeMarkingVisitor; friend class CodeMarkingVisitor;
friend class MarkCompactMarkingVisitor;
friend class MarkingVisitor;
friend class RootMarkingVisitor;
friend class SharedFunctionInfoMarkingVisitor; friend class SharedFunctionInfoMarkingVisitor;
friend class IncrementalMarkingMarkingVisitor;
// Mark code objects that are active on the stack to prevent them // Mark code objects that are active on the stack to prevent them
// from being flushed. // from being flushed.
...@@ -778,6 +778,14 @@ class MarkCompactCollector { ...@@ -778,6 +778,14 @@ class MarkCompactCollector {
void AfterMarking(); void AfterMarking();
// Pushes a black object onto the marking stack and accounts for live bytes.
// Note that this assumes live bytes have not yet been counted.
INLINE(void PushBlack(HeapObject* obj));
// Unshifts a black object into the marking stack and accounts for live bytes.
// Note that this assumes lives bytes have already been counted.
INLINE(void UnshiftBlack(HeapObject* obj));
// Marks the object black and pushes it on the marking stack. // Marks the object black and pushes it on the marking stack.
// This is for non-incremental marking only. // This is for non-incremental marking only.
INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit)); INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit));
...@@ -826,6 +834,14 @@ class MarkCompactCollector { ...@@ -826,6 +834,14 @@ class MarkCompactCollector {
// flag on the marking stack. // flag on the marking stack.
void RefillMarkingDeque(); void RefillMarkingDeque();
// Helper methods for refilling the marking stack by discovering grey objects
// on various pages of the heap. Used by {RefillMarkingDeque} only.
template <class T>
void DiscoverGreyObjectsWithIterator(T* it);
void DiscoverGreyObjectsOnPage(MemoryChunk* p);
void DiscoverGreyObjectsInSpace(PagedSpace* space);
void DiscoverGreyObjectsInNewSpace();
// Callback function for telling whether the object *p is an unmarked // Callback function for telling whether the object *p is an unmarked
// heap object. // heap object.
static bool IsUnmarkedHeapObject(Object** p); static bool IsUnmarkedHeapObject(Object** p);
......
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