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; |