diff options
author | bfredl <bjorn.linse@gmail.com> | 2022-10-31 10:07:21 +0100 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2022-10-31 11:12:55 +0100 |
commit | 8b7247af7dc613a7e4248ba14760f586a8a66a32 (patch) | |
tree | 381bf1b8cea3bd12ee5868da99eca1fb1775c3bc /src | |
parent | 0240fd6d0f7e27c459b243578ad51100ff6e2b66 (diff) | |
download | rneovim-8b7247af7dc613a7e4248ba14760f586a8a66a32.tar.gz rneovim-8b7247af7dc613a7e4248ba14760f586a8a66a32.tar.bz2 rneovim-8b7247af7dc613a7e4248ba14760f586a8a66a32.zip |
refactor(memory): simplify new alignment logic
In particular, we can assume the xmalloc-ed pointer is at least
double-aligned, otherwise nothing work work.
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/memory.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 93aa9bd6e5..16033e9c63 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -577,14 +577,13 @@ void alloc_block(Arena *arena) 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 ((uptr + (alignment - 1)) & ~(alignment - 1)) - uptr; + return ((off + (ARENA_ALIGN - 1)) & ~(ARENA_ALIGN - 1)); } /// @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) { if (!arena) { @@ -593,30 +592,33 @@ void *arena_alloc(Arena *arena, size_t size, bool align) if (!arena->cur_blk) { alloc_block(arena); } - size_t align_pos = align ? arena_align_offset(arena->cur_blk + arena->pos, ARENA_ALIGN) : 0; - if (arena->pos + align_pos + size > arena->size) { - if (size + (align ? (ARENA_ALIGN - 1) : 0) > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk)) - >> 1) { + size_t alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos; + if (alloc_pos + size > arena->size) { + if (size > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk)) >> 1) { // if allocation is too big, allocate a large block with the requested // size, but still with block pointer head. We do this even for // arena->size / 2, as there likely is space left for the next // small allocation in the current block. 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 *fix_blk = (struct consumed_blk *)alloc; fix_blk->prev = cur_blk->prev; cur_blk->prev = fix_blk; - char *mem = (alloc + sizeof(struct consumed_blk)); - return mem + (align ? arena_align_offset(mem, ARENA_ALIGN) : 0); + return alloc + aligned_hdr_size; } else { - alloc_block(arena); - align_pos = align ? arena_align_offset(arena->cur_blk + arena->pos, ARENA_ALIGN) : 0; + alloc_block(arena); // resets arena->pos + alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos; } } - char *mem = arena->cur_blk + arena->pos + align_pos; - arena->pos += (size + align_pos); + char *mem = arena->cur_blk + alloc_pos; + arena->pos = alloc_pos + size; return mem; } |