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.c134
1 files changed, 92 insertions, 42 deletions
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index df6c81fe0d..37e53e4453 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -9,29 +9,38 @@
#include <time.h>
#include "nvim/api/extmark.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/api/ui.h"
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
+#include "nvim/channel.h"
#include "nvim/context.h"
#include "nvim/decoration_provider.h"
#include "nvim/drawline.h"
#include "nvim/eval.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/insexpand.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
+#include "nvim/map_defs.h"
#include "nvim/mapping.h"
#include "nvim/memfile.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_vars.h"
+#include "nvim/os/input.h"
#include "nvim/sign.h"
#include "nvim/state_defs.h"
+#include "nvim/statusline.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_client.h"
+#include "nvim/ui_compositor.h"
#include "nvim/usercmd.h"
#include "nvim/vim_defs.h"
@@ -279,7 +288,8 @@ void strchrsub(char *str, char c, char x)
void memchrsub(void *data, char c, char x, size_t len)
FUNC_ATTR_NONNULL_ALL
{
- char *p = data, *end = (char *)data + len;
+ char *p = data;
+ char *end = (char *)data + len;
while ((p = memchr(p, c, (size_t)(end - p)))) {
*p++ = x;
}
@@ -314,7 +324,8 @@ size_t memcnt(const void *data, char c, size_t len)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
{
size_t cnt = 0;
- const char *ptr = data, *end = ptr + len;
+ const char *ptr = data;
+ const char *end = ptr + len;
while ((ptr = memchr(ptr, c, (size_t)(end - ptr))) != NULL) {
cnt++;
ptr++; // Skip the instance of c.
@@ -508,6 +519,13 @@ bool strequal(const char *a, const char *b)
return (a == NULL && b == NULL) || (a && b && strcmp(a, b) == 0);
}
+/// Returns true if first `n` characters of strings `a` and `b` are equal. Arguments may be NULL.
+bool strnequal(const char *a, const char *b, size_t n)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return (a == NULL && b == NULL) || (a && b && strncmp(a, b, n) == 0);
+}
+
// Avoid repeating the error message many times (they take 1 second each).
// Did_outofmem_msg is reset when a character is read.
void do_outofmem_msg(size_t size)
@@ -536,7 +554,6 @@ void time_to_bytes(time_t time_, uint8_t buf[8])
}
}
-#define ARENA_BLOCK_SIZE 4096
#define REUSE_MAX 4
static struct consumed_blk *arena_reuse_blk;
@@ -565,17 +582,26 @@ ArenaMem arena_finish(Arena *arena)
return res;
}
-void alloc_block(Arena *arena)
+/// allocate a block of ARENA_BLOCK_SIZE
+///
+/// free it with free_block
+void *alloc_block(void)
{
- struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk;
if (arena_reuse_blk_count > 0) {
- arena->cur_blk = (char *)arena_reuse_blk;
+ void *retval = (char *)arena_reuse_blk;
arena_reuse_blk = arena_reuse_blk->prev;
arena_reuse_blk_count--;
+ return retval;
} else {
arena_alloc_count++;
- arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
+ return xmalloc(ARENA_BLOCK_SIZE);
}
+}
+
+void arena_alloc_block(Arena *arena)
+{
+ struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk;
+ arena->cur_blk = alloc_block();
arena->pos = 0;
arena->size = ARENA_BLOCK_SIZE;
struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
@@ -597,7 +623,7 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
return xmalloc(size);
}
if (!arena->cur_blk) {
- alloc_block(arena);
+ arena_alloc_block(arena);
}
size_t alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos;
if (alloc_pos + size > arena->size) {
@@ -619,7 +645,7 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
cur_blk->prev = fix_blk;
return alloc + aligned_hdr_size;
} else {
- alloc_block(arena); // resets arena->pos
+ arena_alloc_block(arena); // resets arena->pos
alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos;
}
}
@@ -629,17 +655,27 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
return mem;
}
+void free_block(void *block)
+{
+ if (arena_reuse_blk_count < REUSE_MAX) {
+ struct consumed_blk *reuse_blk = block;
+ reuse_blk->prev = arena_reuse_blk;
+ arena_reuse_blk = reuse_blk;
+ arena_reuse_blk_count++;
+ } else {
+ xfree(block);
+ }
+}
+
void arena_mem_free(ArenaMem mem)
{
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 (arena_reuse_blk_count < REUSE_MAX && b != NULL) {
+ if (b != NULL) {
struct consumed_blk *reuse_blk = b;
b = b->prev;
- reuse_blk->prev = arena_reuse_blk;
- arena_reuse_blk = reuse_blk;
- arena_reuse_blk_count++;
+ free_block(reuse_blk);
}
while (b) {
@@ -649,14 +685,20 @@ void arena_mem_free(ArenaMem mem)
}
}
-char *arena_memdupz(Arena *arena, const char *buf, size_t size)
+char *arena_allocz(Arena *arena, size_t size)
{
char *mem = arena_alloc(arena, size + 1, false);
- memcpy(mem, buf, size);
mem[size] = NUL;
return mem;
}
+char *arena_memdupz(Arena *arena, const char *buf, size_t size)
+{
+ char *mem = arena_allocz(arena, size);
+ memcpy(mem, buf, size);
+ return mem;
+}
+
#if defined(EXITFREE)
# include "nvim/autocmd.h"
@@ -705,13 +747,6 @@ void free_all_mem(void)
do_cmdline_cmd("tabonly!");
}
- if (!ONE_WINDOW) {
- // to keep things simple, don't perform this
- // ritual inside a float
- curwin = firstwin;
- do_cmdline_cmd("only!");
- }
-
// Free all spell info.
spell_free_all();
@@ -739,6 +774,7 @@ void free_all_mem(void)
free_all_marks();
alist_clear(&global_alist);
free_homedir();
+ free_envmap();
free_users();
free_search_patterns();
free_old_sub();
@@ -773,6 +809,25 @@ void free_all_mem(void)
// Free all option values. Must come after closing windows.
free_all_options();
+ // Free all buffers. Reset 'autochdir' to avoid accessing things that
+ // were freed already.
+ // Must be after eval_clear to avoid it trying to access b:changedtick after
+ // freeing it.
+ p_acd = false;
+ for (buf = firstbuf; buf != NULL;) {
+ bufref_T bufref;
+ set_bufref(&bufref, buf);
+ nextbuf = buf->b_next;
+
+ // Since options (in addition to other stuff) have been freed above we need to ensure no
+ // callbacks are called, so free them before closing the buffer.
+ buf_free_callbacks(buf);
+
+ close_buffer(NULL, buf, DOBUF_WIPE, false, false);
+ // Didn't work, try next one.
+ buf = bufref_valid(&bufref) ? nextbuf : firstbuf;
+ }
+
// Clear registers.
clear_registers();
ResetRedobuff();
@@ -793,31 +848,19 @@ void free_all_mem(void)
}
}
+ channel_free_all_mem();
eval_clear();
api_extmark_free_all_mem();
ctx_free_all();
- // Free all buffers. Reset 'autochdir' to avoid accessing things that
- // were freed already.
- // Must be after eval_clear to avoid it trying to access b:changedtick after
- // freeing it.
- p_acd = false;
- for (buf = firstbuf; buf != NULL;) {
- bufref_T bufref;
- set_bufref(&bufref, buf);
- nextbuf = buf->b_next;
-
- // Since options (in addition to other stuff) have been freed above we need to ensure no
- // callbacks are called, so free them before closing the buffer.
- buf_free_callbacks(buf);
-
- close_buffer(NULL, buf, DOBUF_WIPE, false, false);
- // Didn't work, try next one.
- buf = bufref_valid(&bufref) ? nextbuf : firstbuf;
- }
+ map_destroy(int, &buffer_handles);
+ map_destroy(int, &window_handles);
+ map_destroy(int, &tabpage_handles);
// free screenlines (can't display anything now!)
grid_free_all_mem();
+ stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
+ xfree(tab_page_click_defs);
clear_hl_tables(false);
@@ -825,8 +868,15 @@ void free_all_mem(void)
decor_free_all_mem();
drawline_free_all_mem();
+ input_free_all_mem();
+
+ if (ui_client_channel_id) {
+ ui_client_free_all_mem();
+ }
+ remote_ui_free_all_mem();
ui_free_all_mem();
+ ui_comp_free_all_mem();
nlua_free_all_mem();
rpc_free_all_mem();