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

Unified Diff: src/spaces.cc

Issue 7302003: Support slots recording for compaction during incremental marking. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: fix presubmit, remove last debug check 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
« no previous file with comments | « src/spaces.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/spaces.cc
diff --git a/src/spaces.cc b/src/spaces.cc
index f7c67129c8169931cf033a5ca4a20891be42efe0..79ba6307153d459f90cf9835b020cbb053090006 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -1617,7 +1617,6 @@ void FreeListNode::set_size(Heap* heap, int size_in_bytes) {
// If the block is too small (eg, one or two words), to hold both a size
// field and a next pointer, we give it a filler map that gives it the
// correct size.
- // TODO(gc) ISOLATES MERGE cleanup HEAP macro usage
if (size_in_bytes > FreeSpace::kHeaderSize) {
set_map(heap->raw_unchecked_free_space_map());
// Can't use FreeSpace::cast because it fails during deserialization.
@@ -1738,6 +1737,75 @@ int FreeList::Free(Address start, int size_in_bytes) {
}
+FreeListNode* FreeList::PickNodeFromList(FreeListNode** list, int* node_size) {
+ FreeListNode* node = *list;
+
+ if (node == NULL) return NULL;
+
+ while (node != NULL &&
+ Page::FromAddress(node->address())->IsEvacuationCandidate()) {
+ available_ -= node->Size();
+ node = node->next();
+ }
+
+ if (node != NULL) {
+ *node_size = node->Size();
+ *list = node->next();
+ } else {
+ *list = NULL;
+ }
+
+ return node;
+}
+
+
+FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
+ FreeListNode* node = NULL;
+
+ if (size_in_bytes <= kSmallAllocationMax) {
+ node = PickNodeFromList(&small_list_, node_size);
+ if (node != NULL) return node;
+ }
+
+ if (size_in_bytes <= kMediumAllocationMax) {
+ node = PickNodeFromList(&medium_list_, node_size);
+ if (node != NULL) return node;
+ }
+
+ if (size_in_bytes <= kLargeAllocationMax) {
+ node = PickNodeFromList(&large_list_, node_size);
+ if (node != NULL) return node;
+ }
+
+ for (FreeListNode** cur = &huge_list_;
+ *cur != NULL;
+ cur = (*cur)->next_address()) {
+ FreeListNode* cur_node = *cur;
+ while (cur_node != NULL &&
+ Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) {
+ available_ -= reinterpret_cast<FreeSpace*>(cur_node)->Size();
+ cur_node = cur_node->next();
+ }
+
+ *cur = cur_node;
+ if (cur_node == NULL) break;
+
+ ASSERT((*cur)->map() == HEAP->raw_unchecked_free_space_map());
+ FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur);
+ int size = cur_as_free_space->Size();
+ if (size >= size_in_bytes) {
+ // Large enough node found. Unlink it from the list.
+ node = *cur;
+ *node_size = size;
+ *cur = node->next();
+ break;
+ }
+ }
+
+ return node;
+}
+
+
// Allocation on the old space free list. If it succeeds then a new linear
// allocation space has been set up with the top and limit of the space. If
// the allocation fails then NULL is returned, and the caller can perform a GC
@@ -1749,51 +1817,23 @@ HeapObject* FreeList::Allocate(int size_in_bytes) {
// Don't free list allocate if there is linear space available.
ASSERT(owner_->limit() - owner_->top() < size_in_bytes);
- FreeListNode* new_node = NULL;
int new_node_size = 0;
-
- if (size_in_bytes <= kSmallAllocationMax && small_list_ != NULL) {
- new_node = small_list_;
- new_node_size = new_node->Size();
- small_list_ = new_node->next();
- } else if (size_in_bytes <= kMediumAllocationMax && medium_list_ != NULL) {
- new_node = medium_list_;
- new_node_size = new_node->Size();
- medium_list_ = new_node->next();
- } else if (size_in_bytes <= kLargeAllocationMax && large_list_ != NULL) {
- new_node = large_list_;
- new_node_size = new_node->Size();
- large_list_ = new_node->next();
- } else {
- for (FreeListNode** cur = &huge_list_;
- *cur != NULL;
- cur = (*cur)->next_address()) {
- ASSERT((*cur)->map() == HEAP->raw_unchecked_free_space_map());
- FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur);
- int size = cur_as_free_space->Size();
- if (size >= size_in_bytes) {
- // Large enough node found. Unlink it from the list.
- new_node = *cur;
- new_node_size = size;
- *cur = new_node->next();
- break;
- }
- }
- if (new_node == NULL) return NULL;
- }
+ FreeListNode* new_node = FindNodeFor(size_in_bytes, &new_node_size);
+ if (new_node == NULL) return NULL;
available_ -= new_node_size;
ASSERT(IsVeryLong() || available_ == SumFreeLists());
+ int bytes_left = new_node_size - size_in_bytes;
+ ASSERT(bytes_left >= 0);
+
int old_linear_size = owner_->limit() - owner_->top();
+
// Mark the old linear allocation area with a free space map so it can be
// skipped when scanning the heap. This also puts it back in the free list
// if it is big enough.
owner_->Free(owner_->top(), old_linear_size);
- // TODO(gc) ISOLATES MERGE
- HEAP->incremental_marking()->Step(size_in_bytes - old_linear_size);
-
- ASSERT(new_node_size - size_in_bytes >= 0); // New linear size.
+ owner_->heap()->incremental_marking()->Step(size_in_bytes - old_linear_size);
const int kThreshold = IncrementalMarking::kAllocatedThreshold;
@@ -1801,8 +1841,8 @@ HeapObject* FreeList::Allocate(int size_in_bytes) {
// a little of this again immediately - see below.
owner_->Allocate(new_node_size);
- if (new_node_size - size_in_bytes > kThreshold &&
- HEAP->incremental_marking()->IsMarkingIncomplete() &&
+ if (bytes_left > kThreshold &&
+ owner_->heap()->incremental_marking()->IsMarkingIncomplete() &&
FLAG_incremental_marking_steps) {
int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold);
// We don't want to give too large linear areas to the allocator while
@@ -1812,11 +1852,15 @@ HeapObject* FreeList::Allocate(int size_in_bytes) {
new_node_size - size_in_bytes - linear_size);
owner_->SetTop(new_node->address() + size_in_bytes,
new_node->address() + size_in_bytes + linear_size);
- } else {
+ } else if (bytes_left > 0) {
// Normally we give the rest of the node to the allocator as its new
// linear allocation area.
owner_->SetTop(new_node->address() + size_in_bytes,
new_node->address() + new_node_size);
+ } else {
+ // TODO(gc) Try not freeing linear allocation region when bytes_left
+ // are zero.
+ owner_->SetTop(NULL, NULL);
}
return new_node;
@@ -1895,18 +1939,6 @@ intptr_t FreeList::SumFreeLists() {
// -----------------------------------------------------------------------------
// OldSpace implementation
-void OldSpace::PrepareForMarkCompact() {
- // Call prepare of the super class.
- PagedSpace::PrepareForMarkCompact();
-
- // Stop lazy sweeping for this space.
- first_unswept_page_ = last_unswept_page_ = Page::FromAddress(NULL);
-
- // Clear the free list before a full GC---it will be rebuilt afterward.
- free_list_.Reset();
-}
-
-
bool NewSpace::ReserveSpace(int bytes) {
// We can't reliably unpack a partial snapshot that needs more new space
// space than the minimum NewSpace size.
@@ -1925,6 +1957,19 @@ void PagedSpace::PrepareForMarkCompact() {
int old_linear_size = limit() - top();
Free(top(), old_linear_size);
SetTop(NULL, NULL);
+
+ // Stop lazy sweeping for the space.
+ first_unswept_page_ = last_unswept_page_ = Page::FromAddress(NULL);
+
+ // Clear the free list before a full GC---it will be rebuilt afterward.
+ free_list_.Reset();
+
+ // Clear EVACUATED flag from all pages.
+ PageIterator it(this);
+ while (it.has_next()) {
+ Page* page = it.next();
+ page->ClearFlag(MemoryChunk::EVACUATED);
+ }
}
@@ -1966,7 +2011,10 @@ bool PagedSpace::AdvanceSweeper(intptr_t bytes_to_sweep) {
Page* p = first_unswept_page_;
do {
Page* next_page = p->next_page();
- freed_bytes += MarkCompactCollector::SweepConservatively(this, p);
+ // Evacuation candidates were swept by evacuator.
+ if (!p->IsEvacuationCandidate() && !p->WasEvacuated()) {
+ freed_bytes += MarkCompactCollector::SweepConservatively(this, p);
+ }
p = next_page;
} while (p != last && freed_bytes < bytes_to_sweep);
@@ -1984,6 +2032,16 @@ bool PagedSpace::AdvanceSweeper(intptr_t bytes_to_sweep) {
}
+void PagedSpace::EvictEvacuationCandidatesFromFreeLists() {
+ if (allocation_info_.top >= allocation_info_.limit) return;
+
+ if (Page::FromAddress(allocation_info_.top)->IsEvacuationCandidate()) {
+ allocation_info_.top = NULL;
+ allocation_info_.limit = NULL;
+ }
+}
+
+
HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) {
// Allocation in this space has failed.
« no previous file with comments | « src/spaces.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698