Commit 10019c2b authored by mlippautz's avatar mlippautz Committed by Commit bot

[heap] Cleanup: Enforce coding style in FreeList and FreeListCategory

Also update comments.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#31301}
parent 23a8837f
......@@ -2237,7 +2237,6 @@ void FreeListCategory::RepairFreeList(Heap* heap) {
FreeList::FreeList(PagedSpace* owner)
: owner_(owner),
heap_(owner->heap()),
wasted_bytes_(0),
small_list_(this, kSmall),
medium_list_(this, kMedium),
......@@ -2285,7 +2284,7 @@ void FreeList::Reset() {
int FreeList::Free(Address start, int size_in_bytes) {
if (size_in_bytes == 0) return 0;
heap_->CreateFillerObjectAt(start, size_in_bytes);
owner()->heap()->CreateFillerObjectAt(start, size_in_bytes);
Page* page = Page::FromAddress(start);
......@@ -2313,7 +2312,7 @@ int FreeList::Free(Address start, int size_in_bytes) {
page->add_available_in_huge_free_list(size_in_bytes);
}
DCHECK(IsVeryLong() || available() == SumFreeLists());
DCHECK(IsVeryLong() || Available() == SumFreeLists());
return 0;
}
......@@ -2323,7 +2322,7 @@ FreeSpace* FreeList::FindNodeIn(FreeListCategoryType category, int* node_size) {
if (node != nullptr) {
Page::FromAddress(node->address())
->add_available_in_free_list(category, -(*node_size));
DCHECK(IsVeryLong() || available() == SumFreeLists());
DCHECK(IsVeryLong() || Available() == SumFreeLists());
}
return node;
}
......@@ -2336,7 +2335,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
if (size_in_bytes <= kSmallAllocationMax) {
node = FindNodeIn(kSmall, node_size);
if (node != NULL) {
DCHECK(IsVeryLong() || available() == SumFreeLists());
DCHECK(IsVeryLong() || Available() == SumFreeLists());
return node;
}
}
......@@ -2344,7 +2343,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
if (size_in_bytes <= kMediumAllocationMax) {
node = FindNodeIn(kMedium, node_size);
if (node != NULL) {
DCHECK(IsVeryLong() || available() == SumFreeLists());
DCHECK(IsVeryLong() || Available() == SumFreeLists());
return node;
}
}
......@@ -2352,7 +2351,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
if (size_in_bytes <= kLargeAllocationMax) {
node = FindNodeIn(kLarge, node_size);
if (node != NULL) {
DCHECK(IsVeryLong() || available() == SumFreeLists());
DCHECK(IsVeryLong() || Available() == SumFreeLists());
return node;
}
}
......@@ -2360,7 +2359,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
node = huge_list_.SearchForNodeInList(size_in_bytes, node_size);
if (node != NULL) {
DCHECK(IsVeryLong() || available() == SumFreeLists());
DCHECK(IsVeryLong() || Available() == SumFreeLists());
return node;
}
......@@ -2387,7 +2386,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
}
}
DCHECK(IsVeryLong() || available() == SumFreeLists());
DCHECK(IsVeryLong() || Available() == SumFreeLists());
return node;
}
......@@ -2511,9 +2510,6 @@ intptr_t FreeListCategory::SumFreeList() {
}
static const int kVeryLongFreeList = 500;
int FreeListCategory::FreeListLength() {
int length = 0;
FreeSpace* cur = top();
......@@ -2526,12 +2522,14 @@ int FreeListCategory::FreeListLength() {
}
bool FreeListCategory::IsVeryLong() {
return FreeListLength() == kVeryLongFreeList;
}
bool FreeList::IsVeryLong() {
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;
return small_list_.IsVeryLong() || medium_list_.IsVeryLong() ||
large_list_.IsVeryLong() || huge_list_.IsVeryLong();
}
......@@ -2659,7 +2657,7 @@ HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) {
// Try to expand the space and allocate in the new next page.
if (Expand()) {
DCHECK((CountTotalPages() > 1) ||
(size_in_bytes <= free_list_.available()));
(size_in_bytes <= free_list_.Available()));
return free_list_.Allocate(size_in_bytes);
}
......
......@@ -1589,11 +1589,7 @@ class AllocationStats BASE_EMBEDDED {
};
// -----------------------------------------------------------------------------
// Free lists for old object spaces
// The free list category holds a pointer to the top element and a pointer to
// the end element of the linked list of free memory blocks.
// A free list category maintains a linked list of free memory blocks.
class FreeListCategory {
public:
explicit FreeListCategory(FreeList* owner, FreeListCategoryType type)
......@@ -1603,6 +1599,9 @@ class FreeListCategory {
available_(0),
owner_(owner) {}
// Concatenates {category} into {this}.
//
// Note: Thread-safe.
intptr_t Concatenate(FreeListCategory* category);
void Reset();
......@@ -1632,9 +1631,14 @@ class FreeListCategory {
#ifdef DEBUG
intptr_t SumFreeList();
int FreeListLength();
bool IsVeryLong();
#endif
private:
// For debug builds we accurately compute free lists lengths up until
// {kVeryLongFreeList} by manually walking the list.
static const int kVeryLongFreeList = 500;
FreeSpace* top() { return top_.Value(); }
void set_top(FreeSpace* top) { top_.SetValue(top); }
......@@ -1658,59 +1662,28 @@ class FreeListCategory {
FreeList* owner_;
};
// The free list for the old space. The free list is organized in such a way
// as to encourage objects allocated around the same time to be near each
// other. The normal way to allocate is intended to be by bumping a 'top'
// A free list maintaining free blocks of memory. The free list is organized in
// a way to encourage objects allocated around the same time to be near each
// other. The normal way to allocate is intended to be by bumping a 'top'
// pointer until it hits a 'limit' pointer. When the limit is hit we need to
// find a new space to allocate from. This is done with the free list, which
// is divided up into rough categories to cut down on waste. Having finer
// find a new space to allocate from. This is done with the free list, which is
// divided up into rough categories to cut down on waste. Having finer
// categories would scatter allocation more.
// The old space free list is organized in categories.
// 1-31 words: Such small free areas are discarded for efficiency reasons.
// They can be reclaimed by the compactor. However the distance between top
// and limit may be this small.
// 32-255 words: There is a list of spaces this large. It is used for top and
// limit when the object we need to allocate is 1-31 words in size. These
// spaces are called small.
// 256-2047 words: There is a list of spaces this large. It is used for top and
// limit when the object we need to allocate is 32-255 words in size. These
// spaces are called medium.
// 1048-16383 words: There is a list of spaces this large. It is used for top
// and limit when the object we need to allocate is 256-2047 words in size.
// These spaces are call large.
// At least 16384 words. This list is for objects of 2048 words or larger.
// Empty pages are added to this list. These spaces are called huge.
// The free list is organized in categories as follows:
// 1-31 words (too small): Such small free areas are discarded for efficiency
// reasons. They can be reclaimed by the compactor. However the distance
// between top and limit may be this small.
// 32-255 words (small): Used for allocating free space between 1-31 words in
// size.
// 256-2047 words (medium): Used for allocating free space between 32-255 words
// in size.
// 1048-16383 words (large): Used for allocating free space between 256-2047
// words in size.
// At least 16384 words (huge): This list is for objects of 2048 words or
// larger. Empty pages are also added to this list.
class FreeList {
public:
explicit FreeList(PagedSpace* owner);
// The method concatenates {other} into {this} and returns the added bytes,
// including waste.
//
// Can be used concurrently.
intptr_t Concatenate(FreeList* other);
// Clear the free list.
void Reset();
void ResetStats() { wasted_bytes_ = 0; }
// Return the number of bytes available on the free list.
intptr_t available() {
return small_list_.available() + medium_list_.available() +
large_list_.available() + huge_list_.available();
}
// Place a node on the free list. The block of size 'size_in_bytes'
// starting at 'start' is placed on the free list. The return value is the
// number of bytes that have been lost due to internal fragmentation by
// freeing the block. Bookkeeping information will be written to the block,
// i.e., its contents will be destroyed. The start address should be word
// aligned, and the size should be a non-zero multiple of the word size.
int Free(Address start, int size_in_bytes);
// This method returns how much memory can be allocated after freeing
// maximum_freed memory.
static inline int GuaranteedAllocatable(int maximum_freed) {
......@@ -1726,22 +1699,43 @@ class FreeList {
return maximum_freed;
}
// Allocate a block of size 'size_in_bytes' from the free list. The block
// is unitialized. A failure is returned if no block is available.
// The size should be a non-zero multiple of the word size.
explicit FreeList(PagedSpace* owner);
// The method concatenates {other} into {this} and returns the added bytes,
// including waste.
//
// Note: Thread-safe.
intptr_t Concatenate(FreeList* other);
// Adds a node on the free list. The block of size {size_in_bytes} starting
// at {start} is placed on the free list. The return value is the number of
// bytes that were not added to the free list, because they freed memory block
// was too small. Bookkeeping information will be written to the block, i.e.,
// its contents will be destroyed. The start address should be word aligned,
// and the size should be a non-zero multiple of the word size.
int Free(Address start, int size_in_bytes);
// Allocate a block of size {size_in_bytes} from the free list. The block is
// unitialized. A failure is returned if no block is available. The size
// should be a non-zero multiple of the word size.
MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes);
// Clear the free list.
void Reset();
void ResetStats() { wasted_bytes_ = 0; }
// Return the number of bytes available on the free list.
intptr_t Available() {
return small_list_.available() + medium_list_.available() +
large_list_.available() + huge_list_.available();
}
bool IsEmpty() {
return small_list_.IsEmpty() && medium_list_.IsEmpty() &&
large_list_.IsEmpty() && huge_list_.IsEmpty();
}
#ifdef DEBUG
void Zap();
intptr_t SumFreeLists();
bool IsVeryLong();
#endif
// Used after booting the VM.
void RepairLists(Heap* heap);
......@@ -1752,6 +1746,12 @@ class FreeList {
intptr_t wasted_bytes() { return wasted_bytes_; }
base::Mutex* mutex() { return &mutex_; }
#ifdef DEBUG
void Zap();
intptr_t SumFreeLists();
bool IsVeryLong();
#endif
private:
// The size range of blocks, in bytes.
static const int kMinBlockSize = 3 * kPointerSize;
......@@ -1785,9 +1785,7 @@ class FreeList {
return nullptr;
}
PagedSpace* owner_;
Heap* heap_;
base::Mutex mutex_;
intptr_t wasted_bytes_;
FreeListCategory small_list_;
......@@ -1907,7 +1905,7 @@ class PagedSpace : public Space {
// The bytes in the linear allocation area are not included in this total
// because updating the stats would slow down allocation. New pages are
// immediately added to the free list so they show up here.
intptr_t Available() override { return free_list_.available(); }
intptr_t Available() override { return free_list_.Available(); }
// Allocated bytes in this space. Garbage bytes that were not found due to
// concurrent sweeping are counted as being allocated! The bytes in the
......
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