Commit 604ef7bb authored by Darius Mercadier's avatar Darius Mercadier Committed by Commit Bot

[heap] Make FreeListCategory lighter (size-wise)

A recent CL (1762292 and 1765533) changed the FreeList strategy,
switching to one that uses 46 categories rather than the previous 6 we
had. This caused a reduction of V8's heap size by about 1-2% on
average. However, because FreeListCategory is 56 bytes, rather than 4
bytes as one might expect (2 bytes offset, 1 byte for the category
type, and 1 byte padding), the overall memory improvement is actually
lower than that.

For instance, when 256M memory is allocated,
    1000 pages * 46 freelists * 56 bytes = 2.5M overhead
(ie, 1% overhead)

Ideally, FreeListCategory should only by 4 bytes: 2 bytes for the
offset of the top() on the page, 1 byte for the category type, and
1 byte padding.


This CL reduces the size of FreeListCategory by 24 bytes by removing
some fields.

More work should be done to reduce the size even further:

  - Remove the available_ counter (this require maintaining byte count
    at the page level rather than in each FreeListCategory; and
    maintaining that counter is not trivial, but doable).

  - Use a 16 bits offset to store the top() rather than a pointer.

  - Get rid of prev_ and next_: this change is the most
    complicated. It requires storing the space's pages in order, such
    that when one page's freelist is empty, we move on to the next
    page in the space.

  - the type_ field might even be removable, since this information can
    be deduced from the FreeListCategory's position in the page's array
    or FreeListCategory.

