Chromium Code Reviews| Index: src/mark-compact.cc |
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc |
| index 25d1faa48ceb5ef61d68b9f484abbd5a4f6326c0..5445aea1653a310ce6f7c39a3dca545fc77607d8 100644 |
| --- a/src/mark-compact.cc |
| +++ b/src/mark-compact.cc |
| @@ -57,6 +57,8 @@ MarkCompactCollector::MarkCompactCollector() : // NOLINT |
| #ifdef DEBUG |
| state_(IDLE), |
| #endif |
| + sweep_precisely_(false), |
| + compacting_(false), |
| tracer_(NULL), |
| #ifdef DEBUG |
| live_young_objects_size_(0), |
| @@ -154,7 +156,6 @@ class VerifyEvacuationVisitor: public ObjectVisitor { |
| if ((*current)->IsHeapObject()) { |
| HeapObject* object = HeapObject::cast(*current); |
| if (MarkCompactCollector::IsOnEvacuationCandidate(object)) { |
| - HEAP->TracePathToObject(source_); |
| CHECK(false); |
| } |
| } |
| @@ -225,6 +226,26 @@ void MarkCompactCollector::AddEvacuationCandidate(Page* p) { |
| } |
| +bool MarkCompactCollector::StartCompaction() { |
| + // Don't start compaction if we are in the middle of incremental |
| + // marking cycle. We did not collect any slots. |
| + if (!compacting_ && !heap_->incremental_marking()->IsMarking()) { |
| + slots_buffer_.Clear(); |
| + evacuation_candidates_.Rewind(0); |
| + |
| + CollectEvacuationCandidates(heap()->old_pointer_space()); |
| + CollectEvacuationCandidates(heap()->old_data_space()); |
| + |
| + heap()->old_pointer_space()->EvictEvacuationCandidatesFromFreeLists(); |
| + heap()->old_data_space()->EvictEvacuationCandidatesFromFreeLists(); |
| + |
| + compacting_ = evacuation_candidates_.length() > 0; |
| + } |
| + |
| + return compacting_; |
| +} |
| + |
| + |
| void MarkCompactCollector::CollectGarbage() { |
| // Make sure that Prepare() has been called. The individual steps below will |
| // update the state as they proceed. |
| @@ -370,6 +391,7 @@ void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { |
| } |
| +#if 0 |
| static void ClearEvacuationCandidates(PagedSpace* space) { |
|
Erik Corry
2011/07/04 11:04:11
Commented code
Vyacheslav Egorov (Chromium)
2011/08/05 12:50:28
Done.
|
| ASSERT(space->identity() == OLD_POINTER_SPACE || |
| space->identity() == OLD_DATA_SPACE); |
| @@ -380,6 +402,7 @@ static void ClearEvacuationCandidates(PagedSpace* space) { |
| p->ClearEvacuationCandidate(); |
| } |
| } |
| +#endif |
| void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| @@ -410,18 +433,7 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| } |
| #endif |
| - if (!FLAG_never_compact) { |
| - slots_buffer_.Clear(); |
| - evacuation_candidates_.Rewind(0); |
| - |
| - if (!heap()->incremental_marking()->IsMarking()) { |
| - CollectEvacuationCandidates(heap()->old_pointer_space()); |
| - CollectEvacuationCandidates(heap()->old_data_space()); |
| - } else { |
| - ClearEvacuationCandidates(heap()->old_pointer_space()); |
| - ClearEvacuationCandidates(heap()->old_data_space()); |
| - } |
| - } |
| + if (!FLAG_never_compact) StartCompaction(); |
| PagedSpaces spaces; |
| for (PagedSpace* space = spaces.next(); |
| @@ -2314,6 +2326,21 @@ void MarkCompactCollector::EvacuatePages() { |
| } |
| +class EvacuationWeakObjectRetainer : public WeakObjectRetainer { |
| + public: |
| + virtual Object* RetainAs(Object* object) { |
| + if (object->IsHeapObject()) { |
| + HeapObject* heap_object = HeapObject::cast(object); |
| + MapWord map_word = heap_object->map_word(); |
| + if (map_word.IsForwardingAddress()) { |
| + return map_word.ToForwardingAddress(); |
| + } |
| + } |
| + return object; |
| + } |
| +}; |
| + |
| + |
| void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| EvacuateNewSpace(); |
| EvacuatePages(); |
| @@ -2343,7 +2370,7 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| &Heap::ScavengeStoreBufferCallback); |
| heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); |
| } |
| - slots_buffer_.Iterate(&updating_visitor); |
| + slots_buffer_.Update(); |
| // Update pointers from cells. |
| HeapObjectIterator cell_iterator(heap_->cell_space()); |
| @@ -2370,6 +2397,9 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| // Update JSFunction pointers from the runtime profiler. |
| heap_->isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
| + EvacuationWeakObjectRetainer evacuation_object_retainer; |
| + heap()->ProcessWeakReferences(&evacuation_object_retainer); |
| + |
| #ifdef DEBUG |
| if (FLAG_verify_heap) { |
| VerifyEvacuation(heap_); |
| @@ -2377,16 +2407,17 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| #endif |
| int npages = evacuation_candidates_.length(); |
| + ASSERT(compacting_ == (npages > 0)); |
| for (int i = 0; i < npages; i++) { |
| Page* p = evacuation_candidates_[i]; |
| PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| space->Free(p->ObjectAreaStart(), Page::kObjectAreaSize); |
| p->set_scan_on_scavenge(false); |
| - |
| - // We are not clearing evacuation candidate flag here |
| - // because it is required to notify lazy sweeper to skip |
| - // these pages. |
| + p->ClearEvacuationCandidate(); |
| + p->SetFlag(MemoryChunk::EVACUATED); |
| + p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| } |
| + compacting_ = false; |
| } |
| @@ -3058,19 +3089,34 @@ void SlotsBuffer::Add(Object** slot) { |
| } |
| -void SlotsBuffer::Iterate(ObjectVisitor* visitor) { |
| +static inline void UpdateSlot(Object** slot) { |
| + Object* obj = *slot; |
| + if (!obj->IsHeapObject()) return; |
| + |
| + HeapObject* heap_obj = HeapObject::cast(obj); |
| + |
| + MapWord map_word = heap_obj->map_word(); |
| + if (map_word.IsForwardingAddress()) { |
| + ASSERT(MarkCompactCollector::IsOnEvacuationCandidate(*slot)); |
| + *slot = map_word.ToForwardingAddress(); |
| + ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(*slot)); |
| + } |
| +} |
| + |
| + |
| +void SlotsBuffer::Update() { |
| if (buffer_idx_ < 0) return; |
| for (int buffer_index = 0; buffer_index < buffer_idx_; ++buffer_index) { |
| ObjectSlot* buffer = buffers_[buffer_index]; |
| for (int slot_idx = 0; slot_idx < kBufferSize; ++slot_idx) { |
| - visitor->VisitPointer(buffer[slot_idx]); |
| + UpdateSlot(buffer[slot_idx]); |
| } |
| } |
| ObjectSlot* last_buffer = buffers_[buffer_idx_]; |
| for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { |
| - visitor->VisitPointer(last_buffer[slot_idx]); |
| + UpdateSlot(last_buffer[slot_idx]); |
| } |
| } |