5#ifndef V8_HEAP_FREE_LIST_H_
6#define V8_HEAP_FREE_LIST_H_
17#include "testing/gtest/include/gtest/gtest_prod.h"
24class TestCodePageAllocatorScope;
27class AllocationObserver;
30class LargeObjectSpace;
31class LargePageMetadata;
32class LinearAllocationArea;
85 template <
typename Callback>
88 cur_node = cur_node->next()) {
163 size_t size_in_bytes) = 0;
165 virtual void Reset();
200 template <
typename Callback>
203 while (current !=
nullptr) {
210 template <
typename Callback>
253 size_t minimum_size,
size_t* node_size);
257 size_t minimum_size,
size_t* node_size);
262 size_t size_in_bytes) = 0;
297 PageMetadata* GetPageForSize(
size_t size_in_bytes)
override;
303 size_t size_in_bytes,
size_t* node_size,
311 static constexpr size_t kMaxBlockSize = MutablePageMetadata::kPageSize;
314 static constexpr size_t kPreciseCategoryMaxSize = 256;
324 static constexpr int kNumberOfCategories = 24;
325 static constexpr unsigned int categories_min[kNumberOfCategories] = {
326 24, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192,
327 208, 224, 240, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536};
331 size_t size_in_bytes)
override {
332 if (size_in_bytes <= kPreciseCategoryMaxSize) {
333 if (size_in_bytes < categories_min[1])
return 0;
336 for (
int cat = (kPreciseCategoryMaxSize >> 4) - 1; cat < last_category_;
338 if (size_in_bytes < categories_min[cat + 1]) {
342 return last_category_;
359 size_t size_in_bytes,
size_t* node_size,
364 void Reset()
override;
365 void ResetForNonBlackAllocatedPages()
override;
375 next_nonempty_category[
i] = cat;
383 next_nonempty_category[
i] = next_nonempty_category[cat + 1];
388 void CheckCacheIntegrity() {
389 for (
int i = 0;
i <= last_category_;
i++) {
390 DCHECK(next_nonempty_category[
i] == last_category_ + 1 ||
391 categories_[next_nonempty_category[
i]] !=
nullptr);
392 for (
int j =
i; j < next_nonempty_category[
i]; j++) {
393 DCHECK(categories_[j] ==
nullptr);
402 int next_nonempty_category[kNumberOfCategories + 1];
406 for (
int i = 0;
i < kNumberOfCategories;
i++) {
407 next_nonempty_category[
i] = kNumberOfCategories;
411 next_nonempty_category[kNumberOfCategories] = kNumberOfCategories;
440 : small_blocks_mode_(small_blocks_mode) {
441 if (small_blocks_mode_ == SmallBlocksMode::kProhibit) {
444 ? (
v8_flags.minor_ms_min_lab_size_kb * KB)
450 size_t size_in_bytes,
size_t* node_size,
456 static const size_t kFastPathStart = 2048;
457 static const size_t kTinyObjectMaxSize = 128;
458 static const size_t kFastPathOffset = kFastPathStart - kTinyObjectMaxSize;
462 static_assert(categories_min[kFastPathFirstCategory] == kFastPathStart);
463 static_assert(categories_min[kFastPathFallBackTiny] ==
464 kTinyObjectMaxSize * 2);
467 size_t size_in_bytes) {
468 DCHECK(size_in_bytes < kMaxBlockSize);
470 if (size_in_bytes >= categories_min[last_category_])
return last_category_;
472 size_in_bytes += kFastPathOffset;
473 for (
int cat = kFastPathFirstCategory; cat < last_category_; cat++) {
474 if (size_in_bytes <= categories_min[cat]) {
478 return last_category_;
486 FreeListManyCachedFastPathSelectFastAllocationFreeListCategoryType);
514 size_t size_in_bytes,
size_t* node_size,
void Relink(FreeList *owner)
uint32_t available() const
Tagged< FreeSpace > top()
bool is_linked(FreeList *owner) const
FreeListCategory * next()
void RepairFreeList(Heap *heap)
static constexpr int kVeryLongFreeList
void Initialize(FreeListCategoryType type)
void Reset(FreeList *owner)
FreeListCategory * prev()
FreeListCategoryType type_
void Free(const WritableFreeSpace &writable_free_space, FreeMode mode, FreeList *owner)
Tagged< FreeSpace > SearchForNodeInList(size_t minimum_size, size_t *node_size)
void UpdateCountersAfterAllocation(size_t allocation_size)
void set_prev(FreeListCategory *prev)
V8_EXPORT_PRIVATE Tagged< FreeSpace > PickNodeFromList(size_t minimum_size, size_t *node_size)
void set_top(Tagged< FreeSpace > top)
void set_next(FreeListCategory *next)
void Unlink(FreeList *owner)
void IterateNodesForTesting(Callback callback)
FRIEND_TEST(SpacesTest, FreeListManyCachedFastPathSelectFastAllocationFreeListCategoryType)
FreeListCategoryType SelectFastAllocationFreeListCategoryType(size_t size_in_bytes)
FreeListManyCachedFastPathBase(SmallBlocksMode small_blocks_mode)
SmallBlocksMode small_blocks_mode_
FreeListManyCachedFastPathForNewSpace()
FreeListManyCachedFastPath()
void UpdateCacheAfterAddition(FreeListCategoryType cat)
void UpdateCacheAfterRemoval(FreeListCategoryType cat)
FreeListCategoryType SelectFreeListCategoryType(size_t size_in_bytes) override
FRIEND_TEST(SpacesTest, FreeListManySelectFreeListCategoryType)
FRIEND_TEST(SpacesTest, FreeListManyGuaranteedAllocatable)
FreeListCategory * Next()
FreeListCategory * current_
FreeListCategoryIterator(FreeList *free_list, FreeListCategoryType type)
size_t wasted_bytes() const
virtual FreeListCategoryType SelectFreeListCategoryType(size_t size_in_bytes)=0
virtual void ResetForNonBlackAllocatedPages()
static V8_EXPORT_PRIVATE std::unique_ptr< FreeList > CreateFreeList()
FreeList(int number_of_categories, size_t min_block_size)
const int number_of_categories_
void ForAllFreeListCategories(Callback callback)
void increase_wasted_bytes(size_t bytes)
Tagged< FreeSpace > SearchForNodeInList(FreeListCategoryType type, size_t minimum_size, size_t *node_size)
V8_EXPORT_PRIVATE void EvictFreeListItems(PageMetadata *page)
virtual bool AddCategory(FreeListCategory *category)
FreeListCategory ** categories_
void IncreaseAvailableBytes(size_t bytes)
std::atomic< size_t > wasted_bytes_
virtual ~FreeList()=default
PageMetadata * GetPageForCategoryType(FreeListCategoryType type)
void ForAllFreeListCategories(FreeListCategoryType type, Callback callback)
static V8_EXPORT_PRIVATE std::unique_ptr< FreeList > CreateFreeListForNewSpace()
FreeListCategoryType last_category()
virtual size_t Free(const WritableFreeSpace &free_space, FreeMode mode)
void DecreaseAvailableBytes(size_t bytes)
int number_of_categories()
void decrease_wasted_bytes(size_t bytes)
const FreeListCategoryType last_category_
size_t min_block_size() const
virtual V8_WARN_UNUSED_RESULT Tagged< FreeSpace > Allocate(size_t size_in_bytes, size_t *node_size, AllocationOrigin origin)=0
FreeListCategory * top(FreeListCategoryType type) const
virtual V8_EXPORT_PRIVATE void RemoveCategory(FreeListCategory *category)
void RepairLists(Heap *heap)
virtual V8_EXPORT_PRIVATE PageMetadata * GetPageForSize(size_t size_in_bytes)=0
void PrintCategories(FreeListCategoryType type)
Tagged< FreeSpace > TryFindNodeIn(FreeListCategoryType type, size_t minimum_size, size_t *node_size)
V8_INLINE constexpr bool is_null() const
static constexpr FreeListCategoryType kFirstCategory
constexpr int kTaggedSize
int32_t FreeListCategoryType
V8_EXPORT_PRIVATE FlagValues v8_flags
static constexpr FreeListCategoryType kInvalidCategory
#define DCHECK(condition)
#define V8_EXPORT_PRIVATE
#define V8_WARN_UNUSED_RESULT