Commit 6b340ded authored by hpayer's avatar hpayer Committed by Commit bot

[heap] Add two tiny free list categories.

This CL allows the sweeper to free up all memory >= free list item size (3 words). This may reduce memory consumption (especially in map space), but may be worse for allocation order as soon as we start using the tiny category.

This CL is just a first step in the right direction. A follow up CL will add customizable free list categories for each old space.

BUG=chromium:587026
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#34612}
parent a8a0a62e
......@@ -2379,8 +2379,8 @@ int FreeList::Free(Address start, int size_in_bytes) {
Page* page = Page::FromAddress(start);
// Early return to drop too-small blocks on the floor.
if (size_in_bytes <= kSmallListMin) {
// Blocks have to be a minimum size to hold free list items.
if (size_in_bytes < kMinBlockSize) {
page->add_wasted_memory(size_in_bytes);
wasted_bytes_ += size_in_bytes;
return size_in_bytes;
......@@ -2437,7 +2437,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
if (type == kHuge) return nullptr;
// Now search the best fitting free list for a node that has at least the
// requested size. This takes linear time in the number of elements.
// requested size.
type = SelectFreeListCategoryType(size_in_bytes);
node = category_[type].PickNodeFromList(size_in_bytes, node_size);
if (node != nullptr) {
......@@ -2462,18 +2462,18 @@ FreeSpace* FreeList::TryRemoveMemory(intptr_t hint_size_in_bytes) {
if (node == nullptr) node = FindNodeIn(kHuge, &node_size);
if (node == nullptr) node = FindNodeIn(kLarge, &node_size);
if (node != nullptr) {
// We round up the size to (kSmallListMin + kPointerSize) to (a) have a
// We round up the size to (kMinBlockSize + kPointerSize) to (a) have a
// size larger then the minimum size required for FreeSpace, and (b) to get
// a block that can actually be freed into some FreeList later on.
if (hint_size_in_bytes <= kSmallListMin) {
hint_size_in_bytes = kSmallListMin + kPointerSize;
if (hint_size_in_bytes <= kMinBlockSize) {
hint_size_in_bytes = kMinBlockSize + kPointerSize;
}
// Give back left overs that were not required by {size_in_bytes}.
intptr_t left_over = node_size - hint_size_in_bytes;
// Do not bother to return anything below {kSmallListMin} as it would be
// Do not bother to return anything below {kMinBlockSize} as it would be
// immediately discarded anyways.
if (left_over > kSmallListMin) {
if (left_over > kMinBlockSize) {
Free(node->address() + hint_size_in_bytes, static_cast<int>(left_over));
node->set_size(static_cast<int>(hint_size_in_bytes));
}
......
......@@ -724,12 +724,14 @@ class MemoryChunk {
};
enum FreeListCategoryType {
kTiniest,
kTiny,
kSmall,
kMedium,
kLarge,
kHuge,
kFirstCategory = kSmall,
kFirstCategory = kTiniest,
kLastCategory = kHuge,
kNumberOfCategories = kLastCategory + 1
};
......@@ -1650,9 +1652,10 @@ class FreeListCategory {
// categories would scatter allocation more.
// 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.
// kMinBlockSize-10 words (tiniest): The tiniest blocks are only used for
// allocation, when categories >= small do not have entries anymore.
// 11-31 words (tiny): The tiny blocks are only used for allocation, when
// categories >= small do not have entries anymore.
// 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
......@@ -1666,8 +1669,12 @@ class FreeList {
// This method returns how much memory can be allocated after freeing
// maximum_freed memory.
static inline int GuaranteedAllocatable(int maximum_freed) {
if (maximum_freed <= kSmallListMin) {
if (maximum_freed <= kTiniestListMax) {
// Since we are not iterating over all list entries, we cannot guarantee
// that we can find the maximum freed block in that free list.
return 0;
} else if (maximum_freed <= kTinyListMax) {
return kTinyAllocationMax;
} else if (maximum_freed <= kSmallListMax) {
return kSmallAllocationMax;
} else if (maximum_freed <= kMediumListMax) {
......@@ -1749,11 +1756,13 @@ class FreeList {
static const int kMinBlockSize = 3 * kPointerSize;
static const int kMaxBlockSize = Page::kAllocatableMemory;
static const int kSmallListMin = 0x1f * kPointerSize;
static const int kTiniestListMax = 0xa * kPointerSize;
static const int kTinyListMax = 0x1f * kPointerSize;
static const int kSmallListMax = 0xff * kPointerSize;
static const int kMediumListMax = 0x7ff * kPointerSize;
static const int kLargeListMax = 0x3fff * kPointerSize;
static const int kSmallAllocationMax = kSmallListMin;
static const int kTinyAllocationMax = kTiniestListMax;
static const int kSmallAllocationMax = kTinyListMax;
static const int kMediumAllocationMax = kSmallListMax;
static const int kLargeAllocationMax = kMediumListMax;
......@@ -1765,7 +1774,11 @@ class FreeList {
}
FreeListCategoryType SelectFreeListCategoryType(size_t size_in_bytes) {
if (size_in_bytes <= kSmallListMax) {
if (size_in_bytes <= kTiniestListMax) {
return kTiniest;
} else if (size_in_bytes <= kTinyListMax) {
return kTiny;
} else if (size_in_bytes <= kSmallListMax) {
return kSmall;
} else if (size_in_bytes <= kMediumListMax) {
return kMedium;
......@@ -1775,6 +1788,7 @@ class FreeList {
return kHuge;
}
// The tiny categories are not used for fast allocation.
FreeListCategoryType SelectFastAllocationFreeListCategoryType(
size_t size_in_bytes) {
if (size_in_bytes <= kSmallAllocationMax) {
......
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