From 9e70cb84fb9b9d24c714a68a7f8973189e400b47 Mon Sep 17 00:00:00 2001 From: "hpayer@chromium.org" Date: Fri, 14 Jun 2013 11:22:25 +0000 Subject: [PATCH] As a last resort try to allocate out of the smaller size size-class in the free list allocator. BUG= R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/17058002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15146 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/spaces.cc | 58 +++++++++++++++++++++++++++++++++++++++++---------- src/spaces.h | 6 +----- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/spaces.cc b/src/spaces.cc index 50530a1957..d477e15f69 100644 --- a/src/spaces.cc +++ b/src/spaces.cc @@ -2118,13 +2118,13 @@ FreeListNode* FreeListCategory::PickNodeFromList(int *node_size) { while (node != NULL && Page::FromAddress(node->address())->IsEvacuationCandidate()) { - available_ -= node->Size(); + available_ -= reinterpret_cast(node)->Size(); node = node->next(); } if (node != NULL) { set_top(node->next()); - *node_size = node->Size(); + *node_size = reinterpret_cast(node)->Size(); available_ -= *node_size; } else { set_top(NULL); @@ -2138,6 +2138,18 @@ FreeListNode* FreeListCategory::PickNodeFromList(int *node_size) { } +FreeListNode* FreeListCategory::PickNodeFromList(int size_in_bytes, + int *node_size) { + FreeListNode* node = PickNodeFromList(node_size); + if (node != NULL && *node_size < size_in_bytes) { + Free(node, *node_size); + *node_size = 0; + return NULL; + } + return node; +} + + void FreeListCategory::Free(FreeListNode* node, int size_in_bytes) { node->set_next(top_); top_ = node; @@ -2202,11 +2214,6 @@ int FreeList::Free(Address start, int size_in_bytes) { // Insert other blocks at the head of a free list of the appropriate // magnitude. if (size_in_bytes <= kSmallListMax) { - ASSERT(!owner_->ConstantAllocationSize() || - (owner_->identity() == MAP_SPACE && size_in_bytes >= Map::kSize) || - (owner_->identity() == CELL_SPACE && size_in_bytes >= Cell::kSize) || - (owner_->identity() == PROPERTY_CELL_SPACE && - size_in_bytes >= JSGlobalPropertyCell::kSize)); small_list_.Free(node, size_in_bytes); page->add_available_in_small_free_list(size_in_bytes); } else if (size_in_bytes <= kMediumListMax) { @@ -2229,13 +2236,13 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { FreeListNode* node = NULL; Page* page = NULL; - if ((owner_->ConstantAllocationSize() && size_in_bytes <= kSmallListMax) || - size_in_bytes <= kSmallAllocationMax) { + if (size_in_bytes <= kSmallAllocationMax) { node = small_list_.PickNodeFromList(node_size); if (node != NULL) { ASSERT(size_in_bytes <= *node_size); page = Page::FromAddress(node->address()); page->add_available_in_small_free_list(-(*node_size)); + ASSERT(IsVeryLong() || available() == SumFreeLists()); return node; } } @@ -2246,6 +2253,7 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { ASSERT(size_in_bytes <= *node_size); page = Page::FromAddress(node->address()); page->add_available_in_medium_free_list(-(*node_size)); + ASSERT(IsVeryLong() || available() == SumFreeLists()); return node; } } @@ -2256,6 +2264,7 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { ASSERT(size_in_bytes <= *node_size); page = Page::FromAddress(node->address()); page->add_available_in_large_free_list(-(*node_size)); + ASSERT(IsVeryLong() || available() == SumFreeLists()); return node; } } @@ -2298,10 +2307,37 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { if (huge_list_.top() == NULL) { huge_list_.set_end(NULL); } - huge_list_.set_available(huge_list_available); - ASSERT(IsVeryLong() || available() == SumFreeLists()); + if (node != NULL) { + ASSERT(IsVeryLong() || available() == SumFreeLists()); + return node; + } + + if (size_in_bytes <= kSmallListMax) { + node = small_list_.PickNodeFromList(size_in_bytes, node_size); + if (node != NULL) { + ASSERT(size_in_bytes <= *node_size); + page = Page::FromAddress(node->address()); + page->add_available_in_small_free_list(-(*node_size)); + } + } else if (size_in_bytes <= kMediumListMax) { + node = medium_list_.PickNodeFromList(size_in_bytes, node_size); + if (node != NULL) { + ASSERT(size_in_bytes <= *node_size); + page = Page::FromAddress(node->address()); + page->add_available_in_medium_free_list(-(*node_size)); + } + } else if (size_in_bytes <= kLargeListMax) { + node = large_list_.PickNodeFromList(size_in_bytes, node_size); + if (node != NULL) { + ASSERT(size_in_bytes <= *node_size); + page = Page::FromAddress(node->address()); + page->add_available_in_large_free_list(-(*node_size)); + } + } + + ASSERT(IsVeryLong() || available() == SumFreeLists()); return node; } diff --git a/src/spaces.h b/src/spaces.h index 56be1406b6..d964549e56 100644 --- a/src/spaces.h +++ b/src/spaces.h @@ -1454,6 +1454,7 @@ class FreeListCategory { void Free(FreeListNode* node, int size_in_bytes); FreeListNode* PickNodeFromList(int *node_size); + FreeListNode* PickNodeFromList(int size_in_bytes, int *node_size); intptr_t EvictFreeListItemsInList(Page* p); @@ -1820,11 +1821,6 @@ class PagedSpace : public Space { return area_size_; } - bool ConstantAllocationSize() { - return identity() == MAP_SPACE || identity() == CELL_SPACE || - identity() == PROPERTY_CELL_SPACE; - } - protected: FreeList* free_list() { return &free_list_; }