[heap] Refactor and clean up FreeListCategory.
BUG= Review URL: https://codereview.chromium.org/1377723003 Cr-Commit-Position: refs/heads/master@{#31048}
This commit is contained in:
parent
2128d6c036
commit
1d998bd0a6
@ -2074,7 +2074,6 @@ intptr_t FreeListCategory::Concatenate(FreeListCategory* category) {
|
||||
category->end()->set_next(top());
|
||||
}
|
||||
set_top(category->top());
|
||||
base::NoBarrier_Store(&top_, category->top_);
|
||||
available_ += category->available();
|
||||
category->Reset();
|
||||
}
|
||||
@ -2083,9 +2082,9 @@ intptr_t FreeListCategory::Concatenate(FreeListCategory* category) {
|
||||
|
||||
|
||||
void FreeListCategory::Reset() {
|
||||
set_top(NULL);
|
||||
set_end(NULL);
|
||||
set_available(0);
|
||||
set_top(nullptr);
|
||||
set_end(nullptr);
|
||||
available_ = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -2160,6 +2159,55 @@ FreeSpace* FreeListCategory::PickNodeFromList(int size_in_bytes,
|
||||
}
|
||||
|
||||
|
||||
FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes,
|
||||
int* node_size) {
|
||||
FreeSpace* return_node = nullptr;
|
||||
FreeSpace* top_node = top();
|
||||
|
||||
for (FreeSpace** node_it = &top_node; *node_it != NULL;
|
||||
node_it = (*node_it)->next_address()) {
|
||||
FreeSpace* cur_node = *node_it;
|
||||
while (cur_node != NULL &&
|
||||
Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) {
|
||||
int size = cur_node->Size();
|
||||
available_ -= size;
|
||||
Page::FromAddress(cur_node->address())
|
||||
->add_available_in_free_list(type_, -size);
|
||||
cur_node = cur_node->next();
|
||||
}
|
||||
|
||||
// Update iterator.
|
||||
*node_it = cur_node;
|
||||
|
||||
if (cur_node == nullptr) {
|
||||
set_end(nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
int size = cur_node->Size();
|
||||
if (size >= size_in_bytes) {
|
||||
// Large enough node found. Unlink it from the list.
|
||||
return_node = cur_node;
|
||||
*node_it = cur_node->next();
|
||||
*node_size = size;
|
||||
available_ -= size;
|
||||
Page::FromAddress(return_node->address())
|
||||
->add_available_in_free_list(type_, -size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Top could've changed if we took the first node. Update top and end
|
||||
// accordingly.
|
||||
set_top(top_node);
|
||||
if (top() == nullptr) {
|
||||
set_end(nullptr);
|
||||
}
|
||||
|
||||
return return_node;
|
||||
}
|
||||
|
||||
|
||||
void FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes) {
|
||||
free_space->set_next(top());
|
||||
set_top(free_space);
|
||||
@ -2188,10 +2236,10 @@ FreeList::FreeList(PagedSpace* owner)
|
||||
: owner_(owner),
|
||||
heap_(owner->heap()),
|
||||
wasted_bytes_(0),
|
||||
small_list_(this),
|
||||
medium_list_(this),
|
||||
large_list_(this),
|
||||
huge_list_(this) {
|
||||
small_list_(this, kSmall),
|
||||
medium_list_(this, kMedium),
|
||||
large_list_(this, kLarge),
|
||||
huge_list_(this, kHuge) {
|
||||
Reset();
|
||||
}
|
||||
|
||||
@ -2302,44 +2350,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
|
||||
}
|
||||
}
|
||||
|
||||
int huge_list_available = huge_list_.available();
|
||||
FreeSpace* top_node = huge_list_.top();
|
||||
for (FreeSpace** cur = &top_node; *cur != NULL;
|
||||
cur = (*cur)->next_address()) {
|
||||
FreeSpace* cur_node = *cur;
|
||||
while (cur_node != NULL &&
|
||||
Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) {
|
||||
int size = cur_node->Size();
|
||||
huge_list_available -= size;
|
||||
page = Page::FromAddress(cur_node->address());
|
||||
page->add_available_in_huge_free_list(-size);
|
||||
cur_node = cur_node->next();
|
||||
}
|
||||
|
||||
*cur = cur_node;
|
||||
if (cur_node == NULL) {
|
||||
huge_list_.set_end(NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
int size = cur_node->Size();
|
||||
if (size >= size_in_bytes) {
|
||||
// Large enough node found. Unlink it from the list.
|
||||
node = *cur;
|
||||
*cur = node->next();
|
||||
*node_size = size;
|
||||
huge_list_available -= size;
|
||||
page = Page::FromAddress(node->address());
|
||||
page->add_available_in_huge_free_list(-size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
huge_list_.set_top(top_node);
|
||||
if (huge_list_.top() == NULL) {
|
||||
huge_list_.set_end(NULL);
|
||||
}
|
||||
huge_list_.set_available(huge_list_available);
|
||||
node = huge_list_.SearchForNodeInList(size_in_bytes, node_size);
|
||||
|
||||
if (node != NULL) {
|
||||
DCHECK(IsVeryLong() || available() == SumFreeLists());
|
||||
|
@ -752,6 +752,9 @@ class MemoryChunk {
|
||||
};
|
||||
|
||||
|
||||
enum FreeListCategoryType { kSmall, kMedium, kLarge, kHuge };
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// A page is a memory chunk of a size 1MB. Large object pages may be larger.
|
||||
//
|
||||
@ -853,6 +856,25 @@ class Page : public MemoryChunk {
|
||||
|
||||
#undef FRAGMENTATION_STATS_ACCESSORS
|
||||
|
||||
void add_available_in_free_list(FreeListCategoryType type, intptr_t bytes) {
|
||||
switch (type) {
|
||||
case kSmall:
|
||||
add_available_in_small_free_list(bytes);
|
||||
break;
|
||||
case kMedium:
|
||||
add_available_in_medium_free_list(bytes);
|
||||
break;
|
||||
case kLarge:
|
||||
add_available_in_large_free_list(bytes);
|
||||
break;
|
||||
case kHuge:
|
||||
add_available_in_huge_free_list(bytes);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void Print();
|
||||
#endif // DEBUG
|
||||
@ -1518,8 +1540,12 @@ class AllocationStats BASE_EMBEDDED {
|
||||
// the end element of the linked list of free memory blocks.
|
||||
class FreeListCategory {
|
||||
public:
|
||||
explicit FreeListCategory(FreeList* owner)
|
||||
: top_(0), end_(NULL), available_(0), owner_(owner) {}
|
||||
explicit FreeListCategory(FreeList* owner, FreeListCategoryType type)
|
||||
: type_(type),
|
||||
top_(nullptr),
|
||||
end_(nullptr),
|
||||
available_(0),
|
||||
owner_(owner) {}
|
||||
|
||||
intptr_t Concatenate(FreeListCategory* category);
|
||||
|
||||
@ -1527,45 +1553,52 @@ class FreeListCategory {
|
||||
|
||||
void Free(FreeSpace* node, int size_in_bytes);
|
||||
|
||||
// Pick a node from the list.
|
||||
FreeSpace* PickNodeFromList(int* node_size);
|
||||
|
||||
// Pick a node from the list and compare it against {size_in_bytes}. If the
|
||||
// node's size is greater or equal return the node and null otherwise.
|
||||
FreeSpace* PickNodeFromList(int size_in_bytes, int* node_size);
|
||||
|
||||
// Search for a node of size {size_in_bytes}.
|
||||
FreeSpace* SearchForNodeInList(int size_in_bytes, int* node_size);
|
||||
|
||||
intptr_t EvictFreeListItemsInList(Page* p);
|
||||
bool ContainsPageFreeListItemsInList(Page* p);
|
||||
|
||||
void RepairFreeList(Heap* heap);
|
||||
|
||||
FreeSpace* top() const {
|
||||
return reinterpret_cast<FreeSpace*>(base::NoBarrier_Load(&top_));
|
||||
}
|
||||
bool IsEmpty() { return top() == nullptr; }
|
||||
|
||||
void set_top(FreeSpace* top) {
|
||||
base::NoBarrier_Store(&top_, reinterpret_cast<base::AtomicWord>(top));
|
||||
}
|
||||
|
||||
FreeSpace* end() const { return end_; }
|
||||
void set_end(FreeSpace* end) { end_ = end; }
|
||||
|
||||
int* GetAvailableAddress() { return &available_; }
|
||||
FreeList* owner() { return owner_; }
|
||||
int available() const { return available_; }
|
||||
void set_available(int available) { available_ = available; }
|
||||
|
||||
bool IsEmpty() { return top() == 0; }
|
||||
|
||||
#ifdef DEBUG
|
||||
intptr_t SumFreeList();
|
||||
int FreeListLength();
|
||||
#endif
|
||||
|
||||
FreeList* owner() { return owner_; }
|
||||
|
||||
private:
|
||||
// top_ points to the top FreeSpace* in the free list category.
|
||||
base::AtomicWord top_;
|
||||
FreeSpace* top() { return top_.Value(); }
|
||||
void set_top(FreeSpace* top) { top_.SetValue(top); }
|
||||
|
||||
FreeSpace* end() const { return end_; }
|
||||
void set_end(FreeSpace* end) { end_ = end; }
|
||||
|
||||
// |type_|: The type of this free list category.
|
||||
FreeListCategoryType type_;
|
||||
|
||||
// |top_|: Points to the top FreeSpace* in the free list category.
|
||||
AtomicValue<FreeSpace*> top_;
|
||||
|
||||
// |end_|: Points to the end FreeSpace* in the free list category.
|
||||
FreeSpace* end_;
|
||||
// Total available bytes in all blocks of this free list category.
|
||||
|
||||
// |available_|: Total available bytes in all blocks of this free list
|
||||
// category.
|
||||
int available_;
|
||||
|
||||
// |owner_|: The owning free list of this category.
|
||||
FreeList* owner_;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user