@@ -30,6 +30,7 @@ static constexpr cpp::array<size_t, 6> DEFAULT_BUCKETS{16, 32, 64,
3030template <size_t NUM_BUCKETS = DEFAULT_BUCKETS.size()> class FreeListHeap {
3131public:
3232 using BlockType = Block<>;
33+ using FreeListType = FreeList<NUM_BUCKETS>;
3334
3435 struct HeapStats {
3536 size_t total_bytes;
@@ -39,35 +40,73 @@ template <size_t NUM_BUCKETS = DEFAULT_BUCKETS.size()> class FreeListHeap {
3940 size_t total_allocate_calls;
4041 size_t total_free_calls;
4142 };
42- FreeListHeap (span<cpp::byte> region);
43+
44+ FreeListHeap (span<cpp::byte> region)
45+ : FreeListHeap(&*region.begin(), &*region.end(), region.size()) {
46+ auto result = BlockType::init (region);
47+ BlockType *block = *result;
48+ freelist_.add_chunk (block_to_span (block));
49+ }
50+
51+ constexpr FreeListHeap (void *start, cpp::byte *end, size_t total_bytes)
52+ : block_region_start_(start), block_region_end_(end),
53+ freelist_(DEFAULT_BUCKETS), heap_stats_{} {
54+ heap_stats_.total_bytes = total_bytes;
55+ }
4356
4457 void *allocate (size_t size);
4558 void free (void *ptr);
4659 void *realloc (void *ptr, size_t size);
4760 void *calloc (size_t num, size_t size);
4861
4962 const HeapStats &heap_stats () const { return heap_stats_; }
63+ void reset_heap_stats () { heap_stats_ = {}; }
64+
65+ void *region_start () const { return block_region_start_; }
66+ size_t region_size () const {
67+ return reinterpret_cast <uintptr_t >(block_region_end_) -
68+ reinterpret_cast <uintptr_t >(block_region_start_);
69+ }
70+
71+ protected:
72+ constexpr void set_freelist_node (typename FreeListType::FreeListNode *node,
73+ cpp::span<cpp::byte> chunk) {
74+ freelist_.set_freelist_node (node, chunk);
75+ }
5076
5177private:
5278 span<cpp::byte> block_to_span (BlockType *block) {
5379 return span<cpp::byte>(block->usable_space (), block->inner_size ());
5480 }
5581
56- span<cpp::byte> region_;
57- FreeList<NUM_BUCKETS> freelist_;
82+ bool is_valid_ptr (void *ptr) {
83+ return ptr >= block_region_start_ && ptr < block_region_end_;
84+ }
85+
86+ void *block_region_start_;
87+ void *block_region_end_;
88+ FreeListType freelist_;
5889 HeapStats heap_stats_;
5990};
6091
61- template <size_t NUM_BUCKETS>
62- FreeListHeap<NUM_BUCKETS>::FreeListHeap(span<cpp::byte> region)
63- : region_(region), freelist_(DEFAULT_BUCKETS), heap_stats_() {
64- auto result = BlockType::init (region);
65- BlockType *block = *result;
92+ template <size_t BUFF_SIZE, size_t NUM_BUCKETS = DEFAULT_BUCKETS.size()>
93+ struct FreeListHeapBuffer : public FreeListHeap <NUM_BUCKETS> {
94+ using parent = FreeListHeap<NUM_BUCKETS>;
95+ using FreeListNode = typename parent::FreeListType::FreeListNode;
6696
67- freelist_.add_chunk (block_to_span (block));
97+ constexpr FreeListHeapBuffer ()
98+ : FreeListHeap<NUM_BUCKETS>(&block, buffer + sizeof (buffer), BUFF_SIZE),
99+ block(0 , BUFF_SIZE), node{}, buffer{} {
100+ block.mark_last ();
68101
69- heap_stats_.total_bytes = region.size ();
70- }
102+ cpp::span<cpp::byte> chunk (buffer, sizeof (buffer));
103+ parent::set_freelist_node (&node, chunk);
104+ }
105+
106+ typename parent::BlockType block;
107+ FreeListNode node;
108+ cpp::byte buffer[BUFF_SIZE - sizeof (block) - sizeof (node)];
109+ };
71110
72111template <size_t NUM_BUCKETS>
73112void *FreeListHeap<NUM_BUCKETS>::allocate(size_t size) {
@@ -97,7 +136,7 @@ void *FreeListHeap<NUM_BUCKETS>::allocate(size_t size) {
97136template <size_t NUM_BUCKETS> void FreeListHeap<NUM_BUCKETS>::free(void *ptr) {
98137 cpp::byte *bytes = static_cast <cpp::byte *>(ptr);
99138
100- LIBC_ASSERT (bytes >= region_. data () && bytes < region_. data () + region_. size ( ) && " Invalid pointer" );
139+ LIBC_ASSERT (is_valid_ptr ( bytes) && " Invalid pointer" );
101140
102141 BlockType *chunk_block = BlockType::from_usable_space (bytes);
103142
@@ -131,7 +170,7 @@ template <size_t NUM_BUCKETS> void FreeListHeap<NUM_BUCKETS>::free(void *ptr) {
131170 heap_stats_.total_free_calls += 1 ;
132171}
133172
134- // Follows contract of the C standard realloc() function
173+ // Follows constract of the C standard realloc() function
135174// If ptr is free'd, will return nullptr.
136175template <size_t NUM_BUCKETS>
137176void *FreeListHeap<NUM_BUCKETS>::realloc(void *ptr, size_t size) {
@@ -146,7 +185,7 @@ void *FreeListHeap<NUM_BUCKETS>::realloc(void *ptr, size_t size) {
146185
147186 cpp::byte *bytes = static_cast <cpp::byte *>(ptr);
148187
149- if (bytes < region_. data () || bytes >= region_. data () + region_. size ( ))
188+ if (! is_valid_ptr ( bytes))
150189 return nullptr ;
151190
152191 BlockType *chunk_block = BlockType::from_usable_space (bytes);
@@ -177,6 +216,8 @@ void *FreeListHeap<NUM_BUCKETS>::calloc(size_t num, size_t size) {
177216 return ptr;
178217}
179218
219+ extern FreeListHeap<> *freelist_heap;
220+
180221} // namespace LIBC_NAMESPACE
181222
182223#endif // LLVM_LIBC_SRC_STDLIB_FREELIST_HEAP_H
0 commit comments