Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Unified Diff: src/heap/mark-compact.cc

Issue 2498583002: [heap] Minor MC: Add marking (Closed)
Patch Set: Move to concurrent uncomitting of marking deque Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap/mark-compact.h ('k') | test/cctest/heap/heap-utils.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap/mark-compact.cc
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
index 88e6983035cd618394b2d47bc44414b2a37ad7c0..a038fa6056f75036f7b1853553c8f2b3963959bd 100644
--- a/src/heap/mark-compact.cc
+++ b/src/heap/mark-compact.cc
@@ -322,7 +322,6 @@ void MarkCompactCollector::CollectGarbage() {
Finish();
}
-
#ifdef VERIFY_HEAP
void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) {
for (Page* p : *space) {
@@ -354,7 +353,6 @@ void MarkCompactCollector::VerifyMarkbitsAreClean() {
}
}
-
void MarkCompactCollector::VerifyWeakEmbeddedObjectsInCode() {
HeapObjectIterator code_iterator(heap()->code_space());
for (HeapObject* obj = code_iterator.Next(); obj != NULL;
@@ -1083,6 +1081,39 @@ void CodeFlusher::IteratePointersToFromSpace(ObjectVisitor* v) {
}
}
+class StaticYoungGenerationMarkingVisitor
+ : public StaticNewSpaceVisitor<StaticYoungGenerationMarkingVisitor> {
+ public:
+ static void Initialize(Heap* heap) {
+ StaticNewSpaceVisitor<StaticYoungGenerationMarkingVisitor>::Initialize();
+ }
+
+ inline static void VisitPointer(Heap* heap, HeapObject* object, Object** p) {
+ Object* target = *p;
+ if (heap->InNewSpace(target)) {
+ if (MarkRecursively(heap, HeapObject::cast(target))) return;
+ PushOnMarkingDeque(heap, target);
+ }
+ }
+
+ protected:
+ inline static void PushOnMarkingDeque(Heap* heap, Object* obj) {
+ HeapObject* object = HeapObject::cast(obj);
+ MarkBit mark_bit = ObjectMarking::MarkBitFrom(object);
+ heap->mark_compact_collector()->MarkObject(object, mark_bit);
+ }
+
+ inline static bool MarkRecursively(Heap* heap, HeapObject* object) {
+ StackLimitCheck check(heap->isolate());
+ if (check.HasOverflowed()) return false;
+
+ MarkBit mark = ObjectMarking::MarkBitFrom(object);
+ if (Marking::IsBlackOrGrey(mark)) return true;
+ heap->mark_compact_collector()->SetMark(object, mark);
+ IterateBody(object->map(), object);
+ return true;
+ }
+};
class MarkCompactMarkingVisitor
: public StaticMarkingVisitor<MarkCompactMarkingVisitor> {
@@ -1336,11 +1367,12 @@ void MarkCompactCollector::PrepareForCodeFlushing() {
heap()->isolate()->compilation_cache()->IterateFunctions(&visitor);
heap()->isolate()->handle_scope_implementer()->Iterate(&visitor);
- ProcessMarkingDeque();
+ ProcessMarkingDeque<MarkCompactMode::FULL>();
}
// Visitor class for marking heap roots.
+template <MarkCompactMode mode>
class RootMarkingVisitor : public ObjectVisitor {
public:
explicit RootMarkingVisitor(Heap* heap)
@@ -1362,6 +1394,10 @@ class RootMarkingVisitor : public ObjectVisitor {
HeapObject* object = HeapObject::cast(*p);
+ if (mode == MarkCompactMode::YOUNG_GENERATION &&
+ !collector_->heap()->InNewSpace(object))
+ return;
+
MarkBit mark_bit = ObjectMarking::MarkBitFrom(object);
if (Marking::IsBlackOrGrey(mark_bit)) return;
@@ -1369,14 +1405,21 @@ class RootMarkingVisitor : public ObjectVisitor {
// Mark the object.
collector_->SetMark(object, mark_bit);
- // Mark the map pointer and body, and push them on the marking stack.
- MarkBit map_mark = ObjectMarking::MarkBitFrom(map);
- collector_->MarkObject(map, map_mark);
- MarkCompactMarkingVisitor::IterateBody(map, object);
+ switch (mode) {
+ case MarkCompactMode::FULL: {
+ // Mark the map pointer and body, and push them on the marking stack.
+ MarkBit map_mark = ObjectMarking::MarkBitFrom(map);
+ collector_->MarkObject(map, map_mark);
+ MarkCompactMarkingVisitor::IterateBody(map, object);
+ } break;
+ case MarkCompactMode::YOUNG_GENERATION:
+ StaticYoungGenerationMarkingVisitor::IterateBody(map, object);
+ break;
+ }
// Mark all the objects reachable from the map and body. May leave
// overflowed objects in the heap.
- collector_->EmptyMarkingDeque();
+ collector_->EmptyMarkingDeque<mode>();
}
MarkCompactCollector* collector_;
@@ -1946,8 +1989,8 @@ bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap,
return Marking::IsWhite(mark);
}
-
-void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) {
+void MarkCompactCollector::MarkStringTable(
+ RootMarkingVisitor<MarkCompactMode::FULL>* visitor) {
StringTable* string_table = heap()->string_table();
// Mark the string table itself.
MarkBit string_table_mark = ObjectMarking::MarkBitFrom(string_table);
@@ -1957,7 +2000,7 @@ void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) {
}
// Explicitly mark the prefix.
string_table->IteratePrefix(visitor);
- ProcessMarkingDeque();
+ ProcessMarkingDeque<MarkCompactMode::FULL>();
}
@@ -1966,8 +2009,8 @@ void MarkCompactCollector::MarkAllocationSite(AllocationSite* site) {
SetMark(site, mark_bit);
}
-
-void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
+void MarkCompactCollector::MarkRoots(
+ RootMarkingVisitor<MarkCompactMode::FULL>* visitor) {
// Mark the heap roots including global variables, stack variables,
// etc., and all objects reachable from them.
heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG);
@@ -1977,8 +2020,8 @@ void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) {
// There may be overflowed objects in the heap. Visit them now.
while (marking_deque()->overflowed()) {
- RefillMarkingDeque();
- EmptyMarkingDeque();
+ RefillMarkingDeque<MarkCompactMode::FULL>();
+ EmptyMarkingDeque<MarkCompactMode::FULL>();
}
}
@@ -2018,6 +2061,7 @@ void MarkCompactCollector::MarkImplicitRefGroups(
// Before: the marking stack contains zero or more heap object pointers.
// After: the marking stack is empty, and all objects reachable from the
// marking stack have been marked, or are overflowed in the heap.
+template <MarkCompactMode mode>
void MarkCompactCollector::EmptyMarkingDeque() {
while (!marking_deque()->IsEmpty()) {
HeapObject* object = marking_deque()->Pop();
@@ -2028,10 +2072,17 @@ void MarkCompactCollector::EmptyMarkingDeque() {
DCHECK(!Marking::IsWhite(ObjectMarking::MarkBitFrom(object)));
Map* map = object->map();
- MarkBit map_mark = ObjectMarking::MarkBitFrom(map);
- MarkObject(map, map_mark);
-
- MarkCompactMarkingVisitor::IterateBody(map, object);
+ switch (mode) {
+ case MarkCompactMode::FULL: {
+ MarkBit map_mark = ObjectMarking::MarkBitFrom(map);
+ MarkObject(map, map_mark);
+ MarkCompactMarkingVisitor::IterateBody(map, object);
+ } break;
+ case MarkCompactMode::YOUNG_GENERATION: {
+ DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
+ StaticYoungGenerationMarkingVisitor::IterateBody(map, object);
+ } break;
+ }
}
}
@@ -2041,6 +2092,7 @@ void MarkCompactCollector::EmptyMarkingDeque() {
// before sweeping completes. If sweeping completes, there are no remaining
// overflowed objects in the heap so the overflow flag on the markings stack
// is cleared.
+template <MarkCompactMode mode>
void MarkCompactCollector::RefillMarkingDeque() {
isolate()->CountUsage(v8::Isolate::UseCounterFeature::kMarkDequeOverflow);
DCHECK(marking_deque()->overflowed());
@@ -2048,18 +2100,17 @@ void MarkCompactCollector::RefillMarkingDeque() {
DiscoverGreyObjectsInNewSpace();
if (marking_deque()->IsFull()) return;
- DiscoverGreyObjectsInSpace(heap()->old_space());
- if (marking_deque()->IsFull()) return;
-
- DiscoverGreyObjectsInSpace(heap()->code_space());
- if (marking_deque()->IsFull()) return;
-
- DiscoverGreyObjectsInSpace(heap()->map_space());
- if (marking_deque()->IsFull()) return;
-
- LargeObjectIterator lo_it(heap()->lo_space());
- DiscoverGreyObjectsWithIterator(&lo_it);
- if (marking_deque()->IsFull()) return;
+ if (mode == MarkCompactMode::FULL) {
+ DiscoverGreyObjectsInSpace(heap()->old_space());
+ if (marking_deque()->IsFull()) return;
+ DiscoverGreyObjectsInSpace(heap()->code_space());
+ if (marking_deque()->IsFull()) return;
+ DiscoverGreyObjectsInSpace(heap()->map_space());
+ if (marking_deque()->IsFull()) return;
+ LargeObjectIterator lo_it(heap()->lo_space());
+ DiscoverGreyObjectsWithIterator(&lo_it);
+ if (marking_deque()->IsFull()) return;
+ }
marking_deque()->ClearOverflowed();
}
@@ -2069,12 +2120,14 @@ void MarkCompactCollector::RefillMarkingDeque() {
// stack. Before: the marking stack contains zero or more heap object
// pointers. After: the marking stack is empty and there are no overflowed
// objects in the heap.
+template <MarkCompactMode mode>
void MarkCompactCollector::ProcessMarkingDeque() {
- EmptyMarkingDeque();
+ EmptyMarkingDeque<mode>();
while (marking_deque()->overflowed()) {
- RefillMarkingDeque();
- EmptyMarkingDeque();
+ RefillMarkingDeque<mode>();
+ EmptyMarkingDeque<mode>();
}
+ DCHECK(marking_deque()->IsEmpty());
}
// Mark all objects reachable (transitively) from objects on the marking
@@ -2099,7 +2152,7 @@ void MarkCompactCollector::ProcessEphemeralMarking(
}
ProcessWeakCollections();
work_to_do = !marking_deque()->IsEmpty();
- ProcessMarkingDeque();
+ ProcessMarkingDeque<MarkCompactMode::FULL>();
}
}
@@ -2114,7 +2167,7 @@ void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) {
if (!code->CanDeoptAt(it.frame()->pc())) {
Code::BodyDescriptor::IterateBody(code, visitor);
}
- ProcessMarkingDeque();
+ ProcessMarkingDeque<MarkCompactMode::FULL>();
return;
}
}
@@ -2154,6 +2207,7 @@ void MarkingDeque::StartUsing() {
void MarkingDeque::StopUsing() {
base::LockGuard<base::Mutex> guard(&mutex_);
+ if (!in_use_) return;
DCHECK(IsEmpty());
DCHECK(!overflowed_);
top_ = bottom_ = mask_ = 0;
@@ -2267,6 +2321,95 @@ void MarkCompactCollector::RecordObjectStats() {
}
}
+SlotCallbackResult MarkCompactCollector::CheckAndMarkObject(
+ Heap* heap, Address slot_address) {
+ Object* object = *reinterpret_cast<Object**>(slot_address);
+ if (heap->InNewSpace(object)) {
+ // Marking happens before flipping the young generation, so the object
+ // has to be in ToSpace.
+ DCHECK(heap->InToSpace(object));
+ HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
+ MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object);
+ if (Marking::IsBlackOrGrey(mark_bit)) {
+ return KEEP_SLOT;
+ }
+ heap->mark_compact_collector()->SetMark(heap_object, mark_bit);
+ StaticYoungGenerationMarkingVisitor::IterateBody(heap_object->map(),
+ heap_object);
+ return KEEP_SLOT;
+ }
+ return REMOVE_SLOT;
+}
+
+static bool IsUnmarkedObject(Heap* heap, Object** p) {
+ DCHECK_IMPLIES(heap->InNewSpace(*p), heap->InToSpace(*p));
+ return heap->InNewSpace(*p) &&
+ !Marking::IsBlack(ObjectMarking::MarkBitFrom(HeapObject::cast(*p)));
+}
+
+void MarkCompactCollector::MarkLiveObjectsInYoungGeneration() {
+ TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK);
+
+ PostponeInterruptsScope postpone(isolate());
+
+ StaticYoungGenerationMarkingVisitor::Initialize(heap());
+ RootMarkingVisitor<MarkCompactMode::YOUNG_GENERATION> root_visitor(heap());
+
+ marking_deque()->StartUsing();
+
+ isolate()->global_handles()->IdentifyWeakUnmodifiedObjects(
+ &Heap::IsUnmodifiedHeapObject);
+
+ {
+ TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_ROOTS);
+ heap()->IterateRoots(&root_visitor, VISIT_ALL_IN_SCAVENGE);
+ ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
+ }
+
+ {
+ TRACE_GC(heap()->tracer(),
+ GCTracer::Scope::MINOR_MC_MARK_OLD_TO_NEW_POINTERS);
+ RememberedSet<OLD_TO_NEW>::Iterate(heap(), [this](Address addr) {
+ return CheckAndMarkObject(heap(), addr);
+ });
+ RememberedSet<OLD_TO_NEW>::IterateTyped(
+ heap(), [this](SlotType type, Address host_addr, Address addr) {
+ return UpdateTypedSlotHelper::UpdateTypedSlot(
+ isolate(), type, addr, [this](Object** addr) {
+ return CheckAndMarkObject(heap(),
+ reinterpret_cast<Address>(addr));
+ });
+ });
+ ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
+ }
+
+ {
+ TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_WEAK);
+ heap()->VisitEncounteredWeakCollections(&root_visitor);
+ ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
+ }
+
+ if (is_code_flushing_enabled()) {
+ TRACE_GC(heap()->tracer(),
+ GCTracer::Scope::MINOR_MC_MARK_CODE_FLUSH_CANDIDATES);
+ code_flusher()->IteratePointersToFromSpace(&root_visitor);
+ ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
+ }
+
+ {
+ TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_GLOBAL_HANDLES);
+ isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending(
+ &IsUnmarkedObject);
+ isolate()
+ ->global_handles()
+ ->IterateNewSpaceWeakUnmodifiedRoots<GlobalHandles::VISIT_OTHERS>(
+ &root_visitor);
+ ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
+ }
+
+ marking_deque()->StopUsing();
+}
+
void MarkCompactCollector::MarkLiveObjects() {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK);
// The recursive GC marker detects when it is nearing stack overflow,
@@ -2296,7 +2439,7 @@ void MarkCompactCollector::MarkLiveObjects() {
PrepareForCodeFlushing();
}
- RootMarkingVisitor root_visitor(heap());
+ RootMarkingVisitor<MarkCompactMode::FULL> root_visitor(heap());
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOTS);
@@ -2328,7 +2471,7 @@ void MarkCompactCollector::MarkLiveObjects() {
GCTracer::Scope::MC_MARK_WEAK_CLOSURE_WEAK_HANDLES);
heap()->isolate()->global_handles()->IdentifyWeakHandles(
&IsUnmarkedHeapObject);
- ProcessMarkingDeque();
+ ProcessMarkingDeque<MarkCompactMode::FULL>();
}
// Then we mark the objects.
@@ -2336,7 +2479,7 @@ void MarkCompactCollector::MarkLiveObjects() {
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_MARK_WEAK_CLOSURE_WEAK_ROOTS);
heap()->isolate()->global_handles()->IterateWeakRoots(&root_visitor);
- ProcessMarkingDeque();
+ ProcessMarkingDeque<MarkCompactMode::FULL>();
}
// Repeat Harmony weak maps marking to mark unmarked objects reachable from
« no previous file with comments | « src/heap/mark-compact.h ('k') | test/cctest/heap/heap-utils.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698