@@ -227,15 +227,17 @@ class Block {
227227 *new (&next ()->prev_ ) size_t = outer_size ();
228228 }
229229
230- // / Marks this block as the last one in the chain. Makes next() return
231- // / nullptr.
232- LIBC_INLINE void mark_last () { next_ |= LAST_MASK; }
233-
234- LIBC_INLINE Block ( size_t outer_size) : next_(outer_size) {
235- LIBC_ASSERT ( outer_size % alignof (max_align_t ) == 0 &&
236- " block sizes must be aligned" );
230+ LIBC_INLINE Block ( size_t outer_size, bool is_last) : next_(outer_size) {
231+ // Last blocks are not usable, so they need not have sizes aligned to
232+ // max_align_t. Their lower bits must still be free, so they must be aligned
233+ // to Block.
234+ LIBC_ASSERT (
235+ outer_size % (is_last ? alignof (Block) : alignof ( max_align_t ) ) == 0 &&
236+ " block sizes must be aligned" );
237237 LIBC_ASSERT (is_usable_space_aligned (alignof (max_align_t )) &&
238238 " usable space must be aligned to a multiple of max_align_t" );
239+ if (is_last)
240+ next_ |= LAST_MASK;
239241 }
240242
241243 LIBC_INLINE bool is_usable_space_aligned (size_t alignment) const {
@@ -325,7 +327,13 @@ class Block {
325327 LIBC_ASSERT (reinterpret_cast <uintptr_t >(bytes.data ()) % alignof (Block) ==
326328 0 &&
327329 " block start must be suitably aligned" );
328- return ::new (bytes.data ()) Block (bytes.size ());
330+ return ::new (bytes.data ()) Block (bytes.size (), /* is_last=*/ false );
331+ }
332+
333+ LIBC_INLINE static void make_last_block (cpp::byte *start) {
334+ LIBC_ASSERT (reinterpret_cast <uintptr_t >(start) % alignof (Block) == 0 &&
335+ " block start must be suitably aligned" );
336+ ::new (start) Block (sizeof (Block), /* is_last=*/ true );
329337 }
330338
331339 // / Offset from this block to the previous block. 0 if this is the first
@@ -353,7 +361,7 @@ class Block {
353361 static constexpr size_t PREV_FIELD_SIZE = sizeof (prev_);
354362};
355363
356- static_assert (alignof (max_align_t ) >= 4 ,
364+ static_assert (alignof (Block ) >= 4 ,
357365 " at least 2 bits must be available in block sizes for flags" );
358366
359367LIBC_INLINE
@@ -380,9 +388,8 @@ optional<Block *> Block::init(ByteSpan region) {
380388 auto *last_start_ptr = reinterpret_cast <cpp::byte *>(last_start);
381389 Block *block =
382390 as_block ({reinterpret_cast <cpp::byte *>(block_start), last_start_ptr});
383- Block *last = as_block ({ last_start_ptr, sizeof (Block)} );
391+ make_last_block ( last_start_ptr);
384392 block->mark_free ();
385- last->mark_last ();
386393 return block;
387394}
388395
0 commit comments