Index: src/heap/mark-compact.cc |
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc |
index 5c11e513fec63760f1dcf7f2382de257a1737720..e1eaba0b92cf0a92bb6ceff2bd10a5dd6decdda8 100644 |
--- a/src/heap/mark-compact.cc |
+++ b/src/heap/mark-compact.cc |
@@ -1666,7 +1666,7 @@ |
semispace_copied_size_(0), |
local_pretenuring_feedback_(local_pretenuring_feedback) {} |
- inline bool Visit(HeapObject* object) override { |
+ bool Visit(HeapObject* object) override { |
heap_->UpdateAllocationSite<Heap::kCached>(object, |
local_pretenuring_feedback_); |
int size = object->Size(); |
@@ -1798,33 +1798,6 @@ |
HashMap* local_pretenuring_feedback_; |
}; |
-class MarkCompactCollector::EvacuateNewSpacePageVisitor final |
- : public MarkCompactCollector::HeapObjectVisitor { |
- public: |
- EvacuateNewSpacePageVisitor() : promoted_size_(0) {} |
- |
- static void MoveToOldSpace(NewSpacePage* page, PagedSpace* owner) { |
- page->heap()->new_space()->ReplaceWithEmptyPage(page); |
- Page* new_page = Page::Convert(page, owner); |
- new_page->SetFlag(Page::PAGE_NEW_OLD_PROMOTION); |
- } |
- |
- inline bool Visit(HeapObject* object) { |
- if (V8_UNLIKELY(object->IsJSArrayBuffer())) { |
- object->GetHeap()->array_buffer_tracker()->Promote( |
- JSArrayBuffer::cast(object)); |
- } |
- RecordMigratedSlotVisitor visitor; |
- object->IterateBodyFast(&visitor); |
- promoted_size_ += object->Size(); |
- return true; |
- } |
- |
- intptr_t promoted_size() { return promoted_size_; } |
- |
- private: |
- intptr_t promoted_size_; |
-}; |
class MarkCompactCollector::EvacuateOldSpaceVisitor final |
: public MarkCompactCollector::EvacuateVisitorBase { |
@@ -1833,7 +1806,7 @@ |
CompactionSpaceCollection* compaction_spaces) |
: EvacuateVisitorBase(heap, compaction_spaces) {} |
- inline bool Visit(HeapObject* object) override { |
+ bool Visit(HeapObject* object) override { |
CompactionSpace* target_space = compaction_spaces_->Get( |
Page::FromAddress(object->address())->owner()->identity()); |
HeapObject* target_object = nullptr; |
@@ -3048,17 +3021,9 @@ |
newspace_evacuation_candidates_.Rewind(0); |
} |
+ |
class MarkCompactCollector::Evacuator : public Malloced { |
public: |
- // NewSpacePages with more live bytes than this threshold qualify for fast |
- // evacuation. |
- static int PageEvacuationThreshold() { |
- if (FLAG_page_promotion) |
- return FLAG_page_promotion_threshold * NewSpacePage::kAllocatableMemory / |
- 100; |
- return NewSpacePage::kAllocatableMemory + kPointerSize; |
- } |
- |
explicit Evacuator(MarkCompactCollector* collector) |
: collector_(collector), |
compaction_spaces_(collector->heap()), |
@@ -3066,7 +3031,6 @@ |
kInitialLocalPretenuringFeedbackCapacity), |
new_space_visitor_(collector->heap(), &compaction_spaces_, |
&local_pretenuring_feedback_), |
- new_space_page_visitor(), |
old_space_visitor_(collector->heap(), &compaction_spaces_), |
duration_(0.0), |
bytes_compacted_(0) {} |
@@ -3080,32 +3044,17 @@ |
CompactionSpaceCollection* compaction_spaces() { return &compaction_spaces_; } |
private: |
- enum EvacuationMode { |
- kObjectsNewToOld, |
- kPageNewToOld, |
- kObjectsOldToOld, |
- }; |
- |
static const int kInitialLocalPretenuringFeedbackCapacity = 256; |
- inline Heap* heap() { return collector_->heap(); } |
- |
- inline EvacuationMode ComputeEvacuationMode(MemoryChunk* chunk) { |
- // Note: The order of checks is important in this function. |
- if (chunk->InNewSpace()) return kObjectsNewToOld; |
- if (chunk->IsFlagSet(MemoryChunk::PAGE_NEW_OLD_PROMOTION)) |
- return kPageNewToOld; |
- DCHECK(chunk->IsEvacuationCandidate()); |
- return kObjectsOldToOld; |
- } |
+ Heap* heap() { return collector_->heap(); } |
void ReportCompactionProgress(double duration, intptr_t bytes_compacted) { |
duration_ += duration; |
bytes_compacted_ += bytes_compacted; |
} |
- template <IterationMode mode, class Visitor> |
- inline bool EvacuateSinglePage(MemoryChunk* p, Visitor* visitor); |
+ template <IterationMode mode> |
+ inline bool EvacuateSinglePage(MemoryChunk* p, HeapObjectVisitor* visitor); |
MarkCompactCollector* collector_; |
@@ -3115,7 +3064,6 @@ |
// Visitors for the corresponding spaces. |
EvacuateNewSpaceVisitor new_space_visitor_; |
- EvacuateNewSpacePageVisitor new_space_page_visitor; |
EvacuateOldSpaceVisitor old_space_visitor_; |
// Book keeping info. |
@@ -3123,18 +3071,17 @@ |
intptr_t bytes_compacted_; |
}; |
-template <MarkCompactCollector::IterationMode mode, class Visitor> |
-bool MarkCompactCollector::Evacuator::EvacuateSinglePage(MemoryChunk* p, |
- Visitor* visitor) { |
+template <MarkCompactCollector::IterationMode mode> |
+bool MarkCompactCollector::Evacuator::EvacuateSinglePage( |
+ MemoryChunk* p, HeapObjectVisitor* visitor) { |
bool success = false; |
- DCHECK(p->IsEvacuationCandidate() || p->InNewSpace() || |
- p->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION)); |
+ DCHECK(p->IsEvacuationCandidate() || p->InNewSpace()); |
int saved_live_bytes = p->LiveBytes(); |
double evacuation_time; |
{ |
AlwaysAllocateScope always_allocate(heap()->isolate()); |
TimedScope timed_scope(&evacuation_time); |
- success = collector_->VisitLiveObjects<Visitor>(p, visitor, mode); |
+ success = collector_->VisitLiveObjects(p, visitor, mode); |
} |
if (FLAG_trace_evacuation) { |
const char age_mark_tag = |
@@ -3146,9 +3093,8 @@ |
: '#'; |
PrintIsolate(heap()->isolate(), |
"evacuation[%p]: page=%p new_space=%d age_mark_tag=%c " |
- "page_evacuation=%d executable=%d live_bytes=%d time=%f\n", |
+ "executable=%d live_bytes=%d time=%f\n", |
this, p, p->InNewSpace(), age_mark_tag, |
- p->IsFlagSet(MemoryChunk::PAGE_NEW_OLD_PROMOTION), |
p->IsFlagSet(MemoryChunk::IS_EXECUTABLE), saved_live_bytes, |
evacuation_time); |
} |
@@ -3159,38 +3105,30 @@ |
} |
bool MarkCompactCollector::Evacuator::EvacuatePage(MemoryChunk* chunk) { |
- bool result = false; |
- DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), |
- NewSpacePage::kSweepingDone); |
- switch (ComputeEvacuationMode(chunk)) { |
- case kObjectsNewToOld: |
- result = EvacuateSinglePage<kClearMarkbits>(chunk, &new_space_visitor_); |
- DCHECK(result); |
- USE(result); |
- break; |
- case kPageNewToOld: |
- result = EvacuateSinglePage<kKeepMarking>(chunk, &new_space_page_visitor); |
- DCHECK(result); |
- USE(result); |
- break; |
- case kObjectsOldToOld: |
- result = EvacuateSinglePage<kClearMarkbits>(chunk, &old_space_visitor_); |
- if (!result) { |
- // Aborted compaction page. We can record slots here to have them |
- // processed in parallel later on. |
- EvacuateRecordOnlyVisitor record_visitor(chunk->owner()->identity()); |
- result = EvacuateSinglePage<kKeepMarking>(chunk, &record_visitor); |
- DCHECK(result); |
- USE(result); |
- // We need to return failure here to indicate that we want this page |
- // added to the sweeper. |
- return false; |
- } |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- return result; |
+ bool success = false; |
+ if (chunk->InNewSpace()) { |
+ DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), |
+ NewSpacePage::kSweepingDone); |
+ success = EvacuateSinglePage<kClearMarkbits>(chunk, &new_space_visitor_); |
+ DCHECK(success); |
+ USE(success); |
+ } else { |
+ DCHECK(chunk->IsEvacuationCandidate()); |
+ DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), Page::kSweepingDone); |
+ success = EvacuateSinglePage<kClearMarkbits>(chunk, &old_space_visitor_); |
+ if (!success) { |
+ // Aborted compaction page. We can record slots here to have them |
+ // processed in parallel later on. |
+ EvacuateRecordOnlyVisitor record_visitor(chunk->owner()->identity()); |
+ success = EvacuateSinglePage<kKeepMarking>(chunk, &record_visitor); |
+ DCHECK(success); |
+ USE(success); |
+ // We need to return failure here to indicate that we want this page added |
+ // to the sweeper. |
+ return false; |
+ } |
+ } |
+ return success; |
} |
void MarkCompactCollector::Evacuator::Finalize() { |
@@ -3198,14 +3136,12 @@ |
heap()->code_space()->MergeCompactionSpace( |
compaction_spaces_.Get(CODE_SPACE)); |
heap()->tracer()->AddCompactionEvent(duration_, bytes_compacted_); |
- heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size() + |
- new_space_page_visitor.promoted_size()); |
+ heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size()); |
heap()->IncrementSemiSpaceCopiedObjectSize( |
new_space_visitor_.semispace_copied_size()); |
heap()->IncrementYoungSurvivorsCounter( |
new_space_visitor_.promoted_size() + |
- new_space_visitor_.semispace_copied_size() + |
- new_space_page_visitor.promoted_size()); |
+ new_space_visitor_.semispace_copied_size()); |
heap()->MergeAllocationSitePretenuringFeedback(local_pretenuring_feedback_); |
} |
@@ -3255,14 +3191,6 @@ |
bool success, PerPageData data) { |
if (chunk->InNewSpace()) { |
DCHECK(success); |
- } else if (chunk->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION)) { |
- DCHECK(success); |
- Page* p = static_cast<Page*>(chunk); |
- p->ClearFlag(Page::PAGE_NEW_OLD_PROMOTION); |
- p->ForAllFreeListCategories( |
- [](FreeListCategory* category) { DCHECK(!category->is_linked()); }); |
- heap->mark_compact_collector()->sweeper().AddLatePage( |
- p->owner()->identity(), p); |
} else { |
Page* p = static_cast<Page*>(chunk); |
if (success) { |
@@ -3292,15 +3220,8 @@ |
live_bytes += page->LiveBytes(); |
job.AddPage(page, &abandoned_pages); |
} |
- const Address age_mark = heap()->new_space()->age_mark(); |
for (NewSpacePage* page : newspace_evacuation_candidates_) { |
live_bytes += page->LiveBytes(); |
- if (!page->NeverEvacuate() && |
- (page->LiveBytes() > Evacuator::PageEvacuationThreshold()) && |
- page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK) && |
- !page->Contains(age_mark)) { |
- EvacuateNewSpacePageVisitor::MoveToOldSpace(page, heap()->old_space()); |
- } |
job.AddPage(page, &abandoned_pages); |
} |
DCHECK_GE(job.NumberOfPages(), 1); |
@@ -3460,8 +3381,9 @@ |
} |
#endif // VERIFY_HEAP |
-template <class Visitor> |
-bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page, Visitor* visitor, |
+ |
+bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page, |
+ HeapObjectVisitor* visitor, |
IterationMode mode) { |
#ifdef VERIFY_HEAP |
VerifyAllBlackObjects(page); |
@@ -3622,8 +3544,12 @@ |
static void UpdateOldToNewSlot(HeapObject** address, HeapObject* object) { |
MapWord map_word = object->map_word(); |
- // There could still be stale pointers in large object space, map space, |
- // and old space for pages that have been promoted. |
+ // Since we only filter invalid slots in old space, the store buffer can |
+ // still contain stale pointers in large object and in map spaces. Ignore |
+ // these pointers here. |
+ DCHECK(map_word.IsForwardingAddress() || |
+ !object->GetHeap()->old_space()->Contains( |
+ reinterpret_cast<Address>(address))); |
if (map_word.IsForwardingAddress()) { |
// Update the corresponding slot. |
*address = map_word.ToForwardingAddress(); |