// Copyright 2020 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_HEAP_FREE_LIST_H_ #define V8_HEAP_FREE_LIST_H_ #include <atomic> #include "src/base/macros.h" #include "src/common/globals.h" #include "src/heap/allocation-result.h" #include "src/heap/mutable-page-metadata.h" #include "src/objects/free-space.h" #include "src/objects/map.h" #include "src/utils/utils.h" #include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck namespace v8 { namespace internal { namespace heap { class HeapTester; class TestCodePageAllocatorScope; } // namespace heap class AllocationObserver; class FreeList; class Isolate; class LargeObjectSpace; class LargePageMetadata; class LinearAllocationArea; class PageMetadata; class PagedSpace; class SemiSpace; FreeListCategoryType; static constexpr FreeListCategoryType kFirstCategory = …; static constexpr FreeListCategoryType kInvalidCategory = …; enum FreeMode { … }; // A free list category maintains a linked list of free memory blocks. class FreeListCategory { … }; // A free list maintains 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 // categories would scatter allocation more. class FreeList { … }; // Use 24 Freelists: on per 16 bytes between 24 and 256, and then a few ones for // larger sizes. See the variable |categories_min| for the size of each // Freelist. Allocation is done using a best-fit strategy (considering only the // first element of each category though). // Performances are expected to be worst than FreeListLegacy, but memory // consumption should be lower (since fragmentation should be lower). class V8_EXPORT_PRIVATE FreeListMany : public FreeList { … }; // Same as FreeListMany but uses a cache to know which categories are empty. // The cache (|next_nonempty_category|) is maintained in a way such that for // each category c, next_nonempty_category[c] contains the first non-empty // category greater or equal to c, that may hold an object of size c. // Allocation is done using the same strategy as FreeListMany (ie, best fit). class V8_EXPORT_PRIVATE FreeListManyCached : public FreeListMany { … }; // Same as FreeListManyCached but uses a fast path. // The fast path overallocates by at least 1.85k bytes. The idea of this 1.85k // is: we want the fast path to always overallocate, even for larger // categories. Therefore, we have two choices: either overallocate by // "size_in_bytes * something" or overallocate by "size_in_bytes + // something". We choose the later, as the former will tend to overallocate too // much for larger objects. The 1.85k (= 2048 - 128) has been chosen such that // for tiny objects (size <= 128 bytes), the first category considered is the // 36th (which holds objects of 2k to 3k), while for larger objects, the first // category considered will be one that guarantees a 1.85k+ bytes // overallocation. Using 2k rather than 1.85k would have resulted in either a // more complex logic for SelectFastAllocationFreeListCategoryType, or the 36th // category (2k to 3k) not being used; both of which are undesirable. // A secondary fast path is used for tiny objects (size <= 128), in order to // consider categories from 256 to 2048 bytes for them. // Note that this class uses a precise GetPageForSize (inherited from // FreeListMany), which makes its fast path less fast in the Scavenger. This is // done on purpose, since this class's only purpose is to be used by // FreeListManyCachedOrigin, which is precise for the scavenger. class V8_EXPORT_PRIVATE FreeListManyCachedFastPathBase : public FreeListManyCached { … }; class FreeListManyCachedFastPath : public FreeListManyCachedFastPathBase { … }; class FreeListManyCachedFastPathForNewSpace : public FreeListManyCachedFastPathBase { … }; // Uses FreeListManyCached if in the GC; FreeListManyCachedFastPath otherwise. // The reasoning behind this FreeList is the following: the GC runs in // parallel, and therefore, more expensive allocations there are less // noticeable. On the other hand, the generated code and runtime need to be very // fast. Therefore, the strategy for the former is one that is not very // efficient, but reduces fragmentation (FreeListManyCached), while the strategy // for the later is one that is very efficient, but introduces some // fragmentation (FreeListManyCachedFastPath). class V8_EXPORT_PRIVATE FreeListManyCachedOrigin : public FreeListManyCachedFastPath { … }; } // namespace internal } // namespace v8 #endif // V8_HEAP_FREE_LIST_H_