Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(779)

Unified Diff: src/mark-compact.cc

Issue 7326012: Split single slots buffer into per page slots buffers. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/mark-compact.h ('K') | « src/mark-compact.h ('k') | src/spaces.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mark-compact.cc
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index c85d38b2e057b3cbee820dafc61227c76ed27f70..b404756c064baa484565439e6eeb0c6f5991a0bc 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -60,6 +60,7 @@ MarkCompactCollector::MarkCompactCollector() : // NOLINT
sweep_precisely_(false),
compacting_(false),
tracer_(NULL),
+ migration_slots_buffer_(NULL),
#ifdef DEBUG
live_young_objects_size_(0),
live_old_pointer_objects_size_(0),
@@ -232,9 +233,6 @@ bool MarkCompactCollector::StartCompaction() {
if (!compacting_ && !heap_->incremental_marking()->IsMarking()) {
ASSERT(evacuation_candidates_.length() == 0);
- // TODO(gc) Shrink slots buffer when we receive low memory notification.
- slots_buffer_.Clear();
-
CollectEvacuationCandidates(heap()->old_pointer_space());
CollectEvacuationCandidates(heap()->old_data_space());
@@ -384,6 +382,7 @@ void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) {
space->identity() == OLD_DATA_SPACE);
PageIterator it(space);
+ if (it.has_next()) it.next(); // Never compact the first page.
while (it.has_next()) {
Page* p = it.next();
if (space->IsFragmented(p)) {
@@ -2063,7 +2062,10 @@ void MarkCompactCollector::MigrateObject(Address dst,
heap_->store_buffer()->Mark(dst_slot);
} else if (value->IsHeapObject() &&
MarkCompactCollector::IsOnEvacuationCandidate(value)) {
- slots_buffer_.Add(reinterpret_cast<Object**>(dst_slot));
+ SlotsBuffer::AddTo(&slots_buffer_allocator_,
+ &migration_slots_buffer_,
+ reinterpret_cast<Object**>(dst_slot),
+ SlotsBuffer::IGNORE_OVERFLOW);
}
src_slot += kPointerSize;
@@ -2268,7 +2270,7 @@ void MarkCompactCollector::EvacuateNewSpace() {
void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) {
AlwaysAllocateScope always_allocate;
- ASSERT(p->IsEvacuationCandidate() && !p->WasEvacuated());
+ ASSERT(p->IsEvacuationCandidate() && !p->WasSwept());
PagedSpace* space = static_cast<PagedSpace*>(p->owner());
@@ -2317,7 +2319,11 @@ void MarkCompactCollector::EvacuatePages() {
int npages = evacuation_candidates_.length();
for (int i = 0; i < npages; i++) {
Page* p = evacuation_candidates_[i];
- EvacuateLiveObjectsFromPage(p);
+ ASSERT(p->IsEvacuationCandidate() ||
+ p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
+ if (p->IsEvacuationCandidate()) {
+ EvacuateLiveObjectsFromPage(p);
+ }
}
}
@@ -2337,6 +2343,86 @@ class EvacuationWeakObjectRetainer : public WeakObjectRetainer {
};
+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));
+ }
+}
+
+
+static inline void UpdateSlotsInRange(Object** start, Object** end) {
+ for (Object** slot = start;
+ slot < end;
+ slot++) {
+ Object* obj = *slot;
+ if (obj->IsHeapObject() &&
+ MarkCompactCollector::IsOnEvacuationCandidate(obj)) {
+ MapWord map_word = HeapObject::cast(obj)->map_word();
+ if (map_word.IsForwardingAddress()) {
+ *slot = map_word.ToForwardingAddress();
+ ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(*slot));
+ }
+ }
+ }
+}
+
+
+static void UpdateSlotsOnPage(Page* p, ObjectVisitor* visitor) {
+ // TODO(gc) this is basically clone of SweepPrecisely
+ PagedSpace* space = static_cast<PagedSpace*>(p->owner());
+ MarkBit::CellType* cells = p->markbits()->cells();
+
+ p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY);
+ p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION);
+ p->MarkSwept();
+
+ int last_cell_index =
+ Bitmap::IndexToCell(
+ Bitmap::CellAlignIndex(
+ p->AddressToMarkbitIndex(p->ObjectAreaEnd())));
+
+ int cell_index = Page::kFirstUsedCell;
+ Address free_start = p->ObjectAreaStart();
+ ASSERT(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0);
+ Address object_address = p->ObjectAreaStart();
+ int offsets[16];
+
+ for (cell_index = Page::kFirstUsedCell;
+ cell_index < last_cell_index;
+ cell_index++, object_address += 32 * kPointerSize) {
+ ASSERT((unsigned)cell_index ==
+ Bitmap::IndexToCell(
+ Bitmap::CellAlignIndex(
+ p->AddressToMarkbitIndex(object_address))));
+ int live_objects = MarkWordToObjectStarts(cells[cell_index], offsets);
+ int live_index = 0;
+ for ( ; live_objects != 0; live_objects--) {
+ Address free_end = object_address + offsets[live_index++] * kPointerSize;
+ if (free_end != free_start) {
+ space->Free(free_start, free_end - free_start);
+ }
+ HeapObject* live_object = HeapObject::FromAddress(free_end);
+ ASSERT(Marking::IsBlack(Marking::MarkBitFrom(live_object)));
+ int size = live_object->Size();
+ UpdateSlotsInRange(HeapObject::RawField(live_object, kPointerSize),
+ HeapObject::RawField(live_object, size));
+ free_start = free_end + size;
+ }
+ }
+ if (free_start != p->ObjectAreaEnd()) {
+ space->Free(free_start, p->ObjectAreaEnd() - free_start);
+ }
+}
+
+
void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
EvacuateNewSpace();
EvacuatePages();
@@ -2366,7 +2452,30 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
&Heap::ScavengeStoreBufferCallback);
heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer);
}
- slots_buffer_.Update();
+
+ SlotsBuffer::UpdateSlotsRecordedIn(migration_slots_buffer_);
+ if (FLAG_trace_fragmentation) {
+ PrintF(" migration slots buffer: %d\n",
+ SlotsBuffer::SizeOfChain(migration_slots_buffer_));
+ }
+
+ int npages = evacuation_candidates_.length();
+ for (int i = 0; i < npages; i++) {
+ Page* p = evacuation_candidates_[i];
+ ASSERT(p->IsEvacuationCandidate() ||
+ p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
+
+ if (p->IsEvacuationCandidate()) {
+ SlotsBuffer::UpdateSlotsRecordedIn(p->slots_buffer());
+ if (FLAG_trace_fragmentation) {
+ PrintF(" page %p slots buffer: %d\n",
+ reinterpret_cast<void*>(p),
+ SlotsBuffer::SizeOfChain(p->slots_buffer()));
+ }
+ } else {
+ UpdateSlotsOnPage(p, &updating_visitor);
+ }
+ }
// Update pointers from cells.
HeapObjectIterator cell_iterator(heap_->cell_space());
@@ -2402,16 +2511,17 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
}
#endif
- int npages = evacuation_candidates_.length();
- ASSERT(compacting_ == (npages > 0));
+ slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_);
+ ASSERT(migration_slots_buffer_ == NULL);
for (int i = 0; i < npages; i++) {
Page* p = evacuation_candidates_[i];
- ASSERT(p->IsEvacuationCandidate() && !p->WasEvacuated());
+ if (!p->IsEvacuationCandidate()) continue;
PagedSpace* space = static_cast<PagedSpace*>(p->owner());
space->Free(p->ObjectAreaStart(), Page::kObjectAreaSize);
p->set_scan_on_scavenge(false);
+ slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address());
p->ClearEvacuationCandidate();
- p->SetFlag(MemoryChunk::EVACUATED);
+ p->MarkSwept();
p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY);
}
evacuation_candidates_.Rewind(0);
@@ -2743,7 +2853,7 @@ static inline Address StartOfLiveObject(Address block_address, uint32_t cell) {
// memory that can be ignored when scanning. Dead objects other than free
// spaces will not contain the free space map.
int MarkCompactCollector::SweepConservatively(PagedSpace* space, Page* p) {
- ASSERT(!p->IsEvacuationCandidate() && !p->WasEvacuated());
+ ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept());
int freed_bytes = 0;
@@ -2831,7 +2941,7 @@ int MarkCompactCollector::SweepConservatively(PagedSpace* space, Page* p) {
// over it. Map space is swept precisely, because it is not compacted.
static void SweepPrecisely(PagedSpace* space,
Page* p) {
- ASSERT(!p->IsEvacuationCandidate() && !p->WasEvacuated());
+ ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept());
MarkBit::CellType* cells = p->markbits()->cells();
p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY);
@@ -2892,6 +3002,11 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space,
continue;
}
+ if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) {
+ // Will be processed in EvacuateNewSpaceAndCandidates.
+ continue;
+ }
+
switch (sweeper) {
case CONSERVATIVE: {
SweepConservatively(space, p);
@@ -3052,74 +3167,36 @@ void MarkCompactCollector::Initialize() {
}
-SlotsBuffer::SlotsBuffer()
- : buffers_(0),
- buffer_(NULL),
- idx_(kBufferSize),
- buffer_idx_(-1) {
-}
-
-
-SlotsBuffer::~SlotsBuffer() {
- for (int buffer_index = 0; buffer_index < buffers_.length(); ++buffer_index) {
- delete buffers_[buffer_index];
+void SlotsBuffer::UpdateSlots() {
+ ObjectSlot* slots = AsArray();
+ for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) {
+ UpdateSlot(slots[slot_idx]);
}
}
-void SlotsBuffer::Clear() {
- idx_ = kBufferSize;
- buffer_idx_ = -1;
-}
-
-
-void SlotsBuffer::Add(Object** slot) {
- if (idx_ == kBufferSize) {
- idx_ = 0;
- buffer_idx_++;
- if (buffer_idx_ == buffers_.length()) {
- buffers_.Add(new ObjectSlot[kBufferSize]);
- }
- buffer_ = buffers_[buffer_idx_];
- }
-
- buffer_[idx_++] = slot;
+SlotsBuffer* SlotsBufferAllocator::AllocateBuffer(SlotsBuffer* next_buffer) {
+ // TODO(gc) Consider maintaining local cache of buffers.
+ SlotsBuffer* buffer = reinterpret_cast<SlotsBuffer*>(
Erik Corry 2011/07/08 13:02:38 This could just be new SlotsBuffer().
+ malloc(SlotsBuffer::kSizeWords * kPointerSize));
+ buffer->Initialize(next_buffer);
+ return buffer;
}
-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 SlotsBufferAllocator::DeallocateBuffer(SlotsBuffer* buffer) {
+ free(buffer);
}
-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) {
- UpdateSlot(buffer[slot_idx]);
- }
- }
-
- ObjectSlot* last_buffer = buffers_[buffer_idx_];
- for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) {
- UpdateSlot(last_buffer[slot_idx]);
+void SlotsBufferAllocator::DeallocateChain(SlotsBuffer** buffer_address) {
+ SlotsBuffer* buffer = *buffer_address;
+ while (buffer != NULL) {
+ SlotsBuffer* next_buffer = buffer->next();
+ DeallocateBuffer(buffer);
+ buffer = next_buffer;
}
-}
-
-
-void SlotsBuffer::Report() {
+ *buffer_address = NULL;
}
« src/mark-compact.h ('K') | « src/mark-compact.h ('k') | src/spaces.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698