mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 11:58:17 +00:00
refactor(memory): simplify new alignment logic
In particular, we can assume the xmalloc-ed pointer is at least
double-aligned, otherwise nothing work work.
(cherry picked from commit 8b7247af7d
)
This commit is contained in:

committed by
github-actions[bot]
![github-actions[bot]](/assets/img/avatar_default.png)
parent
9c32331904
commit
41192dae78
@@ -577,14 +577,13 @@ void alloc_block(Arena *arena)
|
|||||||
blk->prev = prev_blk;
|
blk->prev = prev_blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t arena_align_offset(void *ptr, size_t alignment)
|
static size_t arena_align_offset(uint64_t off)
|
||||||
{
|
{
|
||||||
uintptr_t uptr = (uintptr_t)ptr;
|
return ((off + (ARENA_ALIGN - 1)) & ~(ARENA_ALIGN - 1));
|
||||||
return ((uptr + (alignment - 1)) & ~(alignment - 1)) - uptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param arena if NULL, do a global allocation. caller must then free the value!
|
/// @param arena if NULL, do a global allocation. caller must then free the value!
|
||||||
/// @param size if zero, will still return a non-null pointer, but not a unique one
|
/// @param size if zero, will still return a non-null pointer, but not a usable or unique one
|
||||||
void *arena_alloc(Arena *arena, size_t size, bool align)
|
void *arena_alloc(Arena *arena, size_t size, bool align)
|
||||||
{
|
{
|
||||||
if (!arena) {
|
if (!arena) {
|
||||||
@@ -593,30 +592,33 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
|
|||||||
if (!arena->cur_blk) {
|
if (!arena->cur_blk) {
|
||||||
alloc_block(arena);
|
alloc_block(arena);
|
||||||
}
|
}
|
||||||
size_t align_pos = align ? arena_align_offset(arena->cur_blk + arena->pos, ARENA_ALIGN) : 0;
|
size_t alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos;
|
||||||
if (arena->pos + align_pos + size > arena->size) {
|
if (alloc_pos + size > arena->size) {
|
||||||
if (size + (align ? (ARENA_ALIGN - 1) : 0) > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk))
|
if (size > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk)) >> 1) {
|
||||||
>> 1) {
|
|
||||||
// if allocation is too big, allocate a large block with the requested
|
// if allocation is too big, allocate a large block with the requested
|
||||||
// size, but still with block pointer head. We do this even for
|
// size, but still with block pointer head. We do this even for
|
||||||
// arena->size / 2, as there likely is space left for the next
|
// arena->size / 2, as there likely is space left for the next
|
||||||
// small allocation in the current block.
|
// small allocation in the current block.
|
||||||
arena_alloc_count++;
|
arena_alloc_count++;
|
||||||
char *alloc = xmalloc(size + sizeof(struct consumed_blk) + (align ? (ARENA_ALIGN - 1) : 0));
|
size_t hdr_size = sizeof(struct consumed_blk);
|
||||||
|
size_t aligned_hdr_size = (align ? arena_align_offset(hdr_size) : hdr_size);
|
||||||
|
char *alloc = xmalloc(size + aligned_hdr_size);
|
||||||
|
|
||||||
|
// to simplify free-list management, arena->cur_blk must
|
||||||
|
// always be a normal, ARENA_BLOCK_SIZE sized, block
|
||||||
struct consumed_blk *cur_blk = (struct consumed_blk *)arena->cur_blk;
|
struct consumed_blk *cur_blk = (struct consumed_blk *)arena->cur_blk;
|
||||||
struct consumed_blk *fix_blk = (struct consumed_blk *)alloc;
|
struct consumed_blk *fix_blk = (struct consumed_blk *)alloc;
|
||||||
fix_blk->prev = cur_blk->prev;
|
fix_blk->prev = cur_blk->prev;
|
||||||
cur_blk->prev = fix_blk;
|
cur_blk->prev = fix_blk;
|
||||||
char *mem = (alloc + sizeof(struct consumed_blk));
|
return alloc + aligned_hdr_size;
|
||||||
return mem + (align ? arena_align_offset(mem, ARENA_ALIGN) : 0);
|
|
||||||
} else {
|
} else {
|
||||||
alloc_block(arena);
|
alloc_block(arena); // resets arena->pos
|
||||||
align_pos = align ? arena_align_offset(arena->cur_blk + arena->pos, ARENA_ALIGN) : 0;
|
alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mem = arena->cur_blk + arena->pos + align_pos;
|
char *mem = arena->cur_blk + alloc_pos;
|
||||||
arena->pos += (size + align_pos);
|
arena->pos = alloc_pos + size;
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user