| Index: src/spaces.cc
|
| diff --git a/src/spaces.cc b/src/spaces.cc
|
| index cacd9691501c10428a7a2b97d3a810cfd683789a..ab3bcf2d84c8d1a19912380d7d5f4a98764b2df9 100644
|
| --- a/src/spaces.cc
|
| +++ b/src/spaces.cc
|
| @@ -1929,6 +1929,98 @@ void FreeListNode::set_next(FreeListNode* next) {
|
| }
|
|
|
|
|
| +void FreeListCategory::Reset() {
|
| + top_ = NULL;
|
| + end_ = NULL;
|
| + available_ = 0;
|
| +}
|
| +
|
| +
|
| +intptr_t FreeListCategory::CountFreeListItemsInList(Page* p) {
|
| + intptr_t 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) {
|
| + intptr_t 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();
|
| + } else {
|
| + n = (*n)->next_address();
|
| + }
|
| + }
|
| + if (top_ == NULL) {
|
| + end_ = NULL;
|
| + }
|
| + available_ -= sum;
|
| + return sum;
|
| +}
|
| +
|
| +
|
| +FreeListNode* FreeListCategory::PickNodeFromList(int *node_size) {
|
| + FreeListNode* node = top_;
|
| +
|
| + if (node == NULL) return NULL;
|
| +
|
| + while (node != NULL &&
|
| + Page::FromAddress(node->address())->IsEvacuationCandidate()) {
|
| + available_ -= node->Size();
|
| + node = node->next();
|
| + }
|
| +
|
| + if (node != NULL) {
|
| + set_top(node->next());
|
| + *node_size = node->Size();
|
| + available_ -= *node_size;
|
| + } else {
|
| + set_top(NULL);
|
| + }
|
| +
|
| + if (top() == NULL) {
|
| + set_end(NULL);
|
| + }
|
| +
|
| + return node;
|
| +}
|
| +
|
| +
|
| +void FreeListCategory::Free(FreeListNode* node, int size_in_bytes) {
|
| + node->set_next(top_);
|
| + top_ = node;
|
| + if (end_ == NULL) {
|
| + end_ = node;
|
| + }
|
| + available_ += size_in_bytes;
|
| +}
|
| +
|
| +
|
| +void FreeListCategory::RepairFreeList(Heap* heap) {
|
| + FreeListNode* n = top_;
|
| + while (n != NULL) {
|
| + Map** map_location = reinterpret_cast<Map**>(n->address());
|
| + if (*map_location == NULL) {
|
| + *map_location = heap->free_space_map();
|
| + } else {
|
| + ASSERT(*map_location == heap->free_space_map());
|
| + }
|
| + n = n->next();
|
| + }
|
| +}
|
| +
|
| +
|
| FreeList::FreeList(PagedSpace* owner)
|
| : owner_(owner), heap_(owner->heap()) {
|
| Reset();
|
| @@ -1936,16 +2028,16 @@ FreeList::FreeList(PagedSpace* owner)
|
|
|
|
|
| void FreeList::Reset() {
|
| - available_ = 0;
|
| - small_list_ = NULL;
|
| - medium_list_ = NULL;
|
| - large_list_ = NULL;
|
| - huge_list_ = NULL;
|
| + small_list_.Reset();
|
| + medium_list_.Reset();
|
| + large_list_.Reset();
|
| + huge_list_.Reset();
|
| }
|
|
|
|
|
| int FreeList::Free(Address start, int size_in_bytes) {
|
| if (size_in_bytes == 0) return 0;
|
| +
|
| FreeListNode* node = FreeListNode::FromAddress(start);
|
| node->set_size(heap_, size_in_bytes);
|
|
|
| @@ -1955,43 +2047,17 @@ 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) {
|
| - node->set_next(small_list_);
|
| - small_list_ = node;
|
| + small_list_.Free(node, size_in_bytes);
|
| } else if (size_in_bytes <= kMediumListMax) {
|
| - node->set_next(medium_list_);
|
| - medium_list_ = node;
|
| + medium_list_.Free(node, size_in_bytes);
|
| } else if (size_in_bytes <= kLargeListMax) {
|
| - node->set_next(large_list_);
|
| - large_list_ = node;
|
| - } else {
|
| - node->set_next(huge_list_);
|
| - huge_list_ = node;
|
| - }
|
| - available_ += size_in_bytes;
|
| - ASSERT(IsVeryLong() || available_ == SumFreeLists());
|
| - return 0;
|
| -}
|
| -
|
| -
|
| -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();
|
| + large_list_.Free(node, size_in_bytes);
|
| } else {
|
| - *list = NULL;
|
| + huge_list_.Free(node, size_in_bytes);
|
| }
|
|
|
| - return node;
|
| + ASSERT(IsVeryLong() || available() == SumFreeLists());
|
| + return 0;
|
| }
|
|
|
|
|
| @@ -1999,32 +2065,36 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
|
| FreeListNode* node = NULL;
|
|
|
| if (size_in_bytes <= kSmallAllocationMax) {
|
| - node = PickNodeFromList(&small_list_, node_size);
|
| + node = small_list_.PickNodeFromList(node_size);
|
| if (node != NULL) return node;
|
| }
|
|
|
| if (size_in_bytes <= kMediumAllocationMax) {
|
| - node = PickNodeFromList(&medium_list_, node_size);
|
| + node = medium_list_.PickNodeFromList(node_size);
|
| if (node != NULL) return node;
|
| }
|
|
|
| if (size_in_bytes <= kLargeAllocationMax) {
|
| - node = PickNodeFromList(&large_list_, node_size);
|
| + node = large_list_.PickNodeFromList(node_size);
|
| if (node != NULL) return node;
|
| }
|
|
|
| - for (FreeListNode** cur = &huge_list_;
|
| + int huge_list_available = huge_list_.available();
|
| + for (FreeListNode** cur = huge_list_.GetTopAddress();
|
| *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();
|
| + huge_list_available -= reinterpret_cast<FreeSpace*>(cur_node)->Size();
|
| cur_node = cur_node->next();
|
| }
|
|
|
| *cur = cur_node;
|
| - if (cur_node == NULL) break;
|
| + if (cur_node == NULL) {
|
| + huge_list_.set_end(NULL);
|
| + break;
|
| + }
|
|
|
| ASSERT((*cur)->map() == HEAP->raw_unchecked_free_space_map());
|
| FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur);
|
| @@ -2032,12 +2102,20 @@ FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
|
| if (size >= size_in_bytes) {
|
| // Large enough node found. Unlink it from the list.
|
| node = *cur;
|
| - *node_size = size;
|
| *cur = node->next();
|
| + *node_size = size;
|
| + huge_list_available -= size;
|
| break;
|
| }
|
| }
|
|
|
| + if (huge_list_.top() == NULL) {
|
| + huge_list_.set_end(NULL);
|
| + }
|
| +
|
| + huge_list_.set_available(huge_list_available);
|
| + ASSERT(IsVeryLong() || available() == SumFreeLists());
|
| +
|
| return node;
|
| }
|
|
|
| @@ -2057,8 +2135,6 @@ HeapObject* FreeList::Allocate(int size_in_bytes) {
|
| 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);
|
| @@ -2116,25 +2192,12 @@ HeapObject* FreeList::Allocate(int size_in_bytes) {
|
| }
|
|
|
|
|
| -static intptr_t CountFreeListItemsInList(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();
|
| - }
|
| - return sum;
|
| -}
|
| -
|
| -
|
| void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) {
|
| - sizes->huge_size_ = CountFreeListItemsInList(huge_list_, p);
|
| + sizes->huge_size_ = huge_list_.CountFreeListItemsInList(p);
|
| if (sizes->huge_size_ < p->area_size()) {
|
| - sizes->small_size_ = CountFreeListItemsInList(small_list_, p);
|
| - sizes->medium_size_ = CountFreeListItemsInList(medium_list_, p);
|
| - sizes->large_size_ = CountFreeListItemsInList(large_list_, p);
|
| + 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;
|
| @@ -2143,39 +2206,31 @@ void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) {
|
| }
|
|
|
|
|
| -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);
|
| + intptr_t sum = huge_list_.EvictFreeListItemsInList(p);
|
|
|
| if (sum < p->area_size()) {
|
| - sum += EvictFreeListItemsInList(&small_list_, p) +
|
| - EvictFreeListItemsInList(&medium_list_, p) +
|
| - EvictFreeListItemsInList(&large_list_, p);
|
| + sum += small_list_.EvictFreeListItemsInList(p) +
|
| + medium_list_.EvictFreeListItemsInList(p) +
|
| + large_list_.EvictFreeListItemsInList(p);
|
| }
|
|
|
| - available_ -= static_cast<int>(sum);
|
| -
|
| return sum;
|
| }
|
|
|
|
|
| +void FreeList::RepairLists(Heap* heap) {
|
| + small_list_.RepairFreeList(heap);
|
| + medium_list_.RepairFreeList(heap);
|
| + large_list_.RepairFreeList(heap);
|
| + huge_list_.RepairFreeList(heap);
|
| +}
|
| +
|
| +
|
| #ifdef DEBUG
|
| -intptr_t FreeList::SumFreeList(FreeListNode* cur) {
|
| +intptr_t FreeListCategory::SumFreeList() {
|
| intptr_t sum = 0;
|
| + FreeListNode* cur = top_;
|
| while (cur != NULL) {
|
| ASSERT(cur->map() == HEAP->raw_unchecked_free_space_map());
|
| FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(cur);
|
| @@ -2189,8 +2244,9 @@ intptr_t FreeList::SumFreeList(FreeListNode* cur) {
|
| static const int kVeryLongFreeList = 500;
|
|
|
|
|
| -int FreeList::FreeListLength(FreeListNode* cur) {
|
| +int FreeListCategory::FreeListLength() {
|
| int length = 0;
|
| + FreeListNode* cur = top_;
|
| while (cur != NULL) {
|
| length++;
|
| cur = cur->next();
|
| @@ -2201,10 +2257,10 @@ int FreeList::FreeListLength(FreeListNode* cur) {
|
|
|
|
|
| bool FreeList::IsVeryLong() {
|
| - if (FreeListLength(small_list_) == kVeryLongFreeList) return true;
|
| - if (FreeListLength(medium_list_) == kVeryLongFreeList) return true;
|
| - if (FreeListLength(large_list_) == kVeryLongFreeList) return true;
|
| - if (FreeListLength(huge_list_) == kVeryLongFreeList) return true;
|
| + if (small_list_.FreeListLength() == kVeryLongFreeList) return true;
|
| + if (medium_list_.FreeListLength() == kVeryLongFreeList) return true;
|
| + if (large_list_.FreeListLength() == kVeryLongFreeList) return true;
|
| + if (huge_list_.FreeListLength() == kVeryLongFreeList) return true;
|
| return false;
|
| }
|
|
|
| @@ -2213,10 +2269,10 @@ bool FreeList::IsVeryLong() {
|
| // on the free list, so it should not be called if FreeListLength returns
|
| // kVeryLongFreeList.
|
| intptr_t FreeList::SumFreeLists() {
|
| - intptr_t sum = SumFreeList(small_list_);
|
| - sum += SumFreeList(medium_list_);
|
| - sum += SumFreeList(large_list_);
|
| - sum += SumFreeList(huge_list_);
|
| + intptr_t sum = small_list_.SumFreeList();
|
| + sum += medium_list_.SumFreeList();
|
| + sum += large_list_.SumFreeList();
|
| + sum += huge_list_.SumFreeList();
|
| return sum;
|
| }
|
| #endif
|
| @@ -2304,27 +2360,6 @@ bool PagedSpace::ReserveSpace(int size_in_bytes) {
|
| }
|
|
|
|
|
| -static void RepairFreeList(Heap* heap, FreeListNode* n) {
|
| - while (n != NULL) {
|
| - Map** map_location = reinterpret_cast<Map**>(n->address());
|
| - if (*map_location == NULL) {
|
| - *map_location = heap->free_space_map();
|
| - } else {
|
| - ASSERT(*map_location == heap->free_space_map());
|
| - }
|
| - n = n->next();
|
| - }
|
| -}
|
| -
|
| -
|
| -void FreeList::RepairLists(Heap* heap) {
|
| - RepairFreeList(heap, small_list_);
|
| - RepairFreeList(heap, medium_list_);
|
| - RepairFreeList(heap, large_list_);
|
| - RepairFreeList(heap, huge_list_);
|
| -}
|
| -
|
| -
|
| // After we have booted, we have created a map which represents free space
|
| // on the heap. If there was already a free list then the elements on it
|
| // were created with the wrong FreeSpaceMap (normally NULL), so we need to
|
|
|