Commit 8951a9cd authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

[heap] Scavenger: Introduce list of copied objects

Bug: 
Change-Id: I6953e494632684b9e2bc9a1bf7f7801eea25cdcb
Reviewed-on: https://chromium-review.googlesource.com/563212
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46479}
parent 01148639
...@@ -1723,31 +1723,13 @@ void Heap::Scavenge() { ...@@ -1723,31 +1723,13 @@ void Heap::Scavenge() {
new_space_->Flip(); new_space_->Flip();
new_space_->ResetAllocationInfo(); new_space_->ResetAllocationInfo();
// We need to sweep newly copied objects which can be either in the
// to space or promoted to the old generation. For to-space
// objects, we treat the bottom of the to space as a queue. Newly
// copied and unswept objects lie between a 'front' mark and the
// allocation pointer.
//
// Promoted objects can go into various old-generation spaces, and
// can be allocated internally in the spaces (from the free list).
// We treat the top of the to space as a queue of addresses of
// promoted objects. The addresses of newly promoted and unswept
// objects lie between a 'front' mark and a 'rear' mark that is
// updated as a side effect of promoting an object.
//
// There is guaranteed to be enough room at the top of the to space
// for the addresses of promoted objects: every object promoted
// frees up its size in bytes from the top of the new space, and
// objects are at least one pointer in size.
Address new_space_front = new_space_->ToSpaceStart();
const int kScavengerTasks = 1; const int kScavengerTasks = 1;
const int kMainThreadId = 0; const int kMainThreadId = 0;
CopiedList copied_list(kScavengerTasks);
PromotionList promotion_list(kScavengerTasks); PromotionList promotion_list(kScavengerTasks);
Scavenger scavenger(this, IsLogging(isolate()), Scavenger scavenger(this, IsLogging(isolate()),
incremental_marking()->IsMarking(), &promotion_list, incremental_marking()->IsMarking(), &copied_list,
kMainThreadId); &promotion_list, kMainThreadId);
RootScavengeVisitor root_scavenge_visitor(this, &scavenger); RootScavengeVisitor root_scavenge_visitor(this, &scavenger);
isolate()->global_handles()->IdentifyWeakUnmodifiedObjects( isolate()->global_handles()->IdentifyWeakUnmodifiedObjects(
...@@ -1788,7 +1770,7 @@ void Heap::Scavenge() { ...@@ -1788,7 +1770,7 @@ void Heap::Scavenge() {
{ {
TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SEMISPACE); TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SEMISPACE);
new_space_front = DoScavenge(&scavenger, new_space_front); DoScavenge(&scavenger);
} }
isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending( isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending(
...@@ -1796,7 +1778,7 @@ void Heap::Scavenge() { ...@@ -1796,7 +1778,7 @@ void Heap::Scavenge() {
isolate()->global_handles()->IterateNewSpaceWeakUnmodifiedRoots( isolate()->global_handles()->IterateNewSpaceWeakUnmodifiedRoots(
&root_scavenge_visitor); &root_scavenge_visitor);
new_space_front = DoScavenge(&scavenger, new_space_front); DoScavenge(&scavenger);
UpdateNewSpaceReferencesInExternalStringTable( UpdateNewSpaceReferencesInExternalStringTable(
&UpdateNewSpaceReferenceInExternalStringTableEntry); &UpdateNewSpaceReferenceInExternalStringTableEntry);
...@@ -1806,8 +1788,6 @@ void Heap::Scavenge() { ...@@ -1806,8 +1788,6 @@ void Heap::Scavenge() {
ScavengeWeakObjectRetainer weak_object_retainer(this); ScavengeWeakObjectRetainer weak_object_retainer(this);
ProcessYoungWeakReferences(&weak_object_retainer); ProcessYoungWeakReferences(&weak_object_retainer);
DCHECK(new_space_front == new_space_->top());
// Set age mark. // Set age mark.
new_space_->set_age_mark(new_space_->top()); new_space_->set_age_mark(new_space_->top());
...@@ -2002,43 +1982,38 @@ void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { ...@@ -2002,43 +1982,38 @@ void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
external_string_table_.IterateAll(&external_string_table_visitor); external_string_table_.IterateAll(&external_string_table_visitor);
} }
Address Heap::DoScavenge(Scavenger* scavenger, Address new_space_front) { void Heap::DoScavenge(Scavenger* scavenger) {
// Threshold when to switch processing the promotion list to avoid allocating // Threshold when to switch processing the promotion list to avoid
// too much backing store in the worklist. // allocating too much backing store in the worklist.
const int kProcessPromotionListThreshold = kPromotionListSegmentSize / 2; const int kProcessPromotionListThreshold = kPromotionListSegmentSize / 2;
ScavengeVisitor scavenge_visitor(this, scavenger); ScavengeVisitor scavenge_visitor(this, scavenger);
PromotionList::View* promotion_list = scavenger->promotion_list(); PromotionList::View* promotion_list = scavenger->promotion_list();
CopiedRangesList* copied_list = scavenger->copied_list();
bool done;
do { do {
SemiSpace::AssertValidRange(new_space_front, new_space_->top()); done = true;
// The addresses new_space_front and new_space_.top() define a AddressRange range;
// queue of unprocessed copied objects. Process them until the
// queue is empty.
while ((promotion_list->LocalPushSegmentSize() < while ((promotion_list->LocalPushSegmentSize() <
kProcessPromotionListThreshold) && kProcessPromotionListThreshold) &&
new_space_front != new_space_->top()) { copied_list->Pop(&range)) {
if (!Page::IsAlignedToPageSize(new_space_front)) { for (Address current = range.first; current < range.second;) {
HeapObject* object = HeapObject::FromAddress(new_space_front); HeapObject* object = HeapObject::FromAddress(current);
new_space_front += scavenge_visitor.Visit(object); int size = object->Size();
} else { scavenge_visitor.Visit(object);
new_space_front = Page::FromAllocationAreaAddress(new_space_front) current += size;
->next_page()
->area_start();
} }
done = false;
} }
ObjectAndSize object_and_size; ObjectAndSize object_and_size;
while (promotion_list->Pop(&object_and_size)) { while (promotion_list->Pop(&object_and_size)) {
HeapObject* target = object_and_size.first; HeapObject* target = object_and_size.first;
int size = object_and_size.second; int size = object_and_size.second;
DCHECK(!target->IsMap()); DCHECK(!target->IsMap());
IterateAndScavengePromotedObject(scavenger, target, size); IterateAndScavengePromotedObject(scavenger, target, size);
done = false;
} }
} while (!done);
// Take another spin if there are now unswept objects in new space
// (there are currently no more unswept promoted objects).
} while (new_space_front != new_space_->top());
return new_space_front;
} }
......
...@@ -1783,7 +1783,7 @@ class Heap { ...@@ -1783,7 +1783,7 @@ class Heap {
void Scavenge(); void Scavenge();
void EvacuateYoungGeneration(); void EvacuateYoungGeneration();
Address DoScavenge(Scavenger* scavenger, Address new_space_front); void DoScavenge(Scavenger* scavenger);
void UpdateNewSpaceReferencesInExternalStringTable( void UpdateNewSpaceReferencesInExternalStringTable(
ExternalStringTableUpdaterCallback updater_func); ExternalStringTableUpdaterCallback updater_func);
......
...@@ -78,6 +78,7 @@ bool Scavenger::SemiSpaceCopyObject(Map* map, HeapObject** slot, ...@@ -78,6 +78,7 @@ bool Scavenger::SemiSpaceCopyObject(Map* map, HeapObject** slot,
// Update slot to new target. // Update slot to new target.
*slot = target; *slot = target;
copied_list()->Insert(target, object_size);
heap()->IncrementSemiSpaceCopiedObjectSize(object_size); heap()->IncrementSemiSpaceCopiedObjectSize(object_size);
return true; return true;
} }
......
...@@ -12,17 +12,67 @@ ...@@ -12,17 +12,67 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
static const int kCopiedListSegmentSize = 64;
static const int kPromotionListSegmentSize = 64; static const int kPromotionListSegmentSize = 64;
using AddressRange = std::pair<Address, Address>;
using CopiedList = Worklist<AddressRange, kCopiedListSegmentSize>;
using ObjectAndSize = std::pair<HeapObject*, int>; using ObjectAndSize = std::pair<HeapObject*, int>;
using PromotionList = Worklist<ObjectAndSize, kPromotionListSegmentSize>; using PromotionList = Worklist<ObjectAndSize, kPromotionListSegmentSize>;
// A list of copied ranges. Keeps the last consecutive range local and announces
// all other ranges to a global work list.
class CopiedRangesList {
public:
CopiedRangesList(CopiedList* copied_list, int task_id)
: current_start_(nullptr),
current_end_(nullptr),
copied_list_(copied_list, task_id) {}
~CopiedRangesList() {
CHECK_NULL(current_start_);
CHECK_NULL(current_end_);
}
void Insert(HeapObject* object, int size) {
const Address object_address = object->address();
if (current_end_ != object_address) {
if (current_start_ != nullptr) {
copied_list_.Push(AddressRange(current_start_, current_end_));
}
current_start_ = object_address;
current_end_ = current_start_ + size;
return;
}
DCHECK_EQ(current_end_, object_address);
current_end_ += size;
return;
}
bool Pop(AddressRange* entry) {
if (copied_list_.Pop(entry)) {
return true;
} else if (current_start_ != nullptr) {
*entry = AddressRange(current_start_, current_end_);
current_start_ = current_end_ = nullptr;
return true;
}
return false;
}
private:
Address current_start_;
Address current_end_;
CopiedList::View copied_list_;
};
class Scavenger { class Scavenger {
public: public:
Scavenger(Heap* heap, bool is_logging, bool is_incremental_marking, Scavenger(Heap* heap, bool is_logging, bool is_incremental_marking,
PromotionList* promotion_list, int task_id) CopiedList* copied_list, PromotionList* promotion_list, int task_id)
: heap_(heap), : heap_(heap),
promotion_list_(promotion_list, task_id), promotion_list_(promotion_list, task_id),
copied_list_(copied_list, task_id),
is_logging_(is_logging), is_logging_(is_logging),
is_incremental_marking_(is_incremental_marking) {} is_incremental_marking_(is_incremental_marking) {}
...@@ -36,6 +86,7 @@ class Scavenger { ...@@ -36,6 +86,7 @@ class Scavenger {
Address slot_address); Address slot_address);
inline Heap* heap() { return heap_; } inline Heap* heap() { return heap_; }
inline PromotionList::View* promotion_list() { return &promotion_list_; } inline PromotionList::View* promotion_list() { return &promotion_list_; }
inline CopiedRangesList* copied_list() { return &copied_list_; }
private: private:
V8_INLINE HeapObject* MigrateObject(HeapObject* source, HeapObject* target, V8_INLINE HeapObject* MigrateObject(HeapObject* source, HeapObject* target,
...@@ -68,6 +119,7 @@ class Scavenger { ...@@ -68,6 +119,7 @@ class Scavenger {
Heap* const heap_; Heap* const heap_;
PromotionList::View promotion_list_; PromotionList::View promotion_list_;
CopiedRangesList copied_list_;
bool is_logging_; bool is_logging_;
bool is_incremental_marking_; bool is_incremental_marking_;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment