| Index: src/heap/spaces.h
|
| diff --git a/src/heap/spaces.h b/src/heap/spaces.h
|
| index 69a8d89fccba5c5aa06f91d2a1995870b70ef033..9e115eaeca5d83247dd0251384790cd6d87684f9 100644
|
| --- a/src/heap/spaces.h
|
| +++ b/src/heap/spaces.h
|
| @@ -1584,11 +1584,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)
|
| @@ -1598,6 +1594,9 @@ class FreeListCategory {
|
| available_(0),
|
| owner_(owner) {}
|
|
|
| + // Concatenates {category} into {this}.
|
| + //
|
| + // Note: Thread-safe.
|
| intptr_t Concatenate(FreeListCategory* category);
|
|
|
| void Reset();
|
| @@ -1627,9 +1626,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); }
|
|
|
| @@ -1653,59 +1657,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) {
|
| @@ -1721,22 +1694,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);
|
|
|
| @@ -1747,6 +1741,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;
|
| @@ -1780,9 +1780,7 @@ class FreeList {
|
| return nullptr;
|
| }
|
|
|
| -
|
| PagedSpace* owner_;
|
| - Heap* heap_;
|
| base::Mutex mutex_;
|
| intptr_t wasted_bytes_;
|
| FreeListCategory small_list_;
|
| @@ -1902,7 +1900,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
|
|
|