aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/memory.c')
-rw-r--r--src/nvim/memory.c110
1 files changed, 99 insertions, 11 deletions
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 677ff8f522..4d5cf047f9 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -10,10 +10,12 @@
#include "nvim/api/extmark.h"
#include "nvim/context.h"
-#include "nvim/decoration.h"
+#include "nvim/decoration_provider.h"
#include "nvim/eval.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
+#include "nvim/mapping.h"
#include "nvim/memfile.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -523,6 +525,95 @@ void time_to_bytes(time_t time_, uint8_t buf[8])
}
}
+#define ARENA_BLOCK_SIZE 4096
+
+void arena_start(Arena *arena, ArenaMem *reuse_blk)
+{
+ if (reuse_blk && *reuse_blk) {
+ arena->cur_blk = (char *)(*reuse_blk);
+ *reuse_blk = NULL;
+ } else {
+ arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
+ }
+ arena->pos = 0;
+ arena->size = ARENA_BLOCK_SIZE;
+ // address is the same as as (struct consumed_blk *)arena->cur_blk
+ struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
+ assert((char *)blk == (char *)arena->cur_blk);
+ blk->prev = NULL;
+}
+
+/// Finnish the allocations in an arena.
+///
+/// This does not immedately free the memory, but leaves existing allocated
+/// objects valid, and returns an opaque ArenaMem handle, which can be used to
+/// free the allocations using `arena_mem_free`, when the objects allocated
+/// from the arena are not needed anymore.
+ArenaMem arena_finish(Arena *arena)
+{
+ struct consumed_blk *res = (struct consumed_blk *)arena->cur_blk;
+ *arena = (Arena)ARENA_EMPTY;
+ return res;
+}
+
+void *arena_alloc(Arena *arena, size_t size, bool align)
+{
+ if (align) {
+ arena->pos = (arena->pos + (ARENA_ALIGN - 1)) & ~(ARENA_ALIGN - 1);
+ }
+ if (arena->pos + size > arena->size) {
+ if (size > (arena->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.
+ char *alloc = xmalloc(size + sizeof(struct consumed_blk));
+ 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;
+ return (alloc + sizeof(struct consumed_blk));
+ } else {
+ struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk;
+ arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
+ arena->pos = 0;
+ arena->size = ARENA_BLOCK_SIZE;
+ struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
+ blk->prev = prev_blk;
+ }
+ }
+
+ char *mem = arena->cur_blk + arena->pos;
+ arena->pos += size;
+ return mem;
+}
+
+void arena_mem_free(ArenaMem mem, ArenaMem *reuse_blk)
+{
+ struct consumed_blk *b = mem;
+ // peel of the first block, as it is guaranteed to be ARENA_BLOCK_SIZE,
+ // not a custom fix_blk
+ if (reuse_blk && *reuse_blk == NULL && b != NULL) {
+ *reuse_blk = b;
+ b = b->prev;
+ (*reuse_blk)->prev = NULL;
+ }
+
+ while (b) {
+ struct consumed_blk *prev = b->prev;
+ xfree(b);
+ b = prev;
+ }
+}
+
+char *arena_memdupz(Arena *arena, const char *buf, size_t size)
+{
+ char *mem = arena_alloc(arena, size + 1, false);
+ memcpy(mem, buf, size);
+ mem[size] = NUL;
+ return mem;
+}
+
#if defined(EXITFREE)
# include "nvim/buffer.h"
@@ -596,14 +687,13 @@ void free_all_mem(void)
// Clear menus.
do_cmdline_cmd("aunmenu *");
+ do_cmdline_cmd("tlunmenu *");
do_cmdline_cmd("menutranslate clear");
// Clear mappings, abbreviations, breakpoints.
- do_cmdline_cmd("lmapclear");
- do_cmdline_cmd("xmapclear");
- do_cmdline_cmd("mapclear");
- do_cmdline_cmd("mapclear!");
- do_cmdline_cmd("abclear");
+ // NB: curbuf not used with local=false arg
+ map_clear_mode(curbuf, MAP_ALL_MODES, false, false);
+ map_clear_mode(curbuf, MAP_ALL_MODES, false, true);
do_cmdline_cmd("breakdel *");
do_cmdline_cmd("profdel *");
do_cmdline_cmd("set keymap=");
@@ -630,7 +720,6 @@ void free_all_mem(void)
clear_sb_text(true); // free any scrollback text
// Free some global vars.
- xfree(last_mode);
xfree(last_cmdline);
xfree(new_last_cmdline);
set_keep_msg(NULL, 0);
@@ -661,7 +750,6 @@ void free_all_mem(void)
ResetRedobuff();
ResetRedobuff();
-
// highlight info
free_highlight();
@@ -690,13 +778,13 @@ void free_all_mem(void)
bufref_T bufref;
set_bufref(&bufref, buf);
nextbuf = buf->b_next;
- close_buffer(NULL, buf, DOBUF_WIPE, false);
+ close_buffer(NULL, buf, DOBUF_WIPE, false, false);
// Didn't work, try next one.
buf = bufref_valid(&bufref) ? nextbuf : firstbuf;
}
// free screenlines (can't display anything now!)
- screen_free_all_mem();
+ grid_free_all_mem();
clear_hl_tables(false);
list_free_log();
@@ -706,7 +794,7 @@ void free_all_mem(void)
decor_free_all_mem();
nlua_free_all_mem();
+ ui_free_all_mem();
}
#endif
-