@@ -43,8 +43,8 @@ using cpp::optional;
4343// / The blocks store their offsets to the previous and next blocks. The latter
4444// / is also the block's size.
4545// /
46- // / All blocks have their usable space aligned to some multiple of max_align_t .
47- // / This also implies that block outer sizes are aligned to max_align_t .
46+ // / All blocks have their usable space aligned to some multiple of MIN_ALIGN .
47+ // / This also implies that block outer sizes are aligned to MIN_ALIGN .
4848// /
4949// / As an example, the diagram below represents two contiguous `Block`s. The
5050// / indices indicate byte offsets:
@@ -97,13 +97,17 @@ class Block {
9797 static constexpr size_t SIZE_MASK = ~(PREV_FREE_MASK | LAST_MASK);
9898
9999public:
100+ // To ensure block sizes have two lower unused bits, ensure usable space is
101+ // always aligned to at least 4 bytes. (The distances between usable spaces,
102+ // the outer size, is then always also 4-aligned.)
103+ static constexpr size_t MIN_ALIGN = cpp::max(size_t {4 }, alignof (max_align_t ));
100104 // No copy or move.
101105 Block (const Block &other) = delete ;
102106 Block &operator =(const Block &other) = delete ;
103107
104108 // / Initializes a given memory region into a first block and a sentinel last
105109 // / block. Returns the first block, which has its usable space aligned to
106- // / max_align_t .
110+ // / MIN_ALIGN .
107111 static optional<Block *> init (ByteSpan region);
108112
109113 // / @returns A pointer to a `Block`, given a pointer to the start of the
@@ -160,17 +164,17 @@ class Block {
160164
161165 // / @returns A pointer to the usable space inside this block.
162166 // /
163- // / Aligned to some multiple of max_align_t .
167+ // / Aligned to some multiple of MIN_ALIGN .
164168 LIBC_INLINE cpp::byte *usable_space () {
165169 auto *s = reinterpret_cast <cpp::byte *>(this ) + sizeof (Block);
166- LIBC_ASSERT (reinterpret_cast <uintptr_t >(s) % alignof ( max_align_t ) == 0 &&
167- " usable space must be aligned to a multiple of max_align_t " );
170+ LIBC_ASSERT (reinterpret_cast <uintptr_t >(s) % MIN_ALIGN == 0 &&
171+ " usable space must be aligned to MIN_ALIGN " );
168172 return s;
169173 }
170174 LIBC_INLINE const cpp::byte *usable_space () const {
171175 const auto *s = reinterpret_cast <const cpp::byte *>(this ) + sizeof (Block);
172- LIBC_ASSERT (reinterpret_cast <uintptr_t >(s) % alignof ( max_align_t ) == 0 &&
173- " usable space must be aligned to a multiple of max_align_t " );
176+ LIBC_ASSERT (reinterpret_cast <uintptr_t >(s) % MIN_ALIGN == 0 &&
177+ " usable space must be aligned to MIN_ALIGN " );
174178 return s;
175179 }
176180
@@ -185,9 +189,9 @@ class Block {
185189 // / `new_inner_size`. The remaining space will be returned as a new block,
186190 // / with usable space aligned to `usable_space_alignment`. Note that the prev_
187191 // / field of the next block counts as part of the inner size of the block.
188- // / `usable_space_alignment` must be a multiple of max_align_t .
192+ // / `usable_space_alignment` must be a multiple of MIN_ALIGN .
189193 optional<Block *> split (size_t new_inner_size,
190- size_t usable_space_alignment = alignof ( max_align_t ) );
194+ size_t usable_space_alignment = MIN_ALIGN );
191195
192196 // / Merges this block with the one that comes after it.
193197 bool merge_next ();
@@ -228,13 +232,11 @@ class Block {
228232
229233 LIBC_INLINE Block (size_t outer_size, bool is_last) : next_(outer_size) {
230234 // Last blocks are not usable, so they need not have sizes aligned to
231- // max_align_t. Their lower bits must still be free, so they must be aligned
232- // to Block.
233- LIBC_ASSERT (
234- outer_size % (is_last ? alignof (Block) : alignof (max_align_t )) == 0 &&
235- " block sizes must be aligned" );
236- LIBC_ASSERT (is_usable_space_aligned (alignof (max_align_t )) &&
237- " usable space must be aligned to a multiple of max_align_t" );
235+ // MIN_ALIGN.
236+ LIBC_ASSERT (outer_size % (is_last ? alignof (Block) : MIN_ALIGN) == 0 &&
237+ " block sizes must be aligned" );
238+ LIBC_ASSERT (is_usable_space_aligned (MIN_ALIGN) &&
239+ " usable space must be aligned to a multiple of MIN_ALIGN" );
238240 if (is_last)
239241 next_ |= LAST_MASK;
240242 }
@@ -249,11 +251,10 @@ class Block {
249251 // Returns 0 if there is no such size.
250252 LIBC_INLINE static size_t min_size_for_allocation (size_t alignment,
251253 size_t size) {
252- LIBC_ASSERT (alignment >= alignof (max_align_t ) &&
253- alignment % alignof (max_align_t ) == 0 &&
254- " alignment must be multiple of max_align_t" );
254+ LIBC_ASSERT (alignment >= MIN_ALIGN && alignment % MIN_ALIGN == 0 &&
255+ " alignment must be multiple of MIN_ALIGN" );
255256
256- if (alignment == alignof ( max_align_t ) )
257+ if (alignment == MIN_ALIGN )
257258 return size;
258259
259260 // We must create a new block inside this one (splitting). This requires a
@@ -274,7 +275,7 @@ class Block {
274275 // So the maximum distance would be G - L. As a special case, if L is 1
275276 // (unaligned), the max distance is G - 1.
276277 //
277- // This block's usable space is aligned to max_align_t >= Block. With zero
278+ // This block's usable space is aligned to MIN_ALIGN >= Block. With zero
278279 // padding, the next block's usable space is sizeof(Block) past it, which is
279280 // a point aligned to Block. Thus the max padding needed is alignment -
280281 // alignof(Block).
@@ -309,13 +310,15 @@ class Block {
309310 static BlockInfo allocate (Block *block, size_t alignment, size_t size);
310311
311312 // These two functions may wrap around.
312- LIBC_INLINE static uintptr_t next_possible_block_start (
313- uintptr_t ptr, size_t usable_space_alignment = alignof (max_align_t )) {
313+ LIBC_INLINE static uintptr_t
314+ next_possible_block_start (uintptr_t ptr,
315+ size_t usable_space_alignment = MIN_ALIGN) {
314316 return align_up (ptr + sizeof (Block), usable_space_alignment) -
315317 sizeof (Block);
316318 }
317- LIBC_INLINE static uintptr_t prev_possible_block_start (
318- uintptr_t ptr, size_t usable_space_alignment = alignof (max_align_t )) {
319+ LIBC_INLINE static uintptr_t
320+ prev_possible_block_start (uintptr_t ptr,
321+ size_t usable_space_alignment = MIN_ALIGN) {
319322 return align_down (ptr, usable_space_alignment) - sizeof (Block);
320323 }
321324
@@ -360,9 +363,6 @@ class Block {
360363 static constexpr size_t PREV_FIELD_SIZE = sizeof (prev_);
361364};
362365
363- static_assert (alignof (Block) >= 4 ,
364- " at least 2 bits must be available in block sizes for flags" );
365-
366366LIBC_INLINE
367367optional<Block *> Block::init (ByteSpan region) {
368368 if (!region.data ())
@@ -394,8 +394,8 @@ optional<Block *> Block::init(ByteSpan region) {
394394
395395LIBC_INLINE
396396Block::BlockInfo Block::allocate (Block *block, size_t alignment, size_t size) {
397- LIBC_ASSERT (alignment % alignof ( max_align_t ) == 0 &&
398- " alignment must be a multiple of max_align_t " );
397+ LIBC_ASSERT (alignment % MIN_ALIGN == 0 &&
398+ " alignment must be a multiple of MIN_ALIGN " );
399399
400400 BlockInfo info{block, /* prev=*/ nullptr , /* next=*/ nullptr };
401401
@@ -430,8 +430,8 @@ Block::BlockInfo Block::allocate(Block *block, size_t alignment, size_t size) {
430430LIBC_INLINE
431431optional<Block *> Block::split (size_t new_inner_size,
432432 size_t usable_space_alignment) {
433- LIBC_ASSERT (usable_space_alignment % alignof ( max_align_t ) == 0 &&
434- " alignment must be a multiple of max_align_t " );
433+ LIBC_ASSERT (usable_space_alignment % MIN_ALIGN == 0 &&
434+ " alignment must be a multiple of MIN_ALIGN " );
435435 if (used ())
436436 return {};
437437
@@ -445,8 +445,8 @@ optional<Block *> Block::split(size_t new_inner_size,
445445 if (next_block_start < start)
446446 return {};
447447 size_t new_outer_size = next_block_start - start;
448- LIBC_ASSERT (new_outer_size % alignof ( max_align_t ) == 0 &&
449- " new size must be aligned to max_align_t " );
448+ LIBC_ASSERT (new_outer_size % MIN_ALIGN == 0 &&
449+ " new size must be aligned to MIN_ALIGN " );
450450
451451 if (outer_size () < new_outer_size ||
452452 outer_size () - new_outer_size < sizeof (Block))
0 commit comments