Chromium Code Reviews| Index: src/spaces.cc | 
| diff --git a/src/spaces.cc b/src/spaces.cc | 
| index f8e6a1e875f4f544fecf1b1047cd3c24c5659d7f..5bc3d5ef8fc7ddc23fbd0f24a205260ca60211dc 100644 | 
| --- a/src/spaces.cc | 
| +++ b/src/spaces.cc | 
| @@ -697,6 +697,20 @@ MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t reserve_area_size, | 
| } | 
| +void Page::ResetFreeListStatistics() { | 
| + non_available_small_blocks_ = 0; | 
| + available_in_small_free_list_ = 0; | 
| + available_in_medium_free_list_ = 0; | 
| + available_in_large_free_list_ = 0; | 
| + available_in_huge_free_list_ = 0; | 
| +} | 
| + | 
| + | 
| +Page::Page() { | 
| + ResetFreeListStatistics(); | 
| +} | 
| + | 
| + | 
| Page* MemoryAllocator::AllocatePage(intptr_t size, | 
| PagedSpace* owner, | 
| Executability executable) { | 
| @@ -1057,6 +1071,23 @@ int PagedSpace::CountTotalPages() { | 
| } | 
| +void PagedSpace::ObtainFreeListStatistics(Page* page, SizeStats* sizes) { | 
| + sizes->huge_size_ = page->available_in_huge_free_list(); | 
| + sizes->small_size_ = page->available_in_small_free_list(); | 
| + sizes->medium_size_ = page->available_in_medium_free_list(); | 
| + sizes->large_size_ = page->available_in_large_free_list(); | 
| +} | 
| + | 
| + | 
| +void PagedSpace::ResetFreeListStatistics() { | 
| + PageIterator page_iterator(this); | 
| + while (page_iterator.has_next()) { | 
| + Page* page = page_iterator.next(); | 
| + page->ResetFreeListStatistics(); | 
| + } | 
| +} | 
| + | 
| + | 
| void PagedSpace::ReleasePage(Page* page, bool unlink) { | 
| ASSERT(page->LiveBytes() == 0); | 
| ASSERT(AreaSize() == page->area_size()); | 
| @@ -2056,20 +2087,6 @@ void FreeListCategory::Reset() { | 
| } | 
| -intptr_t FreeListCategory::CountFreeListItemsInList(Page* p) { | 
| - int sum = 0; | 
| - FreeListNode* n = top_; | 
| - while (n != NULL) { | 
| - if (Page::FromAddress(n->address()) == p) { | 
| - FreeSpace* free_space = reinterpret_cast<FreeSpace*>(n); | 
| - sum += free_space->Size(); | 
| - } | 
| - n = n->next(); | 
| - } | 
| - return sum; | 
| -} | 
| - | 
| - | 
| intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { | 
| int sum = 0; | 
| FreeListNode** n = &top_; | 
| @@ -2170,20 +2187,28 @@ int FreeList::Free(Address start, int size_in_bytes) { | 
| FreeListNode* node = FreeListNode::FromAddress(start); | 
| node->set_size(heap_, size_in_bytes); | 
| + Page* page = Page::FromAddress(start); | 
| // Early return to drop too-small blocks on the floor. | 
| - if (size_in_bytes < kSmallListMin) return size_in_bytes; | 
| + if (size_in_bytes < kSmallListMin) { | 
| + page->AddNonAvailableSmallBlocks(size_in_bytes); | 
| + return size_in_bytes; | 
| + } | 
| // Insert other blocks at the head of a free list of the appropriate | 
| // magnitude. | 
| if (size_in_bytes <= kSmallListMax) { | 
| small_list_.Free(node, size_in_bytes); | 
| + page->AddAvailableInSmallFreeList(size_in_bytes); | 
| } else if (size_in_bytes <= kMediumListMax) { | 
| medium_list_.Free(node, size_in_bytes); | 
| + page->AddAvailableInMediumFreeList(size_in_bytes); | 
| } else if (size_in_bytes <= kLargeListMax) { | 
| large_list_.Free(node, size_in_bytes); | 
| + page->AddAvailableInLargeFreeList(size_in_bytes); | 
| } else { | 
| huge_list_.Free(node, size_in_bytes); | 
| + page->AddAvailableInHugeFreeList(size_in_bytes); | 
| } | 
| ASSERT(IsVeryLong() || available() == SumFreeLists()); | 
| @@ -2196,17 +2221,29 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 
| if (size_in_bytes <= kSmallAllocationMax) { | 
| node = small_list_.PickNodeFromList(node_size); | 
| - if (node != NULL) return node; | 
| + if (node != NULL) { | 
| + Page::FromAddress(node->address())->AddAvailableInSmallFreeList( | 
| 
 
Michael Starzinger
2013/04/09 16:56:04
nit: Can we pull out the page into a local "page"
 
Hannes Payer (out of office)
2013/04/10 07:53:49
Done.
 
 | 
| + -(*node_size)); | 
| + return node; | 
| + } | 
| } | 
| if (size_in_bytes <= kMediumAllocationMax) { | 
| node = medium_list_.PickNodeFromList(node_size); | 
| - if (node != NULL) return node; | 
| + if (node != NULL) { | 
| + Page::FromAddress(node->address())->AddAvailableInMediumFreeList( | 
| + -(*node_size)); | 
| + return node; | 
| + } | 
| } | 
| if (size_in_bytes <= kLargeAllocationMax) { | 
| node = large_list_.PickNodeFromList(node_size); | 
| - if (node != NULL) return node; | 
| + if (node != NULL) { | 
| + Page::FromAddress(node->address())->AddAvailableInLargeFreeList( | 
| + -(*node_size)); | 
| + return node; | 
| + } | 
| } | 
| int huge_list_available = huge_list_.available(); | 
| @@ -2217,6 +2254,8 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 
| while (cur_node != NULL && | 
| Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { | 
| huge_list_available -= reinterpret_cast<FreeSpace*>(cur_node)->Size(); | 
| + Page::FromAddress(cur_node->address())->AddAvailableInHugeFreeList( | 
| + -reinterpret_cast<FreeSpace*>(cur_node)->Size()); | 
| cur_node = cur_node->next(); | 
| } | 
| @@ -2235,6 +2274,7 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 
| *cur = node->next(); | 
| *node_size = size; | 
| huge_list_available -= size; | 
| + Page::FromAddress(node->address())->AddAvailableInHugeFreeList(-size); | 
| break; | 
| } | 
| } | 
| @@ -2322,27 +2362,17 @@ HeapObject* FreeList::Allocate(int size_in_bytes) { | 
| } | 
| -void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) { | 
| - sizes->huge_size_ = huge_list_.CountFreeListItemsInList(p); | 
| - if (sizes->huge_size_ < p->area_size()) { | 
| - sizes->small_size_ = small_list_.CountFreeListItemsInList(p); | 
| - sizes->medium_size_ = medium_list_.CountFreeListItemsInList(p); | 
| - sizes->large_size_ = large_list_.CountFreeListItemsInList(p); | 
| - } else { | 
| - sizes->small_size_ = 0; | 
| - sizes->medium_size_ = 0; | 
| - sizes->large_size_ = 0; | 
| - } | 
| -} | 
| - | 
| - | 
| intptr_t FreeList::EvictFreeListItems(Page* p) { | 
| intptr_t sum = huge_list_.EvictFreeListItemsInList(p); | 
| + p->set_available_in_huge_free_list(0); | 
| if (sum < p->area_size()) { | 
| sum += small_list_.EvictFreeListItemsInList(p) + | 
| medium_list_.EvictFreeListItemsInList(p) + | 
| large_list_.EvictFreeListItemsInList(p); | 
| + p->set_available_in_small_free_list(0); | 
| + p->set_available_in_medium_free_list(0); | 
| + p->set_available_in_large_free_list(0); | 
| } | 
| return sum; |