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