Chromium Code Reviews| Index: src/mark-compact.cc |
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc |
| index 5db1b36e02f1ba121062206f9e5b207fdb13637e..e08ff90e36c8e857b723700f3e0512c05dcab4e1 100644 |
| --- a/src/mark-compact.cc |
| +++ b/src/mark-compact.cc |
| @@ -90,6 +90,61 @@ void Marking::TearDown() { |
| } |
| +#ifdef DEBUG |
| +class VerifyMarkingVisitor: public ObjectVisitor { |
| + public: |
| + void VisitPointers(Object** start, Object** end) { |
| + for (Object** current = start; current < end; current++) { |
| + if ((*current)->IsHeapObject()) { |
| + HeapObject* object = HeapObject::cast(*current); |
| + ASSERT(Marking::IsMarked(object)); |
| + } |
| + } |
| + } |
| +}; |
| + |
|
Erik Corry
2011/02/22 12:27:19
2 blank lines here and several places.
Vyacheslav Egorov (Chromium)
2011/02/23 14:31:46
Done.
|
| +static void VerifyMarking(Address bottom, Address top) { |
| + VerifyMarkingVisitor visitor; |
| + HeapObject* object; |
| + |
| + for (Address current = bottom; |
| + current < top; |
| + current += object->Size()) { |
| + object = HeapObject::FromAddress(current); |
| + if (Marking::IsMarked(object)) object->Iterate(&visitor); |
| + } |
| + |
| +} |
| + |
| +static void VerifyMarking(Page* p) { |
| + VerifyMarking(p->ObjectAreaStart(), p->AllocationTop()); |
| +} |
| + |
| +static void VerifyMarking(NewSpace* space) { |
| + VerifyMarking(space->bottom(), space->top()); |
| +} |
| + |
| +static void VerifyMarking(PagedSpace* space) { |
| + PageIterator it(space, PageIterator::PAGES_IN_USE); |
| + |
| + while (it.has_next()) { |
| + VerifyMarking(it.next()); |
| + } |
| +} |
| + |
| +static void VerifyMarking() { |
| + VerifyMarking(Heap::old_pointer_space()); |
| + VerifyMarking(Heap::old_data_space()); |
| + VerifyMarking(Heap::code_space()); |
| + VerifyMarking(Heap::cell_space()); |
| + VerifyMarking(Heap::map_space()); |
| + VerifyMarking(Heap::new_space()); |
| + |
| + VerifyMarkingVisitor visitor; |
| + Heap::IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
| +} |
| +#endif |
| + |
| void MarkCompactCollector::CollectGarbage() { |
| // Make sure that Prepare() has been called. The individual steps below will |
| // update the state as they proceed. |
| @@ -97,11 +152,23 @@ void MarkCompactCollector::CollectGarbage() { |
| // Prepare has selected whether to compact the old generation or not. |
| // Tell the tracer. |
| - if (IsCompacting()) tracer_->set_is_compacting(); |
| + // if (IsCompacting()) tracer_->set_is_compacting(); |
|
Erik Corry
2011/02/22 12:27:19
Commented code.
Vyacheslav Egorov (Chromium)
2011/02/23 14:31:46
Done.
|
| - MarkLiveObjects(); |
| + if (IncrementalMarking::state() == IncrementalMarking::STOPPED) { |
| + MarkLiveObjects(); |
| + } else { |
| + { |
| + GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_MARK); |
| + IncrementalMarking::Finalize(); |
| + ASSERT(IncrementalMarking::state() == IncrementalMarking::STOPPED); |
| + } |
| + MarkLiveObjects(); |
| + } |
| - if (FLAG_collect_maps) ClearNonLiveTransitions(); |
| +#ifdef DEBUG |
| + VerifyMarking(); |
| +#endif |
| + // if (FLAG_collect_maps) ClearNonLiveTransitions(); |
| SweepSpaces(); |
| @@ -154,11 +221,37 @@ static void ClearMarkbits() { |
| } |
| +void Marking::TransferMark(Address old_start, Address new_start) { |
| + if (IncrementalMarking::state() == IncrementalMarking::MARKING) { |
| + if (IncrementalMarking::IsBlack(HeapObject::FromAddress(old_start))) { |
| + IncrementalMarking::MarkBlack(HeapObject::FromAddress(new_start)); |
| + } else if (IncrementalMarking::IsGrey(HeapObject::FromAddress(old_start))) { |
| + IncrementalMarking::WhiteToGrey(HeapObject::FromAddress(new_start)); |
| + // TODO(gc): if we shift huge array in the loop we might end up pushing |
| + // to much to marking stack. maybe we should check one or two elements |
| + // on top of it to see whether they are equal to old_start. |
|
Erik Corry
2011/02/22 12:27:19
Or perhaps we should compact the marking stack by
Vyacheslav Egorov (Chromium)
2011/02/23 14:31:46
We will think about it.
|
| + } |
| + } else { |
| + if (Heap::InNewSpace(old_start) || |
| + Page::FromAddress(old_start)->IsFlagSet(Page::IS_CONTINUOUS) || |
| + !IsMarked(old_start)) { |
| + return; |
| + } |
| + SetMark(new_start); |
| + } |
| +} |
| + |
| + |
| void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| FLAG_flush_code = false; |
| FLAG_always_compact = false; |
| FLAG_never_compact = true; |
| + // Disable collection of maps if incremental marking is enabled. |
| + // TODO(gc) improve maps collection algorithm to work with incremental |
| + // marking. |
| + if (FLAG_incremental_marking) FLAG_collect_maps = false; |
| + |
| // Rather than passing the tracer around we stash it in a static member |
| // variable. |
| tracer_ = tracer; |
| @@ -174,8 +267,9 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| compact_on_next_gc_ = false; |
| if (FLAG_never_compact) compacting_collection_ = false; |
| - if (!Heap::map_space()->MapPointersEncodable()) |
| - compacting_collection_ = false; |
| + if (!Heap::map_space()->MapPointersEncodable()) { |
| + compacting_collection_ = false; |
| + } |
| if (FLAG_collect_maps) CreateBackPointers(); |
| #ifdef ENABLE_GDB_JIT_INTERFACE |
| if (FLAG_gdbjit) { |
| @@ -190,17 +284,20 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| space->PrepareForMarkCompact(compacting_collection_); |
| } |
| - Address new_space_top = Heap::new_space()->top(); |
| - Address new_space_bottom = Heap::new_space()->bottom(); |
| + if (IncrementalMarking::state() == IncrementalMarking::STOPPED) { |
| + Address new_space_top = Heap::new_space()->top(); |
| + Address new_space_bottom = Heap::new_space()->bottom(); |
| - Marking::ClearRange(new_space_bottom, |
| - static_cast<int>(new_space_top - new_space_bottom)); |
| - |
| - ClearMarkbits(); |
| + Marking::ClearRange(new_space_bottom, |
| + static_cast<int>(new_space_top - new_space_bottom)); |
| + ClearMarkbits(); |
| #ifdef DEBUG |
| - VerifyMarkbitsAreClean(); |
| + VerifyMarkbitsAreClean(); |
| +#endif |
| + } |
| +#ifdef DEBUG |
| live_bytes_ = 0; |
| live_young_objects_size_ = 0; |
| live_old_pointer_objects_size_ = 0; |
| @@ -545,7 +642,7 @@ class StaticMarkingVisitor : public StaticVisitorBase { |
| Object* old_cell = cell; |
| VisitPointer(&cell); |
| if (cell != old_cell) { |
| - rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell)); |
| + rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell), NULL); |
| } |
| } |
| @@ -792,6 +889,8 @@ class StaticMarkingVisitor : public StaticVisitorBase { |
| static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) { |
| + UNREACHABLE(); |
|
Erik Corry
2011/02/22 12:27:19
TODO?
Vyacheslav Egorov (Chromium)
2011/02/23 14:31:46
Done.
|
| +#if 0 |
|
Erik Corry
2011/02/22 12:27:19
Commented code.
Vyacheslav Egorov (Chromium)
2011/02/23 14:31:46
Done.
|
| JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object); |
| // The function must have a valid context and not be a builtin. |
| bool flush_code_candidate = false; |
| @@ -826,6 +925,7 @@ class StaticMarkingVisitor : public StaticVisitorBase { |
| VisitJSFunctionFields(map, |
| reinterpret_cast<JSFunction*>(object), |
| flush_code_candidate); |
| +#endif |
| } |
| @@ -1072,13 +1172,14 @@ void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) { |
| if (FLAG_cleanup_caches_in_maps_at_gc) { |
| map->ClearCodeCache(); |
| } |
| - if (FLAG_collect_maps && |
| + /*if (FLAG_collect_maps && |
|
Erik Corry
2011/02/22 12:27:19
Commented code. TODO?
Vyacheslav Egorov (Chromium)
2011/02/23 14:31:46
Done.
|
| map->instance_type() >= FIRST_JS_OBJECT_TYPE && |
| map->instance_type() <= JS_FUNCTION_TYPE) { |
| + UNREACHABLE(); |
| MarkMapContents(map); |
| - } else { |
| + } else {*/ |
| marking_stack.Push(map); |
| - } |
| + /*}*/ |
| } else { |
| marking_stack.Push(object); |
| } |
| @@ -1388,6 +1489,11 @@ void MarkCompactCollector::MarkLiveObjects() { |
| // weak roots. |
| ProcessObjectGroups(); |
| + AfterMarking(); |
| +} |
| + |
| + |
| +void MarkCompactCollector::AfterMarking() { |
| // Prune the symbol table removing all symbols only pointed to by the |
| // symbol table. Cannot use symbol_table() here because the symbol |
| // table is marked. |
| @@ -1406,7 +1512,7 @@ void MarkCompactCollector::MarkLiveObjects() { |
| GlobalHandles::RemoveObjectGroups(); |
| // Flush code from collected candidates. |
| - FlushCode::ProcessCandidates(); |
| + // FlushCode::ProcessCandidates(); |
|
Erik Corry
2011/02/22 12:27:19
Commented code and missing TODO'
Vyacheslav Egorov (Chromium)
2011/02/23 14:31:46
Done.
|
| } |
| @@ -1566,7 +1672,7 @@ class PointersToNewGenUpdatingVisitor: public ObjectVisitor { |
| ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
| Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| VisitPointer(&target); |
| - rinfo->set_target_address(Code::cast(target)->instruction_start()); |
| + rinfo->set_target_address(Code::cast(target)->instruction_start(), NULL); |
| } |
| void VisitDebugTarget(RelocInfo* rinfo) { |
| @@ -1896,6 +2002,9 @@ static void SweepPrecisely(PagedSpace* space, |
| is_previous_alive = true; |
| } |
| } else { |
| + ASSERT((current + kPointerSize) >= p->AllocationTop() || |
| + object->Size() == 4 || |
|
Erik Corry
2011/02/22 12:27:19
kPointerSize?
Vyacheslav Egorov (Chromium)
2011/02/23 14:31:46
Done.
|
| + IncrementalMarking::IsWhite(object)); |
| MarkCompactCollector::ReportDeleteIfNeeded(object); |
| if (is_previous_alive) { // Transition from live to free. |
| free_start = current; |
| @@ -2038,17 +2147,24 @@ void MarkCompactCollector::SweepSpaces() { |
| #ifdef DEBUG |
| state_ = SWEEP_SPACES; |
| #endif |
| + |
| +#ifndef DEBUG |
| + SweeperType fast_sweeper = CONSERVATIVE; |
| +#else |
| + SweeperType fast_sweeper = PRECISE; |
| +#endif |
| + |
| ASSERT(!IsCompacting()); |
| // Noncompacting collections simply sweep the spaces to clear the mark |
| // bits and free the nonlive blocks (for old and map spaces). We sweep |
| // the map space last because freeing non-live maps overwrites them and |
| // the other spaces rely on possibly non-live maps to get the sizes for |
| // non-live objects. |
| - SweepSpace(Heap::old_pointer_space(), CONSERVATIVE); |
| - SweepSpace(Heap::old_data_space(), CONSERVATIVE); |
| + SweepSpace(Heap::old_pointer_space(), fast_sweeper); |
| + SweepSpace(Heap::old_data_space(), fast_sweeper); |
| SweepSpace(Heap::code_space(), PRECISE); |
| // TODO(gc): implement specialized sweeper for cell space. |
| - SweepSpace(Heap::cell_space(), CONSERVATIVE); |
| + SweepSpace(Heap::cell_space(), fast_sweeper); |
| { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); |
| SweepNewSpace(Heap::new_space()); |
| } |