Index: src/heap/spaces.cc |
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc |
index f7cce1430e55eee5e436f9b49639efcfaebb858b..1e0ed9c8fd10dbefc3e1646de6fd1c979ada6b38 100644 |
--- a/src/heap/spaces.cc |
+++ b/src/heap/spaces.cc |
@@ -1030,79 +1030,46 @@ void PagedSpace::TearDown() { |
accounting_stats_.Clear(); |
} |
- |
-void PagedSpace::AddMemory(Address start, intptr_t size) { |
- accounting_stats_.ExpandSpace(static_cast<int>(size)); |
- Free(start, static_cast<int>(size)); |
-} |
- |
- |
void PagedSpace::RefillFreeList() { |
- MarkCompactCollector* collector = heap()->mark_compact_collector(); |
- FreeList* free_list = nullptr; |
- if (this == heap()->old_space()) { |
- free_list = collector->free_list_old_space().get(); |
- } else if (this == heap()->code_space()) { |
- free_list = collector->free_list_code_space().get(); |
- } else if (this == heap()->map_space()) { |
- free_list = collector->free_list_map_space().get(); |
- } else { |
- // Any PagedSpace might invoke RefillFreeList. We filter all but our old |
- // generation spaces out. |
+ // Any PagedSpace might invoke RefillFreeList. We filter all but our old |
+ // generation spaces out. |
+ if (identity() != OLD_SPACE && identity() != CODE_SPACE && |
+ identity() != MAP_SPACE) { |
return; |
} |
- DCHECK(free_list != nullptr); |
- intptr_t added = free_list_.Concatenate(free_list); |
- accounting_stats_.IncreaseCapacity(added); |
-} |
- |
- |
-void CompactionSpace::RefillFreeList() { |
MarkCompactCollector* collector = heap()->mark_compact_collector(); |
- FreeList* free_list = nullptr; |
- if (identity() == OLD_SPACE) { |
- free_list = collector->free_list_old_space().get(); |
- } else if (identity() == CODE_SPACE) { |
- free_list = collector->free_list_code_space().get(); |
- } else { |
- // Compaction spaces only represent old or code space. |
- UNREACHABLE(); |
- } |
- DCHECK(free_list != nullptr); |
- intptr_t refilled = 0; |
- while (refilled < kCompactionMemoryWanted) { |
- FreeSpace* node = |
- free_list->TryRemoveMemory(kCompactionMemoryWanted - refilled); |
- if (node == nullptr) return; |
- refilled += node->size(); |
- AddMemory(node->address(), node->size()); |
+ List<Page*>* swept_pages = collector->swept_pages(identity()); |
+ intptr_t added = 0; |
+ { |
+ base::LockGuard<base::Mutex> guard(collector->swept_pages_mutex()); |
+ for (int i = swept_pages->length() - 1; i >= 0; --i) { |
+ Page* p = (*swept_pages)[i]; |
+ // Only during compaction pages can actually change ownership. This is |
+ // safe because there exists no other competing action on the page links |
+ // during compaction. |
+ if (is_local() && (p->owner() != this)) { |
+ if (added > kCompactionMemoryWanted) break; |
+ base::LockGuard<base::Mutex> guard( |
+ reinterpret_cast<PagedSpace*>(p->owner())->mutex()); |
+ p->Unlink(); |
+ p->set_owner(this); |
+ p->InsertAfter(anchor_.prev_page()); |
+ } |
+ added += RelinkFreeListCategories(p); |
+ added += p->wasted_memory(); |
+ swept_pages->Remove(i); |
+ } |
} |
-} |
- |
-void PagedSpace::MoveOverFreeMemory(PagedSpace* other) { |
- DCHECK(identity() == other->identity()); |
- // Destroy the linear allocation space of {other}. This is needed to |
- // (a) not waste the memory and |
- // (b) keep the rest of the chunk in an iterable state (filler is needed). |
- other->EmptyAllocationInfo(); |
- |
- // Move over the free list. Concatenate makes sure that the source free list |
- // gets properly reset after moving over all nodes. |
- intptr_t added = free_list_.Concatenate(other->free_list()); |
- |
- // Moved memory is not recorded as allocated memory, but rather increases and |
- // decreases capacity of the corresponding spaces. |
- other->accounting_stats_.DecreaseCapacity(added); |
accounting_stats_.IncreaseCapacity(added); |
} |
- |
void PagedSpace::MergeCompactionSpace(CompactionSpace* other) { |
+ DCHECK(identity() == other->identity()); |
// Unmerged fields: |
// area_size_ |
// anchor_ |
- MoveOverFreeMemory(other); |
+ other->EmptyAllocationInfo(); |
// Update and clear accounting statistics. |
accounting_stats_.Merge(other->accounting_stats_); |
@@ -1119,9 +1086,14 @@ void PagedSpace::MergeCompactionSpace(CompactionSpace* other) { |
Page* p = nullptr; |
while (it.has_next()) { |
p = it.next(); |
+ |
+ // Relinking requires the category to be unlinked. |
+ other->UnlinkFreeListCategories(p); |
+ |
p->Unlink(); |
p->set_owner(this); |
p->InsertAfter(anchor_.prev_page()); |
+ RelinkFreeListCategories(p); |
} |
} |
@@ -1238,17 +1210,12 @@ void PagedSpace::IncreaseCapacity(int size) { |
accounting_stats_.ExpandSpace(size); |
} |
+void PagedSpace::ReleasePage(Page* page) { |
+ DCHECK_EQ(page->LiveBytes(), 0); |
+ DCHECK_EQ(AreaSize(), page->area_size()); |
+ DCHECK_EQ(page->owner(), this); |
-void PagedSpace::ReleasePage(Page* page, bool evict_free_list_items) { |
- DCHECK(page->LiveBytes() == 0); |
- DCHECK(AreaSize() == page->area_size()); |
- |
- if (evict_free_list_items) { |
- intptr_t size = free_list_.EvictFreeListItems(page); |
- accounting_stats_.AllocateBytes(size); |
- DCHECK_EQ(AreaSize(), static_cast<int>(size)); |
- } |
- |
+ free_list_.EvictFreeListItems(page); |
DCHECK(!free_list_.ContainsPageFreeListItems(page)); |
if (Page::FromAllocationTop(allocation_info_.top()) == page) { |
@@ -1268,7 +1235,6 @@ void PagedSpace::ReleasePage(Page* page, bool evict_free_list_items) { |
accounting_stats_.ShrinkSpace(AreaSize()); |
} |
- |
#ifdef DEBUG |
void PagedSpace::Print() {} |
#endif |
@@ -2175,137 +2141,54 @@ size_t NewSpace::CommittedPhysicalMemory() { |
// ----------------------------------------------------------------------------- |
// Free lists for old object spaces implementation |
-intptr_t FreeListCategory::Concatenate(FreeListCategory* category) { |
- intptr_t free_bytes = 0; |
- if (category->top() != NULL) { |
- DCHECK(category->end_ != NULL); |
- free_bytes = category->available(); |
- if (end_ == NULL) { |
- end_ = category->end(); |
- } else { |
- category->end()->set_next(top()); |
- } |
- set_top(category->top()); |
- available_ += category->available(); |
- category->Reset(); |
- } |
- return free_bytes; |
-} |
- |
void FreeListCategory::Reset() { |
set_top(nullptr); |
- set_end(nullptr); |
+ set_prev(nullptr); |
+ set_next(nullptr); |
available_ = 0; |
} |
- |
-intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { |
- intptr_t sum = 0; |
- FreeSpace* prev_node = nullptr; |
- for (FreeSpace* cur_node = top(); cur_node != nullptr; |
- cur_node = cur_node->next()) { |
- Page* page_for_node = Page::FromAddress(cur_node->address()); |
- if (page_for_node == p) { |
- // FreeSpace node on eviction page found, unlink it. |
- int size = cur_node->size(); |
- sum += size; |
- DCHECK((prev_node != nullptr) || (top() == cur_node)); |
- if (cur_node == top()) { |
- set_top(cur_node->next()); |
- } |
- if (cur_node == end()) { |
- set_end(prev_node); |
- } |
- if (prev_node != nullptr) { |
- prev_node->set_next(cur_node->next()); |
- } |
- continue; |
- } |
- prev_node = cur_node; |
- } |
- p->add_available_in_free_list(-sum); |
- available_ -= sum; |
- return sum; |
-} |
- |
- |
-bool FreeListCategory::ContainsPageFreeListItemsInList(Page* p) { |
- FreeSpace* node = top(); |
- while (node != NULL) { |
- if (Page::FromAddress(node->address()) == p) return true; |
- node = node->next(); |
- } |
- return false; |
-} |
- |
- |
FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) { |
+ DCHECK(page()->CanAllocate()); |
+ |
FreeSpace* node = top(); |
if (node == nullptr) return nullptr; |
- |
- Page* page = Page::FromAddress(node->address()); |
- while ((node != nullptr) && !page->CanAllocate()) { |
- available_ -= node->size(); |
- page->add_available_in_free_list(-(node->Size())); |
- node = node->next(); |
- } |
- |
- if (node != nullptr) { |
- set_top(node->next()); |
- *node_size = node->Size(); |
- available_ -= *node_size; |
- } else { |
- set_top(nullptr); |
- } |
- |
- if (top() == nullptr) { |
- set_end(nullptr); |
- } |
- |
+ set_top(node->next()); |
+ *node_size = node->Size(); |
+ available_ -= *node_size; |
return node; |
} |
+FreeSpace* FreeListCategory::TryPickNodeFromList(int minimum_size, |
+ int* node_size) { |
+ DCHECK(page()->CanAllocate()); |
-FreeSpace* FreeListCategory::PickNodeFromList(int size_in_bytes, |
- int* node_size) { |
FreeSpace* node = PickNodeFromList(node_size); |
- if ((node != nullptr) && (*node_size < size_in_bytes)) { |
- Free(node, *node_size); |
+ if ((node != nullptr) && (*node_size < minimum_size)) { |
+ Free(node, *node_size, kLinkCategory); |
*node_size = 0; |
return nullptr; |
} |
return node; |
} |
- |
-FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes, |
+FreeSpace* FreeListCategory::SearchForNodeInList(int minimum_size, |
int* node_size) { |
+ DCHECK(page()->CanAllocate()); |
+ |
FreeSpace* prev_non_evac_node = nullptr; |
for (FreeSpace* cur_node = top(); cur_node != nullptr; |
cur_node = cur_node->next()) { |
int size = cur_node->size(); |
- Page* page_for_node = Page::FromAddress(cur_node->address()); |
- |
- if ((size >= size_in_bytes) || !page_for_node->CanAllocate()) { |
- // The node is either large enough or contained in an evacuation |
- // candidate. In both cases we need to unlink it from the list. |
+ if (size >= minimum_size) { |
available_ -= size; |
if (cur_node == top()) { |
set_top(cur_node->next()); |
} |
- if (cur_node == end()) { |
- set_end(prev_non_evac_node); |
- } |
if (prev_non_evac_node != nullptr) { |
prev_non_evac_node->set_next(cur_node->next()); |
} |
- // For evacuation candidates we continue. |
- if (!page_for_node->CanAllocate()) { |
- page_for_node->add_available_in_free_list(-size); |
- continue; |
- } |
- // Otherwise we have a large enough node and can return. |
*node_size = size; |
return cur_node; |
} |
@@ -2315,14 +2198,17 @@ FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes, |
return nullptr; |
} |
+bool FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes, |
+ FreeMode mode) { |
+ if (!page()->CanAllocate()) return false; |
-void FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes) { |
free_space->set_next(top()); |
set_top(free_space); |
- if (end_ == NULL) { |
- end_ = free_space; |
- } |
available_ += size_in_bytes; |
+ if ((mode == kLinkCategory) && (prev() == nullptr) && (next() == nullptr)) { |
+ owner()->AddCategory(this); |
+ } |
+ return true; |
} |
@@ -2339,49 +2225,35 @@ void FreeListCategory::RepairFreeList(Heap* heap) { |
} |
} |
-FreeList::FreeList(PagedSpace* owner) : owner_(owner), wasted_bytes_(0) { |
- for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
- category_[i].Initialize(this, static_cast<FreeListCategoryType>(i)); |
- } |
- Reset(); |
+void FreeListCategory::Relink() { |
+ DCHECK(!is_linked()); |
+ owner()->AddCategory(this); |
} |
+void FreeListCategory::Invalidate() { |
+ page()->add_available_in_free_list(-available()); |
+ Reset(); |
+ type_ = kInvalidCategory; |
+} |
-intptr_t FreeList::Concatenate(FreeList* other) { |
- intptr_t usable_bytes = 0; |
- intptr_t wasted_bytes = 0; |
- |
- // This is safe (not going to deadlock) since Concatenate operations |
- // are never performed on the same free lists at the same time in |
- // reverse order. Furthermore, we only lock if the PagedSpace containing |
- // the free list is know to be globally available, i.e., not local. |
- if (!owner()->is_local()) mutex_.Lock(); |
- if (!other->owner()->is_local()) other->mutex()->Lock(); |
- |
- wasted_bytes = other->wasted_bytes_; |
- wasted_bytes_ += wasted_bytes; |
- other->wasted_bytes_ = 0; |
- |
+FreeList::FreeList(PagedSpace* owner) : owner_(owner), wasted_bytes_(0) { |
for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
- usable_bytes += category_[i].Concatenate( |
- other->GetFreeListCategory(static_cast<FreeListCategoryType>(i))); |
+ categories_[i] = nullptr; |
} |
- |
- if (!other->owner()->is_local()) other->mutex()->Unlock(); |
- if (!owner()->is_local()) mutex_.Unlock(); |
- return usable_bytes + wasted_bytes; |
+ Reset(); |
} |
void FreeList::Reset() { |
+ ForAllFreeListCategories( |
+ [](FreeListCategory* category) { category->Reset(); }); |
for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
- category_[i].Reset(); |
+ categories_[i] = nullptr; |
} |
ResetStats(); |
} |
- |
-int FreeList::Free(Address start, int size_in_bytes) { |
+int FreeList::Free(Address start, int size_in_bytes, FreeMode mode) { |
if (size_in_bytes == 0) return 0; |
owner()->heap()->CreateFillerObjectAt(start, size_in_bytes, |
@@ -2392,7 +2264,7 @@ int FreeList::Free(Address start, int size_in_bytes) { |
// Blocks have to be a minimum size to hold free list items. |
if (size_in_bytes < kMinBlockSize) { |
page->add_wasted_memory(size_in_bytes); |
- wasted_bytes_ += size_in_bytes; |
+ wasted_bytes_.Increment(size_in_bytes); |
return size_in_bytes; |
} |
@@ -2400,16 +2272,34 @@ int FreeList::Free(Address start, int size_in_bytes) { |
// Insert other blocks at the head of a free list of the appropriate |
// magnitude. |
FreeListCategoryType type = SelectFreeListCategoryType(size_in_bytes); |
- category_[type].Free(free_space, size_in_bytes); |
- page->add_available_in_free_list(size_in_bytes); |
- |
- DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
+ if (page->free_list_category(type)->Free(free_space, size_in_bytes, mode)) { |
+ page->add_available_in_free_list(size_in_bytes); |
+ } |
return 0; |
} |
+FreeSpace* FreeList::FindNodeIn(FreeListCategoryType type, int* node_size) { |
+ FreeListCategoryIterator it(this, type); |
+ FreeSpace* node = nullptr; |
+ while (it.HasNext()) { |
+ FreeListCategory* current = it.Next(); |
+ node = current->PickNodeFromList(node_size); |
+ if (node != nullptr) { |
+ Page::FromAddress(node->address()) |
+ ->add_available_in_free_list(-(*node_size)); |
+ DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
+ return node; |
+ } |
+ RemoveCategory(current); |
+ } |
+ return node; |
+} |
-FreeSpace* FreeList::FindNodeIn(FreeListCategoryType category, int* node_size) { |
- FreeSpace* node = GetFreeListCategory(category)->PickNodeFromList(node_size); |
+FreeSpace* FreeList::TryFindNodeIn(FreeListCategoryType type, int* node_size, |
+ int minimum_size) { |
+ if (categories_[type] == nullptr) return nullptr; |
+ FreeSpace* node = |
+ categories_[type]->TryPickNodeFromList(minimum_size, node_size); |
if (node != nullptr) { |
Page::FromAddress(node->address()) |
->add_available_in_free_list(-(*node_size)); |
@@ -2418,6 +2308,22 @@ FreeSpace* FreeList::FindNodeIn(FreeListCategoryType category, int* node_size) { |
return node; |
} |
+FreeSpace* FreeList::SearchForNodeInList(FreeListCategoryType type, |
+ int* node_size, int minimum_size) { |
+ FreeListCategoryIterator it(this, type); |
+ FreeSpace* node = nullptr; |
+ while (it.HasNext()) { |
+ FreeListCategory* current = it.Next(); |
+ node = current->SearchForNodeInList(minimum_size, node_size); |
+ if (node != nullptr) { |
+ Page::FromAddress(node->address()) |
+ ->add_available_in_free_list(-(*node_size)); |
+ DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
+ return node; |
+ } |
+ } |
+ return node; |
+} |
FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
FreeSpace* node = nullptr; |
@@ -2434,10 +2340,8 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
// Next search the huge list for free list nodes. This takes linear time in |
// the number of huge elements. |
- node = category_[kHuge].SearchForNodeInList(size_in_bytes, node_size); |
+ node = SearchForNodeInList(kHuge, node_size, size_in_bytes); |
if (node != nullptr) { |
- page = Page::FromAddress(node->address()); |
- page->add_available_in_free_list(-(*node_size)); |
DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
return node; |
} |
@@ -2449,7 +2353,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
// Now search the best fitting free list for a node that has at least the |
// requested size. |
type = SelectFreeListCategoryType(size_in_bytes); |
- node = category_[type].PickNodeFromList(size_in_bytes, node_size); |
+ node = TryFindNodeIn(type, node_size, size_in_bytes); |
if (node != nullptr) { |
DCHECK(size_in_bytes <= *node_size); |
page = Page::FromAddress(node->address()); |
@@ -2460,38 +2364,6 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
return node; |
} |
- |
-FreeSpace* FreeList::TryRemoveMemory(intptr_t hint_size_in_bytes) { |
- hint_size_in_bytes = RoundDown(hint_size_in_bytes, kPointerSize); |
- base::LockGuard<base::Mutex> guard(&mutex_); |
- FreeSpace* node = nullptr; |
- int node_size = 0; |
- // Try to find a node that fits exactly. |
- node = FindNodeFor(static_cast<int>(hint_size_in_bytes), &node_size); |
- // If no node could be found get as much memory as possible. |
- if (node == nullptr) node = FindNodeIn(kHuge, &node_size); |
- if (node == nullptr) node = FindNodeIn(kLarge, &node_size); |
- if (node != nullptr) { |
- // We round up the size to (kMinBlockSize + kPointerSize) to (a) have a |
- // size larger then the minimum size required for FreeSpace, and (b) to get |
- // a block that can actually be freed into some FreeList later on. |
- if (hint_size_in_bytes <= kMinBlockSize) { |
- hint_size_in_bytes = kMinBlockSize + kPointerSize; |
- } |
- // Give back left overs that were not required by {size_in_bytes}. |
- intptr_t left_over = node_size - hint_size_in_bytes; |
- |
- // Do not bother to return anything below {kMinBlockSize} as it would be |
- // immediately discarded anyways. |
- if (left_over > kMinBlockSize) { |
- Free(node->address() + hint_size_in_bytes, static_cast<int>(left_over)); |
- node->set_size(static_cast<int>(hint_size_in_bytes)); |
- } |
- } |
- return node; |
-} |
- |
- |
// Allocation on the old space free list. If it succeeds then a new linear |
// allocation space has been set up with the top and limit of the space. If |
// the allocation fails then NULL is returned, and the caller can perform a GC |
@@ -2565,32 +2437,76 @@ HeapObject* FreeList::Allocate(int size_in_bytes) { |
return new_node; |
} |
- |
-intptr_t FreeList::EvictFreeListItems(Page* p) { |
- intptr_t sum = category_[kHuge].EvictFreeListItemsInList(p); |
- if (sum < p->area_size()) { |
- for (int i = kFirstCategory; i <= kLarge; i++) { |
- sum += category_[i].EvictFreeListItemsInList(p); |
- } |
- } |
+intptr_t FreeList::EvictFreeListItems(Page* page) { |
+ intptr_t sum = 0; |
+ page->ForAllFreeListCategories( |
+ [this, &sum, page](FreeListCategory* category) { |
+ DCHECK_EQ(this, category->owner()); |
+ sum += category->available(); |
+ RemoveCategory(category); |
+ category->Invalidate(); |
+ }); |
return sum; |
} |
+bool FreeList::ContainsPageFreeListItems(Page* page) { |
+ bool contained = false; |
+ page->ForAllFreeListCategories( |
+ [this, &contained](FreeListCategory* category) { |
+ if (category->owner() == this && category->is_linked()) { |
+ contained = true; |
+ } |
+ }); |
+ return contained; |
+} |
-bool FreeList::ContainsPageFreeListItems(Page* p) { |
- for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
- if (category_[i].EvictFreeListItemsInList(p)) { |
- return true; |
- } |
+void FreeList::RepairLists(Heap* heap) { |
+ ForAllFreeListCategories( |
+ [heap](FreeListCategory* category) { category->RepairFreeList(heap); }); |
+} |
+ |
+bool FreeList::AddCategory(FreeListCategory* category) { |
+ FreeListCategoryType type = category->type_; |
+ FreeListCategory* top = categories_[type]; |
+ |
+ if (category->is_empty()) return false; |
+ if (top == category) return false; |
+ |
+ // Common double-linked list insertion. |
+ if (top != nullptr) { |
+ top->set_prev(category); |
} |
- return false; |
+ category->set_next(top); |
+ categories_[type] = category; |
+ return true; |
} |
+void FreeList::RemoveCategory(FreeListCategory* category) { |
+ FreeListCategoryType type = category->type_; |
+ FreeListCategory* top = categories_[type]; |
-void FreeList::RepairLists(Heap* heap) { |
- for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
- category_[i].RepairFreeList(heap); |
+ // Common double-linked list removal. |
+ if (top == category) { |
+ categories_[type] = category->next(); |
+ } |
+ if (category->prev() != nullptr) { |
+ category->prev()->set_next(category->next()); |
+ } |
+ if (category->next() != nullptr) { |
+ category->next()->set_prev(category->prev()); |
+ } |
+ category->set_next(nullptr); |
+ category->set_prev(nullptr); |
+} |
+ |
+void FreeList::PrintCategories(FreeListCategoryType type) { |
+ FreeListCategoryIterator it(this, type); |
+ PrintF("FreeList[%p, top=%p, %d] ", this, categories_[type], type); |
+ while (it.HasNext()) { |
+ FreeListCategory* current = it.Next(); |
+ PrintF("%p -> ", current); |
} |
+ PrintF("null\n"); |
} |
@@ -2606,7 +2522,6 @@ intptr_t FreeListCategory::SumFreeList() { |
return sum; |
} |
- |
int FreeListCategory::FreeListLength() { |
int length = 0; |
FreeSpace* cur = top(); |
@@ -2618,16 +2533,13 @@ int FreeListCategory::FreeListLength() { |
return length; |
} |
- |
-bool FreeListCategory::IsVeryLong() { |
- return FreeListLength() == kVeryLongFreeList; |
-} |
- |
- |
bool FreeList::IsVeryLong() { |
+ int len = 0; |
for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
- if (category_[i].IsVeryLong()) { |
- return true; |
+ FreeListCategoryIterator it(this, static_cast<FreeListCategoryType>(i)); |
+ while (it.HasNext()) { |
+ len += it.Next()->FreeListLength(); |
+ if (len >= FreeListCategory::kVeryLongFreeList) return true; |
} |
} |
return false; |
@@ -2639,9 +2551,8 @@ bool FreeList::IsVeryLong() { |
// kVeryLongFreeList. |
intptr_t FreeList::SumFreeLists() { |
intptr_t sum = 0; |
- for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
- sum += category_[i].SumFreeList(); |
- } |
+ ForAllFreeListCategories( |
+ [&sum](FreeListCategory* category) { sum += category->SumFreeList(); }); |
return sum; |
} |
#endif |