Commit b6a86e77 authored by hpayer's avatar hpayer Committed by Commit bot

[heap] Refactor FreeListCategory.

BUG=chromium:587026
LOG=n

Review URL: https://codereview.chromium.org/1698983002

Cr-Commit-Position: refs/heads/master@{#34021}
parent aa31ff31
...@@ -2309,14 +2309,10 @@ void FreeListCategory::RepairFreeList(Heap* heap) { ...@@ -2309,14 +2309,10 @@ void FreeListCategory::RepairFreeList(Heap* heap) {
} }
} }
FreeList::FreeList(PagedSpace* owner) : owner_(owner), wasted_bytes_(0) {
FreeList::FreeList(PagedSpace* owner) for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
: owner_(owner), category_[i].Initialize(this, static_cast<FreeListCategoryType>(i));
wasted_bytes_(0), }
small_list_(this, kSmall),
medium_list_(this, kMedium),
large_list_(this, kLarge),
huge_list_(this, kHuge) {
Reset(); Reset();
} }
...@@ -2336,10 +2332,10 @@ intptr_t FreeList::Concatenate(FreeList* other) { ...@@ -2336,10 +2332,10 @@ intptr_t FreeList::Concatenate(FreeList* other) {
wasted_bytes_ += wasted_bytes; wasted_bytes_ += wasted_bytes;
other->wasted_bytes_ = 0; other->wasted_bytes_ = 0;
usable_bytes += small_list_.Concatenate(other->GetFreeListCategory(kSmall)); for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
usable_bytes += medium_list_.Concatenate(other->GetFreeListCategory(kMedium)); usable_bytes += category_[i].Concatenate(
usable_bytes += large_list_.Concatenate(other->GetFreeListCategory(kLarge)); other->GetFreeListCategory(static_cast<FreeListCategoryType>(i)));
usable_bytes += huge_list_.Concatenate(other->GetFreeListCategory(kHuge)); }
if (!other->owner()->is_local()) other->mutex()->Unlock(); if (!other->owner()->is_local()) other->mutex()->Unlock();
if (!owner()->is_local()) mutex_.Unlock(); if (!owner()->is_local()) mutex_.Unlock();
...@@ -2348,10 +2344,9 @@ intptr_t FreeList::Concatenate(FreeList* other) { ...@@ -2348,10 +2344,9 @@ intptr_t FreeList::Concatenate(FreeList* other) {
void FreeList::Reset() { void FreeList::Reset() {
small_list_.Reset(); for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
medium_list_.Reset(); category_[i].Reset();
large_list_.Reset(); }
huge_list_.Reset();
ResetStats(); ResetStats();
} }
...@@ -2374,16 +2369,16 @@ int FreeList::Free(Address start, int size_in_bytes) { ...@@ -2374,16 +2369,16 @@ int FreeList::Free(Address start, int size_in_bytes) {
// Insert other blocks at the head of a free list of the appropriate // Insert other blocks at the head of a free list of the appropriate
// magnitude. // magnitude.
if (size_in_bytes <= kSmallListMax) { if (size_in_bytes <= kSmallListMax) {
small_list_.Free(free_space, size_in_bytes); category_[kSmall].Free(free_space, size_in_bytes);
page->add_available_in_small_free_list(size_in_bytes); page->add_available_in_small_free_list(size_in_bytes);
} else if (size_in_bytes <= kMediumListMax) { } else if (size_in_bytes <= kMediumListMax) {
medium_list_.Free(free_space, size_in_bytes); category_[kMedium].Free(free_space, size_in_bytes);
page->add_available_in_medium_free_list(size_in_bytes); page->add_available_in_medium_free_list(size_in_bytes);
} else if (size_in_bytes <= kLargeListMax) { } else if (size_in_bytes <= kLargeListMax) {
large_list_.Free(free_space, size_in_bytes); category_[kLarge].Free(free_space, size_in_bytes);
page->add_available_in_large_free_list(size_in_bytes); page->add_available_in_large_free_list(size_in_bytes);
} else { } else {
huge_list_.Free(free_space, size_in_bytes); category_[kHuge].Free(free_space, size_in_bytes);
page->add_available_in_huge_free_list(size_in_bytes); page->add_available_in_huge_free_list(size_in_bytes);
} }
...@@ -2422,7 +2417,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { ...@@ -2422,7 +2417,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
if (node != nullptr) return node; if (node != nullptr) return node;
} }
node = huge_list_.SearchForNodeInList(size_in_bytes, node_size); node = category_[kHuge].SearchForNodeInList(size_in_bytes, node_size);
if (node != nullptr) { if (node != nullptr) {
page = Page::FromAddress(node->address()); page = Page::FromAddress(node->address());
page->add_available_in_large_free_list(-(*node_size)); page->add_available_in_large_free_list(-(*node_size));
...@@ -2431,21 +2426,21 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { ...@@ -2431,21 +2426,21 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
} }
if (size_in_bytes <= kSmallListMax) { if (size_in_bytes <= kSmallListMax) {
node = small_list_.PickNodeFromList(size_in_bytes, node_size); node = category_[kSmall].PickNodeFromList(size_in_bytes, node_size);
if (node != NULL) { if (node != NULL) {
DCHECK(size_in_bytes <= *node_size); DCHECK(size_in_bytes <= *node_size);
page = Page::FromAddress(node->address()); page = Page::FromAddress(node->address());
page->add_available_in_small_free_list(-(*node_size)); page->add_available_in_small_free_list(-(*node_size));
} }
} else if (size_in_bytes <= kMediumListMax) { } else if (size_in_bytes <= kMediumListMax) {
node = medium_list_.PickNodeFromList(size_in_bytes, node_size); node = category_[kMedium].PickNodeFromList(size_in_bytes, node_size);
if (node != NULL) { if (node != NULL) {
DCHECK(size_in_bytes <= *node_size); DCHECK(size_in_bytes <= *node_size);
page = Page::FromAddress(node->address()); page = Page::FromAddress(node->address());
page->add_available_in_medium_free_list(-(*node_size)); page->add_available_in_medium_free_list(-(*node_size));
} }
} else if (size_in_bytes <= kLargeListMax) { } else if (size_in_bytes <= kLargeListMax) {
node = large_list_.PickNodeFromList(size_in_bytes, node_size); node = category_[kLarge].PickNodeFromList(size_in_bytes, node_size);
if (node != NULL) { if (node != NULL) {
DCHECK(size_in_bytes <= *node_size); DCHECK(size_in_bytes <= *node_size);
page = Page::FromAddress(node->address()); page = Page::FromAddress(node->address());
...@@ -2564,29 +2559,30 @@ HeapObject* FreeList::Allocate(int size_in_bytes) { ...@@ -2564,29 +2559,30 @@ HeapObject* FreeList::Allocate(int size_in_bytes) {
intptr_t FreeList::EvictFreeListItems(Page* p) { intptr_t FreeList::EvictFreeListItems(Page* p) {
intptr_t sum = huge_list_.EvictFreeListItemsInList(p); intptr_t sum = category_[kHuge].EvictFreeListItemsInList(p);
if (sum < p->area_size()) { if (sum < p->area_size()) {
sum += small_list_.EvictFreeListItemsInList(p) + for (int i = kFirstCategory; i <= kLarge; i++) {
medium_list_.EvictFreeListItemsInList(p) + sum += category_[i].EvictFreeListItemsInList(p);
large_list_.EvictFreeListItemsInList(p); }
} }
return sum; return sum;
} }
bool FreeList::ContainsPageFreeListItems(Page* p) { bool FreeList::ContainsPageFreeListItems(Page* p) {
return huge_list_.EvictFreeListItemsInList(p) || for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
small_list_.EvictFreeListItemsInList(p) || if (category_[i].EvictFreeListItemsInList(p)) {
medium_list_.EvictFreeListItemsInList(p) || return true;
large_list_.EvictFreeListItemsInList(p); }
}
return false;
} }
void FreeList::RepairLists(Heap* heap) { void FreeList::RepairLists(Heap* heap) {
small_list_.RepairFreeList(heap); for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
medium_list_.RepairFreeList(heap); category_[i].RepairFreeList(heap);
large_list_.RepairFreeList(heap); }
huge_list_.RepairFreeList(heap);
} }
...@@ -2621,8 +2617,12 @@ bool FreeListCategory::IsVeryLong() { ...@@ -2621,8 +2617,12 @@ bool FreeListCategory::IsVeryLong() {
bool FreeList::IsVeryLong() { bool FreeList::IsVeryLong() {
return small_list_.IsVeryLong() || medium_list_.IsVeryLong() || for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
large_list_.IsVeryLong() || huge_list_.IsVeryLong(); if (category_[i].IsVeryLong()) {
return true;
}
}
return false;
} }
...@@ -2630,10 +2630,10 @@ bool FreeList::IsVeryLong() { ...@@ -2630,10 +2630,10 @@ bool FreeList::IsVeryLong() {
// on the free list, so it should not be called if FreeListLength returns // on the free list, so it should not be called if FreeListLength returns
// kVeryLongFreeList. // kVeryLongFreeList.
intptr_t FreeList::SumFreeLists() { intptr_t FreeList::SumFreeLists() {
intptr_t sum = small_list_.SumFreeList(); intptr_t sum = 0;
sum += medium_list_.SumFreeList(); for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
sum += large_list_.SumFreeList(); sum += category_[i].SumFreeList();
sum += huge_list_.SumFreeList(); }
return sum; return sum;
} }
#endif #endif
......
...@@ -717,9 +717,16 @@ class MemoryChunk { ...@@ -717,9 +717,16 @@ class MemoryChunk {
friend class MemoryChunkValidator; friend class MemoryChunkValidator;
}; };
enum FreeListCategoryType {
enum FreeListCategoryType { kSmall, kMedium, kLarge, kHuge }; kSmall,
kMedium,
kLarge,
kHuge,
kFirstCategory = kSmall,
kLastCategory = kHuge,
kNumberOfCategories = kLastCategory + 1
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// A page is a memory chunk of a size 1MB. Large object pages may be larger. // A page is a memory chunk of a size 1MB. Large object pages may be larger.
...@@ -1590,12 +1597,12 @@ class AllocationStats BASE_EMBEDDED { ...@@ -1590,12 +1597,12 @@ class AllocationStats BASE_EMBEDDED {
// A free list category maintains a linked list of free memory blocks. // A free list category maintains a linked list of free memory blocks.
class FreeListCategory { class FreeListCategory {
public: public:
explicit FreeListCategory(FreeList* owner, FreeListCategoryType type) FreeListCategory() : top_(nullptr), end_(nullptr), available_(0) {}
: type_(type),
top_(nullptr), void Initialize(FreeList* owner, FreeListCategoryType type) {
end_(nullptr), owner_ = owner;
available_(0), type_ = type;
owner_(owner) {} }
// Concatenates {category} into {this}. // Concatenates {category} into {this}.
// //
...@@ -1725,8 +1732,11 @@ class FreeList { ...@@ -1725,8 +1732,11 @@ class FreeList {
// Return the number of bytes available on the free list. // Return the number of bytes available on the free list.
intptr_t Available() { intptr_t Available() {
return small_list_.available() + medium_list_.available() + intptr_t available = 0;
large_list_.available() + huge_list_.available(); for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
available += category_[i].available();
}
return available;
} }
// The method tries to find a {FreeSpace} node of at least {size_in_bytes} // The method tries to find a {FreeSpace} node of at least {size_in_bytes}
...@@ -1738,8 +1748,10 @@ class FreeList { ...@@ -1738,8 +1748,10 @@ class FreeList {
MUST_USE_RESULT FreeSpace* TryRemoveMemory(intptr_t hint_size_in_bytes); MUST_USE_RESULT FreeSpace* TryRemoveMemory(intptr_t hint_size_in_bytes);
bool IsEmpty() { bool IsEmpty() {
return small_list_.IsEmpty() && medium_list_.IsEmpty() && for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
large_list_.IsEmpty() && huge_list_.IsEmpty(); if (!category_[i].IsEmpty()) return false;
}
return true;
} }
// Used after booting the VM. // Used after booting the VM.
...@@ -1775,29 +1787,13 @@ class FreeList { ...@@ -1775,29 +1787,13 @@ class FreeList {
FreeSpace* FindNodeIn(FreeListCategoryType category, int* node_size); FreeSpace* FindNodeIn(FreeListCategoryType category, int* node_size);
FreeListCategory* GetFreeListCategory(FreeListCategoryType category) { FreeListCategory* GetFreeListCategory(FreeListCategoryType category) {
switch (category) { return &category_[category];
case kSmall:
return &small_list_;
case kMedium:
return &medium_list_;
case kLarge:
return &large_list_;
case kHuge:
return &huge_list_;
default:
UNREACHABLE();
}
UNREACHABLE();
return nullptr;
} }
PagedSpace* owner_; PagedSpace* owner_;
base::Mutex mutex_; base::Mutex mutex_;
intptr_t wasted_bytes_; intptr_t wasted_bytes_;
FreeListCategory small_list_; FreeListCategory category_[kNumberOfCategories];
FreeListCategory medium_list_;
FreeListCategory large_list_;
FreeListCategory huge_list_;
DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList); DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList);
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment