Index: src/spaces.cc |
diff --git a/src/spaces.cc b/src/spaces.cc |
index 44008b02c46c64e0ab5b19ed58bdb6a9667f7050..4c6c0b10519688587880251ddc3e9f638a636ea5 100644 |
--- a/src/spaces.cc |
+++ b/src/spaces.cc |
@@ -754,6 +754,21 @@ int PagedSpace::CountTotalPages() { |
void PagedSpace::ReleasePage(Page* page) { |
ASSERT(page->LiveBytes() == 0); |
+ |
+ // Adjust list of unswept pages if the page is it's head or tail. |
Michael Starzinger
2011/11/10 12:35:40
This block assumes that last_unswept_page_ is eith
|
+ if (first_unswept_page_ == page) { |
+ first_unswept_page_ = page->next_page(); |
+ if (first_unswept_page_ == last_unswept_page_) { |
+ first_unswept_page_ = last_unswept_page_ = Page::FromAddress(NULL); |
+ } |
+ } |
+ |
+ if (page->WasSwept()) { |
+ intptr_t size = free_list_.EvictFreeListItems(page); |
+ accounting_stats_.AllocateBytes(size); |
+ ASSERT_EQ(Page::kObjectAreaSize, static_cast<int>(size)); |
+ } |
+ |
page->Unlink(); |
if (page->IsFlagSet(MemoryChunk::CONTAINS_ONLY_DATA)) { |
heap()->isolate()->memory_allocator()->Free(page); |
@@ -771,8 +786,18 @@ void PagedSpace::ReleaseAllUnusedPages() { |
PageIterator it(this); |
while (it.has_next()) { |
Page* page = it.next(); |
- if (page->LiveBytes() == 0) { |
- ReleasePage(page); |
+ if (!page->WasSwept()) { |
+ if (page->LiveBytes() == 0) ReleasePage(page); |
+ } else { |
+ HeapObject* obj = HeapObject::FromAddress(page->body()); |
+ if (obj->IsFreeSpace() && |
+ FreeSpace::cast(obj)->size() == Page::kObjectAreaSize) { |
+ FreeList::SizeStats sizes; |
+ free_list_.CountFreeListItems(page, &sizes); |
+ if (sizes.Total() == Page::kObjectAreaSize) { |
Michael Starzinger
2011/11/10 12:35:40
Currently the free-list count at this point should
|
+ ReleasePage(page); |
+ } |
+ } |
} |
} |
heap()->FreeQueuedChunks(); |
@@ -1870,13 +1895,50 @@ static intptr_t CountFreeListItemsInList(FreeListNode* n, Page* p) { |
} |
-void FreeList::CountFreeListItems(Page* p, intptr_t* sizes) { |
- sizes[0] = CountFreeListItemsInList(small_list_, p); |
- sizes[1] = CountFreeListItemsInList(medium_list_, p); |
- sizes[2] = CountFreeListItemsInList(large_list_, p); |
- sizes[3] = CountFreeListItemsInList(huge_list_, p); |
+void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) { |
+ sizes->huge_size_ = CountFreeListItemsInList(huge_list_, p); |
+ if (sizes->huge_size_ < Page::kObjectAreaSize) { |
+ sizes->small_size_ = CountFreeListItemsInList(small_list_, p); |
+ sizes->medium_size_ = CountFreeListItemsInList(medium_list_, p); |
+ sizes->large_size_ = CountFreeListItemsInList(large_list_, p); |
+ } else { |
+ sizes->small_size_ = 0; |
+ sizes->medium_size_ = 0; |
+ sizes->large_size_ = 0; |
+ } |
} |
+ |
+static intptr_t EvictFreeListItemsInList(FreeListNode** n, Page* p) { |
+ intptr_t sum = 0; |
+ while (*n != NULL) { |
+ if (Page::FromAddress((*n)->address()) == p) { |
+ FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); |
+ sum += free_space->Size(); |
+ *n = (*n)->next(); |
+ } else { |
+ n = (*n)->next_address(); |
+ } |
+ } |
+ return sum; |
+} |
+ |
+ |
+intptr_t FreeList::EvictFreeListItems(Page* p) { |
+ intptr_t sum = EvictFreeListItemsInList(&huge_list_, p); |
+ |
+ if (sum < Page::kObjectAreaSize) { |
+ sum += EvictFreeListItemsInList(&small_list_, p) + |
+ EvictFreeListItemsInList(&medium_list_, p) + |
+ EvictFreeListItemsInList(&large_list_, p); |
+ } |
+ |
+ available_ -= sum; |
+ |
+ return sum; |
+} |
+ |
+ |
#ifdef DEBUG |
intptr_t FreeList::SumFreeList(FreeListNode* cur) { |
intptr_t sum = 0; |