Bug: v8:9329
Change-Id: I8fd72cfa31ca12ba0dbf10be3948a72caee15b57
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1773270
Commit-Queue: Darius Mercadier <dmercadier@google.com>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63448}
parent 74fc9048
...@@ -172,9 +172,7 @@ bool PagedSpace::Contains(Object o) { ...@@ -172,9 +172,7 @@ bool PagedSpace::Contains(Object o) {
void PagedSpace::UnlinkFreeListCategories(Page* page) { void PagedSpace::UnlinkFreeListCategories(Page* page) {
DCHECK_EQ(this, page->owner()); DCHECK_EQ(this, page->owner());
page->ForAllFreeListCategories([this](FreeListCategory* category) { page->ForAllFreeListCategories([this](FreeListCategory* category) {
DCHECK_EQ(free_list(), category->owner());
free_list()->RemoveCategory(category); free_list()->RemoveCategory(category);
category->set_free_list(nullptr);
}); });
} }
...@@ -182,9 +180,8 @@ size_t PagedSpace::RelinkFreeListCategories(Page* page) { ...@@ -182,9 +180,8 @@ size_t PagedSpace::RelinkFreeListCategories(Page* page) {
DCHECK_EQ(this, page->owner()); DCHECK_EQ(this, page->owner());
size_t added = 0; size_t added = 0;
page->ForAllFreeListCategories([this, &added](FreeListCategory* category) { page->ForAllFreeListCategories([this, &added](FreeListCategory* category) {
category->set_free_list(free_list());
added += category->available(); added += category->available();
category->Relink(); category->Relink(free_list());
}); });
DCHECK_IMPLIES(!page->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE), DCHECK_IMPLIES(!page->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE),
...@@ -315,17 +312,51 @@ MemoryChunk* OldGenerationMemoryChunkIterator::next() { ...@@ -315,17 +312,51 @@ MemoryChunk* OldGenerationMemoryChunkIterator::next() {
UNREACHABLE(); UNREACHABLE();
} }
FreeList* FreeListCategory::owner() { return free_list_; } bool FreeListCategory::is_linked(FreeList* owner) const {
bool FreeListCategory::is_linked() {
return prev_ != nullptr || next_ != nullptr || return prev_ != nullptr || next_ != nullptr ||
free_list_->categories_[type_] == this; owner->categories_[type_] == this;
} }
void FreeListCategory::UpdateCountersAfterAllocation(size_t allocation_size) { void FreeListCategory::UpdateCountersAfterAllocation(size_t allocation_size) {
available_ -= allocation_size; available_ -= allocation_size;
length_--; }
free_list_->DecreaseAvailableBytes(allocation_size);
Page* FreeList::GetPageForCategoryType(FreeListCategoryType type) {
FreeListCategory* category_top = top(type);
if (category_top != nullptr) {
DCHECK(!category_top->top().is_null());
return Page::FromHeapObject(category_top->top());
} else {
return nullptr;
}
}
Page* FreeListLegacy::GetPageForSize(size_t size_in_bytes) {
const int minimum_category =
static_cast<int>(SelectFreeListCategoryType(size_in_bytes));
Page* page = GetPageForCategoryType(kHuge);
if (!page && static_cast<int>(kLarge) >= minimum_category)
page = GetPageForCategoryType(kLarge);
if (!page && static_cast<int>(kMedium) >= minimum_category)
page = GetPageForCategoryType(kMedium);
if (!page && static_cast<int>(kSmall) >= minimum_category)
page = GetPageForCategoryType(kSmall);
if (!page && static_cast<int>(kTiny) >= minimum_category)
page = GetPageForCategoryType(kTiny);
if (!page && static_cast<int>(kTiniest) >= minimum_category)
page = GetPageForCategoryType(kTiniest);
return page;
}
Page* FreeListFastAlloc::GetPageForSize(size_t size_in_bytes) {
const int minimum_category =
static_cast<int>(SelectFreeListCategoryType(size_in_bytes));
Page* page = GetPageForCategoryType(kHuge);
if (!page && static_cast<int>(kLarge) >= minimum_category)
page = GetPageForCategoryType(kLarge);
if (!page && static_cast<int>(kMedium) >= minimum_category)
page = GetPageForCategoryType(kMedium);
return page;
} }
AllocationResult LocalAllocationBuffer::AllocateRawAligned( AllocationResult LocalAllocationBuffer::AllocateRawAligned(
......
...@@ -822,8 +822,7 @@ void Page::AllocateFreeListCategories() { ...@@ -822,8 +822,7 @@ void Page::AllocateFreeListCategories() {
categories_ = new FreeListCategory*[free_list()->number_of_categories()](); categories_ = new FreeListCategory*[free_list()->number_of_categories()]();
for (int i = kFirstCategory; i <= free_list()->last_category(); i++) { for (int i = kFirstCategory; i <= free_list()->last_category(); i++) {
DCHECK_NULL(categories_[i]); DCHECK_NULL(categories_[i]);
categories_[i] = new FreeListCategory( categories_[i] = new FreeListCategory();
reinterpret_cast<PagedSpace*>(owner())->free_list(), this);
} }
} }
...@@ -1664,8 +1663,9 @@ void PagedSpace::RefillFreeList() { ...@@ -1664,8 +1663,9 @@ void PagedSpace::RefillFreeList() {
// We regularly sweep NEVER_ALLOCATE_ON_PAGE pages. We drop the freelist // We regularly sweep NEVER_ALLOCATE_ON_PAGE pages. We drop the freelist
// entries here to make them unavailable for allocations. // entries here to make them unavailable for allocations.
if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) {
p->ForAllFreeListCategories( p->ForAllFreeListCategories([this](FreeListCategory* category) {
[](FreeListCategory* category) { category->Reset(); }); category->Reset(free_list());
});
} }
// Only during compaction pages can actually change ownership. This is // Only during compaction pages can actually change ownership. This is
// safe because there exists no other competing action on the page links // safe because there exists no other competing action on the page links
...@@ -1982,7 +1982,6 @@ void PagedSpace::ReleasePage(Page* page) { ...@@ -1982,7 +1982,6 @@ void PagedSpace::ReleasePage(Page* page) {
DCHECK_EQ(page->owner(), this); DCHECK_EQ(page->owner(), this);
free_list_->EvictFreeListItems(page); free_list_->EvictFreeListItems(page);
DCHECK(!free_list_->ContainsPageFreeListItems(page));
if (Page::FromAllocationAreaAddress(allocation_info_.top()) == page) { if (Page::FromAllocationAreaAddress(allocation_info_.top()) == page) {
DCHECK(!top_on_previous_step_); DCHECK(!top_on_previous_step_);
...@@ -2967,23 +2966,21 @@ size_t NewSpace::CommittedPhysicalMemory() { ...@@ -2967,23 +2966,21 @@ size_t NewSpace::CommittedPhysicalMemory() {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Free lists for old object spaces implementation // Free lists for old object spaces implementation
void FreeListCategory::Reset(FreeList* owner) {
void FreeListCategory::Reset() { if (is_linked(owner) && !top().is_null()) {
if (is_linked() && !top().is_null()) { owner->DecreaseAvailableBytes(available_);
owner()->DecreaseAvailableBytes(available_);
} }
set_top(FreeSpace()); set_top(FreeSpace());
set_prev(nullptr); set_prev(nullptr);
set_next(nullptr); set_next(nullptr);
available_ = 0; available_ = 0;
length_ = 0;
} }
FreeSpace FreeListCategory::PickNodeFromList(size_t minimum_size, FreeSpace FreeListCategory::PickNodeFromList(size_t minimum_size,
size_t* node_size) { size_t* node_size) {
DCHECK(page()->CanAllocate());
FreeSpace node = top(); FreeSpace node = top();
DCHECK(!node.is_null()); DCHECK(!node.is_null());
DCHECK(Page::FromHeapObject(node)->CanAllocate());
if (static_cast<size_t>(node.Size()) < minimum_size) { if (static_cast<size_t>(node.Size()) < minimum_size) {
*node_size = 0; *node_size = 0;
return FreeSpace(); return FreeSpace();
...@@ -2996,10 +2993,10 @@ FreeSpace FreeListCategory::PickNodeFromList(size_t minimum_size, ...@@ -2996,10 +2993,10 @@ FreeSpace FreeListCategory::PickNodeFromList(size_t minimum_size,
FreeSpace FreeListCategory::SearchForNodeInList(size_t minimum_size, FreeSpace FreeListCategory::SearchForNodeInList(size_t minimum_size,
size_t* node_size) { size_t* node_size) {
DCHECK(page()->CanAllocate());
FreeSpace prev_non_evac_node; FreeSpace prev_non_evac_node;
for (FreeSpace cur_node = top(); !cur_node.is_null(); for (FreeSpace cur_node = top(); !cur_node.is_null();
cur_node = cur_node.next()) { cur_node = cur_node.next()) {
DCHECK(Page::FromHeapObject(cur_node)->CanAllocate());
size_t size = cur_node.size(); size_t size = cur_node.size();
if (size >= minimum_size) { if (size >= minimum_size) {
DCHECK_GE(available_, size); DCHECK_GE(available_, size);
...@@ -3023,23 +3020,21 @@ FreeSpace FreeListCategory::SearchForNodeInList(size_t minimum_size, ...@@ -3023,23 +3020,21 @@ FreeSpace FreeListCategory::SearchForNodeInList(size_t minimum_size,
return FreeSpace(); return FreeSpace();
} }
void FreeListCategory::Free(Address start, size_t size_in_bytes, void FreeListCategory::Free(Address start, size_t size_in_bytes, FreeMode mode,
FreeMode mode) { FreeList* owner) {
FreeSpace free_space = FreeSpace::cast(HeapObject::FromAddress(start)); FreeSpace free_space = FreeSpace::cast(HeapObject::FromAddress(start));
free_space.set_next(top()); free_space.set_next(top());
set_top(free_space); set_top(free_space);
available_ += size_in_bytes; available_ += size_in_bytes;
length_++;
if (mode == kLinkCategory) { if (mode == kLinkCategory) {
if (is_linked()) { if (is_linked(owner)) {
owner()->IncreaseAvailableBytes(size_in_bytes); owner->IncreaseAvailableBytes(size_in_bytes);
} else { } else {
owner()->AddCategory(this); owner->AddCategory(this);
} }
} }
} }
void FreeListCategory::RepairFreeList(Heap* heap) { void FreeListCategory::RepairFreeList(Heap* heap) {
Map free_space_map = ReadOnlyRoots(heap).free_space_map(); Map free_space_map = ReadOnlyRoots(heap).free_space_map();
FreeSpace n = top(); FreeSpace n = top();
...@@ -3054,9 +3049,9 @@ void FreeListCategory::RepairFreeList(Heap* heap) { ...@@ -3054,9 +3049,9 @@ void FreeListCategory::RepairFreeList(Heap* heap) {
} }
} }
void FreeListCategory::Relink() { void FreeListCategory::Relink(FreeList* owner) {
DCHECK(!is_linked()); DCHECK(!is_linked(owner));
owner()->AddCategory(this); owner->AddCategory(this);
} }
// ------------------------------------------------ // ------------------------------------------------
...@@ -3087,6 +3082,7 @@ FreeSpace FreeList::TryFindNodeIn(FreeListCategoryType type, ...@@ -3087,6 +3082,7 @@ FreeSpace FreeList::TryFindNodeIn(FreeListCategoryType type,
if (category == nullptr) return FreeSpace(); if (category == nullptr) return FreeSpace();
FreeSpace node = category->PickNodeFromList(minimum_size, node_size); FreeSpace node = category->PickNodeFromList(minimum_size, node_size);
if (!node.is_null()) { if (!node.is_null()) {
DecreaseAvailableBytes(*node_size);
DCHECK(IsVeryLong() || Available() == SumFreeLists()); DCHECK(IsVeryLong() || Available() == SumFreeLists());
} }
if (category->is_empty()) { if (category->is_empty()) {
...@@ -3104,6 +3100,7 @@ FreeSpace FreeList::SearchForNodeInList(FreeListCategoryType type, ...@@ -3104,6 +3100,7 @@ FreeSpace FreeList::SearchForNodeInList(FreeListCategoryType type,
FreeListCategory* current = it.Next(); FreeListCategory* current = it.Next();
node = current->SearchForNodeInList(minimum_size, node_size); node = current->SearchForNodeInList(minimum_size, node_size);
if (!node.is_null()) { if (!node.is_null()) {
DecreaseAvailableBytes(*node_size);
DCHECK(IsVeryLong() || Available() == SumFreeLists()); DCHECK(IsVeryLong() || Available() == SumFreeLists());
if (current->is_empty()) { if (current->is_empty()) {
RemoveCategory(current); RemoveCategory(current);
...@@ -3128,7 +3125,7 @@ size_t FreeList::Free(Address start, size_t size_in_bytes, FreeMode mode) { ...@@ -3128,7 +3125,7 @@ size_t FreeList::Free(Address start, size_t size_in_bytes, FreeMode mode) {
// 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.
FreeListCategoryType type = SelectFreeListCategoryType(size_in_bytes); FreeListCategoryType type = SelectFreeListCategoryType(size_in_bytes);
page->free_list_category(type)->Free(start, size_in_bytes, mode); page->free_list_category(type)->Free(start, size_in_bytes, mode, this);
DCHECK_EQ(page->AvailableInFreeList(), DCHECK_EQ(page->AvailableInFreeList(),
page->AvailableInFreeListFromAllocatedBytes()); page->AvailableInFreeListFromAllocatedBytes());
return 0; return 0;
...@@ -3348,7 +3345,7 @@ size_t FreeListManyCached::Free(Address start, size_t size_in_bytes, ...@@ -3348,7 +3345,7 @@ size_t FreeListManyCached::Free(Address start, size_t 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.
FreeListCategoryType type = SelectFreeListCategoryType(size_in_bytes); FreeListCategoryType type = SelectFreeListCategoryType(size_in_bytes);
page->free_list_category(type)->Free(start, size_in_bytes, mode); page->free_list_category(type)->Free(start, size_in_bytes, mode, this);
// Updating cache // Updating cache
if (mode == kLinkCategory) { if (mode == kLinkCategory) {
...@@ -3529,7 +3526,7 @@ FreeSpace FreeListMap::Allocate(size_t size_in_bytes, size_t* node_size, ...@@ -3529,7 +3526,7 @@ FreeSpace FreeListMap::Allocate(size_t size_in_bytes, size_t* node_size,
void FreeList::Reset() { void FreeList::Reset() {
ForAllFreeListCategories( ForAllFreeListCategories(
[](FreeListCategory* category) { category->Reset(); }); [this](FreeListCategory* category) { category->Reset(this); });
for (int i = kFirstCategory; i < number_of_categories_; i++) { for (int i = kFirstCategory; i < number_of_categories_; i++) {
categories_[i] = nullptr; categories_[i] = nullptr;
} }
...@@ -3540,25 +3537,13 @@ void FreeList::Reset() { ...@@ -3540,25 +3537,13 @@ void FreeList::Reset() {
size_t FreeList::EvictFreeListItems(Page* page) { size_t FreeList::EvictFreeListItems(Page* page) {
size_t sum = 0; size_t sum = 0;
page->ForAllFreeListCategories([this, &sum](FreeListCategory* category) { page->ForAllFreeListCategories([this, &sum](FreeListCategory* category) {
DCHECK_EQ(this, category->owner());
sum += category->available(); sum += category->available();
RemoveCategory(category); RemoveCategory(category);
category->Reset(); category->Reset(this);
}); });
return sum; 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;
}
void FreeList::RepairLists(Heap* heap) { void FreeList::RepairLists(Heap* heap) {
ForAllFreeListCategories( ForAllFreeListCategories(
[heap](FreeListCategory* category) { category->RepairFreeList(heap); }); [heap](FreeListCategory* category) { category->RepairFreeList(heap); });
...@@ -3588,7 +3573,7 @@ void FreeList::RemoveCategory(FreeListCategory* category) { ...@@ -3588,7 +3573,7 @@ void FreeList::RemoveCategory(FreeListCategory* category) {
DCHECK_LT(type, number_of_categories_); DCHECK_LT(type, number_of_categories_);
FreeListCategory* top = categories_[type]; FreeListCategory* top = categories_[type];
if (category->is_linked()) { if (category->is_linked(this)) {
DecreaseAvailableBytes(category->available()); DecreaseAvailableBytes(category->available());
} }
...@@ -3633,13 +3618,25 @@ size_t FreeListCategory::SumFreeList() { ...@@ -3633,13 +3618,25 @@ size_t FreeListCategory::SumFreeList() {
while (!cur.is_null()) { while (!cur.is_null()) {
// We can't use "cur->map()" here because both cur's map and the // We can't use "cur->map()" here because both cur's map and the
// root can be null during bootstrapping. // root can be null during bootstrapping.
DCHECK(cur.map_slot().contains_value( DCHECK(cur.map_slot().contains_value(Page::FromHeapObject(cur)
page()->heap()->isolate()->root(RootIndex::kFreeSpaceMap).ptr())); ->heap()
->isolate()
->root(RootIndex::kFreeSpaceMap)
.ptr()));
sum += cur.relaxed_read_size(); sum += cur.relaxed_read_size();
cur = cur.next(); cur = cur.next();
} }
return sum; return sum;
} }
int FreeListCategory::FreeListLength() {
int length = 0;
FreeSpace cur = top();
while (!cur.is_null()) {
length++;
cur = cur.next();
}
return length;
}
#ifdef DEBUG #ifdef DEBUG
bool FreeList::IsVeryLong() { bool FreeList::IsVeryLong() {
......
...@@ -121,7 +121,7 @@ class Space; ...@@ -121,7 +121,7 @@ class Space;
#define DCHECK_CODEOBJECT_SIZE(size, code_space) \ #define DCHECK_CODEOBJECT_SIZE(size, code_space) \
DCHECK((0 < size) && (size <= code_space->AreaSize())) DCHECK((0 < size) && (size <= code_space->AreaSize()))
using FreeListCategoryType = int; using FreeListCategoryType = int32_t;
static const FreeListCategoryType kFirstCategory = 0; static const FreeListCategoryType kFirstCategory = 0;
static const FreeListCategoryType kInvalidCategory = -1; static const FreeListCategoryType kInvalidCategory = -1;
...@@ -139,32 +139,23 @@ enum RememberedSetType { ...@@ -139,32 +139,23 @@ enum RememberedSetType {
// 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:
FreeListCategory(FreeList* free_list, Page* page)
: free_list_(free_list),
page_(page),
type_(kInvalidCategory),
available_(0),
length_(0),
prev_(nullptr),
next_(nullptr) {}
void Initialize(FreeListCategoryType type) { void Initialize(FreeListCategoryType type) {
type_ = type; type_ = type;
available_ = 0; available_ = 0;
length_ = 0;
prev_ = nullptr; prev_ = nullptr;
next_ = nullptr; next_ = nullptr;
} }
void Reset(); void Reset(FreeList* owner);
void RepairFreeList(Heap* heap); void RepairFreeList(Heap* heap);
// Relinks the category into the currently owning free list. Requires that the // Relinks the category into the currently owning free list. Requires that the
// category is currently unlinked. // category is currently unlinked.
void Relink(); void Relink(FreeList* owner);
void Free(Address address, size_t size_in_bytes, FreeMode mode); void Free(Address address, size_t size_in_bytes, FreeMode mode,
FreeList* owner);
// Performs a single try to pick a node of at least |minimum_size| from the // Performs a single try to pick a node of at least |minimum_size| from the
// category. Stores the actual size in |node_size|. Returns nullptr if no // category. Stores the actual size in |node_size|. Returns nullptr if no
...@@ -175,16 +166,12 @@ class FreeListCategory { ...@@ -175,16 +166,12 @@ class FreeListCategory {
// actual size in |node_size|. Returns nullptr if no node is found. // actual size in |node_size|. Returns nullptr if no node is found.
FreeSpace SearchForNodeInList(size_t minimum_size, size_t* node_size); FreeSpace SearchForNodeInList(size_t minimum_size, size_t* node_size);
inline FreeList* owner(); inline bool is_linked(FreeList* owner) const;
inline Page* page() const { return page_; }
inline bool is_linked();
bool is_empty() { return top().is_null(); } bool is_empty() { return top().is_null(); }
size_t available() const { return available_; } uint32_t available() const { return available_; }
void set_free_list(FreeList* free_list) { free_list_ = free_list; }
size_t SumFreeList(); size_t SumFreeList();
int FreeListLength() { return length_; } int FreeListLength();
private: private:
// For debug builds we accurately compute free lists lengths up until // For debug builds we accurately compute free lists lengths up until
...@@ -202,34 +189,23 @@ class FreeListCategory { ...@@ -202,34 +189,23 @@ class FreeListCategory {
FreeListCategory* next() { return next_; } FreeListCategory* next() { return next_; }
void set_next(FreeListCategory* next) { next_ = next; } void set_next(FreeListCategory* next) { next_ = next; }
// This FreeListCategory is owned by the given free_list_.
FreeList* free_list_;
// This FreeListCategory holds free list entries of the given page_.
Page* const page_;
// |type_|: The type of this free list category. // |type_|: The type of this free list category.
FreeListCategoryType type_; FreeListCategoryType type_ = kInvalidCategory;
// |available_|: Total available bytes in all blocks of this free list // |available_|: Total available bytes in all blocks of this free list
// category. // category.
size_t available_; uint32_t available_ = 0;
// |length_|: Total blocks in this free list category.
int length_;
// |top_|: Points to the top FreeSpace in the free list category. // |top_|: Points to the top FreeSpace in the free list category.
FreeSpace top_; FreeSpace top_;
FreeListCategory* prev_; FreeListCategory* prev_ = nullptr;
FreeListCategory* next_; FreeListCategory* next_ = nullptr;
friend class FreeList; friend class FreeList;
friend class FreeListManyCached; friend class FreeListManyCached;
friend class PagedSpace; friend class PagedSpace;
friend class MapSpace; friend class MapSpace;
DISALLOW_IMPLICIT_CONSTRUCTORS(FreeListCategory);
}; };
// A free list maintains free blocks of memory. The free list is organized in // A free list maintains free blocks of memory. The free list is organized in
...@@ -293,7 +269,6 @@ class FreeList { ...@@ -293,7 +269,6 @@ class FreeList {
void RepairLists(Heap* heap); void RepairLists(Heap* heap);
V8_EXPORT_PRIVATE size_t EvictFreeListItems(Page* page); V8_EXPORT_PRIVATE size_t EvictFreeListItems(Page* page);
bool ContainsPageFreeListItems(Page* page);
int number_of_categories() { return number_of_categories_; } int number_of_categories() { return number_of_categories_; }
FreeListCategoryType last_category() { return last_category_; } FreeListCategoryType last_category() { return last_category_; }
...@@ -364,9 +339,7 @@ class FreeList { ...@@ -364,9 +339,7 @@ class FreeList {
return categories_[type]; return categories_[type];
} }
Page* GetPageForCategoryType(FreeListCategoryType type) { inline Page* GetPageForCategoryType(FreeListCategoryType type);
return top(type) ? top(type)->page() : nullptr;
}
int number_of_categories_ = 0; int number_of_categories_ = 0;
FreeListCategoryType last_category_ = 0; FreeListCategoryType last_category_ = 0;
...@@ -1829,22 +1802,7 @@ class V8_EXPORT_PRIVATE FreeListLegacy : public FreeList { ...@@ -1829,22 +1802,7 @@ class V8_EXPORT_PRIVATE FreeListLegacy : public FreeList {
return maximum_freed; return maximum_freed;
} }
Page* GetPageForSize(size_t size_in_bytes) override { inline Page* GetPageForSize(size_t size_in_bytes) override;
const int minimum_category =
static_cast<int>(SelectFreeListCategoryType(size_in_bytes));
Page* page = GetPageForCategoryType(kHuge);
if (!page && static_cast<int>(kLarge) >= minimum_category)
page = GetPageForCategoryType(kLarge);
if (!page && static_cast<int>(kMedium) >= minimum_category)
page = GetPageForCategoryType(kMedium);
if (!page && static_cast<int>(kSmall) >= minimum_category)
page = GetPageForCategoryType(kSmall);
if (!page && static_cast<int>(kTiny) >= minimum_category)
page = GetPageForCategoryType(kTiny);
if (!page && static_cast<int>(kTiniest) >= minimum_category)
page = GetPageForCategoryType(kTiniest);
return page;
}
FreeListLegacy(); FreeListLegacy();
~FreeListLegacy(); ~FreeListLegacy();
...@@ -1928,16 +1886,7 @@ class V8_EXPORT_PRIVATE FreeListFastAlloc : public FreeList { ...@@ -1928,16 +1886,7 @@ class V8_EXPORT_PRIVATE FreeListFastAlloc : public FreeList {
return kHugeAllocationMax; return kHugeAllocationMax;
} }
Page* GetPageForSize(size_t size_in_bytes) override { inline Page* GetPageForSize(size_t size_in_bytes) override;
const int minimum_category =
static_cast<int>(SelectFreeListCategoryType(size_in_bytes));
Page* page = GetPageForCategoryType(kHuge);
if (!page && static_cast<int>(kLarge) >= minimum_category)
page = GetPageForCategoryType(kLarge);
if (!page && static_cast<int>(kMedium) >= minimum_category)
page = GetPageForCategoryType(kMedium);
return page;
}
FreeListFastAlloc(); FreeListFastAlloc();
~FreeListFastAlloc(); ~FreeListFastAlloc();
...@@ -1971,10 +1920,6 @@ class V8_EXPORT_PRIVATE FreeListFastAlloc : public FreeList { ...@@ -1971,10 +1920,6 @@ class V8_EXPORT_PRIVATE FreeListFastAlloc : public FreeList {
} }
return kHuge; return kHuge;
} }
Page* GetPageForCategoryType(FreeListCategoryType type) {
return top(type) ? top(type)->page() : nullptr;
}
}; };
// Use 47 Freelists: on per size between 24 and 256, and then a few ones for // Use 47 Freelists: on per size between 24 and 256, and then a few ones for
......
...@@ -509,11 +509,14 @@ void Sweeper::AddPage(AllocationSpace space, Page* page, ...@@ -509,11 +509,14 @@ void Sweeper::AddPage(AllocationSpace space, Page* page,
} }
void Sweeper::PrepareToBeSweptPage(AllocationSpace space, Page* page) { void Sweeper::PrepareToBeSweptPage(AllocationSpace space, Page* page) {
#ifdef DEBUG
DCHECK_GE(page->area_size(), DCHECK_GE(page->area_size(),
static_cast<size_t>(marking_state_->live_bytes(page))); static_cast<size_t>(marking_state_->live_bytes(page)));
DCHECK_EQ(Page::kSweepingDone, page->concurrent_sweeping_state()); DCHECK_EQ(Page::kSweepingDone, page->concurrent_sweeping_state());
page->ForAllFreeListCategories( page->ForAllFreeListCategories([page](FreeListCategory* category) {
[](FreeListCategory* category) { DCHECK(!category->is_linked()); }); DCHECK(!category->is_linked(page->owner()->free_list()));
});
#endif // DEBUG
page->set_concurrent_sweeping_state(Page::kSweepingPending); page->set_concurrent_sweeping_state(Page::kSweepingPending);
heap_->paged_space(space)->IncreaseAllocatedBytes( heap_->paged_space(space)->IncreaseAllocatedBytes(
marking_state_->live_bytes(page), page); marking_state_->live_bytes(page), page);
......
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