[heap] Record pretenuring feedback for moved pages
Record feedback for moved pages. Aligns the behavior of the copying and moving evacuator. BUG=chromium:651354 Review-Url: https://codereview.chromium.org/2494723002 Cr-Commit-Position: refs/heads/master@{#40905}
This commit is contained in:
parent
f50f19eb19
commit
5af14e2482
@ -631,7 +631,13 @@ AllocationMemento* Heap::FindAllocationMemento(HeapObject* object) {
|
||||
template <Heap::UpdateAllocationSiteMode mode>
|
||||
void Heap::UpdateAllocationSite(HeapObject* object,
|
||||
base::HashMap* pretenuring_feedback) {
|
||||
DCHECK(InFromSpace(object));
|
||||
DCHECK(InFromSpace(object) ||
|
||||
(InToSpace(object) &&
|
||||
Page::FromAddress(object->address())
|
||||
->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION)) ||
|
||||
(!InNewSpace(object) &&
|
||||
Page::FromAddress(object->address())
|
||||
->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION)));
|
||||
if (!FLAG_allocation_site_pretenuring ||
|
||||
!AllocationSite::CanTrack(object->map()->instance_type()))
|
||||
return;
|
||||
|
@ -1834,41 +1834,48 @@ class MarkCompactCollector::EvacuateNewSpaceVisitor final
|
||||
base::HashMap* local_pretenuring_feedback_;
|
||||
};
|
||||
|
||||
template <PageEvacuationMode mode>
|
||||
class MarkCompactCollector::EvacuateNewSpacePageVisitor final
|
||||
: public MarkCompactCollector::HeapObjectVisitor {
|
||||
public:
|
||||
explicit EvacuateNewSpacePageVisitor(Heap* heap)
|
||||
: heap_(heap), promoted_size_(0), semispace_copied_size_(0) {}
|
||||
explicit EvacuateNewSpacePageVisitor(
|
||||
Heap* heap, base::HashMap* local_pretenuring_feedback)
|
||||
: heap_(heap),
|
||||
moved_bytes_(0),
|
||||
local_pretenuring_feedback_(local_pretenuring_feedback) {}
|
||||
|
||||
static void MoveToOldSpace(Page* page, PagedSpace* owner) {
|
||||
page->Unlink();
|
||||
Page* new_page = Page::ConvertNewToOld(page, owner);
|
||||
new_page->SetFlag(Page::PAGE_NEW_OLD_PROMOTION);
|
||||
}
|
||||
|
||||
static void MoveToToSpace(Page* page) {
|
||||
page->heap()->new_space()->MovePageFromSpaceToSpace(page);
|
||||
page->SetFlag(Page::PAGE_NEW_NEW_PROMOTION);
|
||||
static void Move(Page* page) {
|
||||
switch (mode) {
|
||||
case NEW_TO_NEW:
|
||||
page->heap()->new_space()->MovePageFromSpaceToSpace(page);
|
||||
page->SetFlag(Page::PAGE_NEW_NEW_PROMOTION);
|
||||
break;
|
||||
case NEW_TO_OLD: {
|
||||
page->Unlink();
|
||||
Page* new_page = Page::ConvertNewToOld(page);
|
||||
new_page->SetFlag(Page::PAGE_NEW_OLD_PROMOTION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool Visit(HeapObject* object) {
|
||||
RecordMigratedSlotVisitor visitor(heap_->mark_compact_collector());
|
||||
object->IterateBodyFast(&visitor);
|
||||
promoted_size_ += object->Size();
|
||||
heap_->UpdateAllocationSite<Heap::kCached>(object,
|
||||
local_pretenuring_feedback_);
|
||||
if (mode == NEW_TO_OLD) {
|
||||
RecordMigratedSlotVisitor visitor(heap_->mark_compact_collector());
|
||||
object->IterateBodyFast(&visitor);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
intptr_t promoted_size() { return promoted_size_; }
|
||||
intptr_t semispace_copied_size() { return semispace_copied_size_; }
|
||||
|
||||
void account_semispace_copied(intptr_t copied) {
|
||||
semispace_copied_size_ += copied;
|
||||
}
|
||||
intptr_t moved_bytes() { return moved_bytes_; }
|
||||
void account_moved_bytes(intptr_t bytes) { moved_bytes_ += bytes; }
|
||||
|
||||
private:
|
||||
Heap* heap_;
|
||||
intptr_t promoted_size_;
|
||||
intptr_t semispace_copied_size_;
|
||||
intptr_t moved_bytes_;
|
||||
base::HashMap* local_pretenuring_feedback_;
|
||||
};
|
||||
|
||||
class MarkCompactCollector::EvacuateOldSpaceVisitor final
|
||||
@ -2925,7 +2932,11 @@ class MarkCompactCollector::Evacuator : public Malloced {
|
||||
local_pretenuring_feedback_(kInitialLocalPretenuringFeedbackCapacity),
|
||||
new_space_visitor_(collector->heap(), &compaction_spaces_,
|
||||
&local_pretenuring_feedback_),
|
||||
new_space_page_visitor(collector->heap()),
|
||||
new_to_new_page_visitor_(collector->heap(),
|
||||
&local_pretenuring_feedback_),
|
||||
new_to_old_page_visitor_(collector->heap(),
|
||||
&local_pretenuring_feedback_),
|
||||
|
||||
old_space_visitor_(collector->heap(), &compaction_spaces_),
|
||||
duration_(0.0),
|
||||
bytes_compacted_(0) {}
|
||||
@ -2956,7 +2967,10 @@ class MarkCompactCollector::Evacuator : public Malloced {
|
||||
|
||||
// Visitors for the corresponding spaces.
|
||||
EvacuateNewSpaceVisitor new_space_visitor_;
|
||||
EvacuateNewSpacePageVisitor new_space_page_visitor;
|
||||
EvacuateNewSpacePageVisitor<PageEvacuationMode::NEW_TO_NEW>
|
||||
new_to_new_page_visitor_;
|
||||
EvacuateNewSpacePageVisitor<PageEvacuationMode::NEW_TO_OLD>
|
||||
new_to_old_page_visitor_;
|
||||
EvacuateOldSpaceVisitor old_space_visitor_;
|
||||
|
||||
// Book keeping info.
|
||||
@ -2977,20 +2991,23 @@ bool MarkCompactCollector::Evacuator::EvacuatePage(Page* page) {
|
||||
case kObjectsNewToOld:
|
||||
success = collector_->VisitLiveObjects(page, &new_space_visitor_,
|
||||
kClearMarkbits);
|
||||
DCHECK(success);
|
||||
ArrayBufferTracker::ProcessBuffers(
|
||||
page, ArrayBufferTracker::kUpdateForwardedRemoveOthers);
|
||||
DCHECK(success);
|
||||
break;
|
||||
case kPageNewToOld:
|
||||
success = collector_->VisitLiveObjects(page, &new_space_page_visitor,
|
||||
success = collector_->VisitLiveObjects(page, &new_to_old_page_visitor_,
|
||||
kKeepMarking);
|
||||
// ArrayBufferTracker will be updated during sweeping.
|
||||
DCHECK(success);
|
||||
new_to_old_page_visitor_.account_moved_bytes(page->LiveBytes());
|
||||
// ArrayBufferTracker will be updated during sweeping.
|
||||
break;
|
||||
case kPageNewToNew:
|
||||
new_space_page_visitor.account_semispace_copied(page->LiveBytes());
|
||||
success = collector_->VisitLiveObjects(page, &new_to_new_page_visitor_,
|
||||
kKeepMarking);
|
||||
DCHECK(success);
|
||||
new_to_new_page_visitor_.account_moved_bytes(page->LiveBytes());
|
||||
// ArrayBufferTracker will be updated during sweeping.
|
||||
success = true;
|
||||
break;
|
||||
case kObjectsOldToOld:
|
||||
success = collector_->VisitLiveObjects(page, &old_space_visitor_,
|
||||
@ -3015,8 +3032,6 @@ bool MarkCompactCollector::Evacuator::EvacuatePage(Page* page) {
|
||||
page, ArrayBufferTracker::kUpdateForwardedRemoveOthers);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
ReportCompactionProgress(evacuation_time, saved_live_bytes);
|
||||
@ -3042,15 +3057,15 @@ void MarkCompactCollector::Evacuator::Finalize() {
|
||||
compaction_spaces_.Get(CODE_SPACE));
|
||||
heap()->tracer()->AddCompactionEvent(duration_, bytes_compacted_);
|
||||
heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size() +
|
||||
new_space_page_visitor.promoted_size());
|
||||
new_to_old_page_visitor_.moved_bytes());
|
||||
heap()->IncrementSemiSpaceCopiedObjectSize(
|
||||
new_space_visitor_.semispace_copied_size() +
|
||||
new_space_page_visitor.semispace_copied_size());
|
||||
new_to_new_page_visitor_.moved_bytes());
|
||||
heap()->IncrementYoungSurvivorsCounter(
|
||||
new_space_visitor_.promoted_size() +
|
||||
new_space_visitor_.semispace_copied_size() +
|
||||
new_space_page_visitor.promoted_size() +
|
||||
new_space_page_visitor.semispace_copied_size());
|
||||
new_to_old_page_visitor_.moved_bytes() +
|
||||
new_to_new_page_visitor_.moved_bytes());
|
||||
heap()->MergeAllocationSitePretenuringFeedback(local_pretenuring_feedback_);
|
||||
}
|
||||
|
||||
@ -3147,9 +3162,9 @@ void MarkCompactCollector::EvacuatePagesInParallel() {
|
||||
(page->LiveBytes() > Evacuator::PageEvacuationThreshold()) &&
|
||||
!page->Contains(age_mark)) {
|
||||
if (page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK)) {
|
||||
EvacuateNewSpacePageVisitor::MoveToOldSpace(page, heap()->old_space());
|
||||
EvacuateNewSpacePageVisitor<NEW_TO_OLD>::Move(page);
|
||||
} else {
|
||||
EvacuateNewSpacePageVisitor::MoveToToSpace(page);
|
||||
EvacuateNewSpacePageVisitor<NEW_TO_NEW>::Move(page);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,6 +329,8 @@ class LiveObjectIterator BASE_EMBEDDED {
|
||||
MarkBit::CellType current_cell_;
|
||||
};
|
||||
|
||||
enum PageEvacuationMode { NEW_TO_NEW, NEW_TO_OLD };
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Mark-Compact collector
|
||||
class MarkCompactCollector {
|
||||
@ -526,6 +528,7 @@ class MarkCompactCollector {
|
||||
Sweeper& sweeper() { return sweeper_; }
|
||||
|
||||
private:
|
||||
template <PageEvacuationMode mode>
|
||||
class EvacuateNewSpacePageVisitor;
|
||||
class EvacuateNewSpaceVisitor;
|
||||
class EvacuateOldSpaceVisitor;
|
||||
|
@ -203,14 +203,15 @@ Page* Page::Initialize(Heap* heap, MemoryChunk* chunk, Executability executable,
|
||||
return page;
|
||||
}
|
||||
|
||||
Page* Page::ConvertNewToOld(Page* old_page, PagedSpace* new_owner) {
|
||||
Page* Page::ConvertNewToOld(Page* old_page) {
|
||||
OldSpace* old_space = old_page->heap()->old_space();
|
||||
DCHECK(old_page->InNewSpace());
|
||||
old_page->set_owner(new_owner);
|
||||
old_page->set_owner(old_space);
|
||||
old_page->SetFlags(0, ~0);
|
||||
new_owner->AccountCommitted(old_page->size());
|
||||
old_space->AccountCommitted(old_page->size());
|
||||
Page* new_page = Page::Initialize<kDoNotFreeMemory>(
|
||||
old_page->heap(), old_page, NOT_EXECUTABLE, new_owner);
|
||||
new_page->InsertAfter(new_owner->anchor()->prev_page());
|
||||
old_page->heap(), old_page, NOT_EXECUTABLE, old_space);
|
||||
new_page->InsertAfter(old_space->anchor()->prev_page());
|
||||
return new_page;
|
||||
}
|
||||
|
||||
|
@ -667,7 +667,7 @@ class Page : public MemoryChunk {
|
||||
static_cast<intptr_t>(MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) |
|
||||
static_cast<intptr_t>(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING);
|
||||
|
||||
static inline Page* ConvertNewToOld(Page* old_page, PagedSpace* new_owner);
|
||||
static inline Page* ConvertNewToOld(Page* old_page);
|
||||
|
||||
// Returns the page containing a given address. The address ranges
|
||||
// from [page_addr .. page_addr + kPageSize[. This only works if the object
|
||||
|
Loading…
Reference in New Issue
Block a user