@@ -68,43 +68,53 @@ template <size_t NUM_BUCKETS = 6> class FreeList {
68
68
// / Removes a chunk from this freelist.
69
69
bool remove_chunk (cpp::span<cpp::byte> chunk);
70
70
71
- private:
72
- // For a given size, find which index into chunks_ the node should be written
73
- // to.
74
- size_t find_chunk_ptr_for_size (size_t size, bool non_null) const ;
71
+ // / For a given size, find which index into chunks_ the node should be written
72
+ // / to.
73
+ constexpr size_t find_chunk_ptr_for_size (size_t size, bool non_null) const ;
75
74
76
75
struct FreeListNode {
77
76
FreeListNode *next;
78
77
size_t size;
79
78
};
80
79
81
- public:
82
- explicit FreeList (cpp::array<size_t , NUM_BUCKETS> sizes)
80
+ constexpr void set_freelist_node (FreeListNode *node,
81
+ cpp::span<cpp::byte> chunk);
82
+
83
+ constexpr explicit FreeList (cpp::array<size_t , NUM_BUCKETS> sizes)
83
84
: chunks_(NUM_BUCKETS + 1 , 0 ), sizes_(sizes.begin(), sizes.end()) {}
84
85
86
+ private:
85
87
FixedVector<FreeList::FreeListNode *, NUM_BUCKETS + 1 > chunks_;
86
88
FixedVector<size_t , NUM_BUCKETS> sizes_;
87
89
};
88
90
91
+ template <size_t NUM_BUCKETS>
92
+ constexpr void FreeList<NUM_BUCKETS>::set_freelist_node(FreeListNode *node,
93
+ span<cpp::byte> chunk) {
94
+ // Add it to the correct list.
95
+ size_t chunk_ptr = find_chunk_ptr_for_size (chunk.size (), false );
96
+ node->size = chunk.size ();
97
+ node->next = chunks_[chunk_ptr];
98
+ chunks_[chunk_ptr] = node;
99
+ }
100
+
89
101
template <size_t NUM_BUCKETS>
90
102
bool FreeList<NUM_BUCKETS>::add_chunk(span<cpp::byte> chunk) {
91
103
// Check that the size is enough to actually store what we need
92
104
if (chunk.size () < sizeof (FreeListNode))
93
105
return false ;
94
106
107
+ // FIXME: This is UB since type punning is not allowed in C++. THe idea here
108
+ // is that we write the FreeListNode `size` and `next` onto the start of the
109
+ // buffer. Unless the original underlying bytes were a `FreeListNode`, the
110
+ // only safe way to do this is with `memcpy`.
95
111
union {
96
112
FreeListNode *node;
97
113
cpp::byte *bytes;
98
114
} aliased;
99
115
100
116
aliased.bytes = chunk.data ();
101
-
102
- size_t chunk_ptr = find_chunk_ptr_for_size (chunk.size (), false );
103
-
104
- // Add it to the correct list.
105
- aliased.node ->size = chunk.size ();
106
- aliased.node ->next = chunks_[chunk_ptr];
107
- chunks_[chunk_ptr] = aliased.node ;
117
+ set_freelist_node (aliased.node , chunk);
108
118
109
119
return true ;
110
120
}
@@ -180,8 +190,9 @@ bool FreeList<NUM_BUCKETS>::remove_chunk(span<cpp::byte> chunk) {
180
190
}
181
191
182
192
template <size_t NUM_BUCKETS>
183
- size_t FreeList<NUM_BUCKETS>::find_chunk_ptr_for_size(size_t size,
184
- bool non_null) const {
193
+ constexpr size_t
194
+ FreeList<NUM_BUCKETS>::find_chunk_ptr_for_size(size_t size,
195
+ bool non_null) const {
185
196
size_t chunk_ptr = 0 ;
186
197
for (chunk_ptr = 0u ; chunk_ptr < sizes_.size (); chunk_ptr++) {
187
198
if (sizes_[chunk_ptr] >= size &&
0 commit comments