aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2023-11-09 10:20:54 +0100
committerbfredl <bjorn.linse@gmail.com>2023-11-09 21:55:21 +0100
commit74581ec7ebd5f9b3d47f6b1ee04a87327ad730a1 (patch)
tree19a28d0d6fa2e9f900acb48bd63dd2a1cf5d0d80
parent3128cff6b198daabfddeedd382c0b8707319504f (diff)
downloadrneovim-74581ec7ebd5f9b3d47f6b1ee04a87327ad730a1.tar.gz
rneovim-74581ec7ebd5f9b3d47f6b1ee04a87327ad730a1.tar.bz2
rneovim-74581ec7ebd5f9b3d47f6b1ee04a87327ad730a1.zip
refactor(drawline): avoid xmalloc/xfree cycles on each screenline
-rw-r--r--src/nvim/drawline.c61
-rw-r--r--src/nvim/memory.c2
2 files changed, 37 insertions, 26 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index c353583dfa..b5438e649c 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -101,7 +101,6 @@ typedef struct {
int n_attr; ///< chars with special attr
char *p_extra; ///< string of extra chars, plus NUL, only used
///< when c_extra and c_final are NUL
- char *p_extra_free; ///< p_extra buffer that needs to be freed
int extra_attr; ///< attributes for p_extra
int c_extra; ///< extra chars, all the same
int c_final; ///< final char, mandatory if set
@@ -113,7 +112,6 @@ typedef struct {
// saved "extra" items for when draw_state becomes WL_LINE (again)
int saved_n_extra;
char *saved_p_extra;
- char *saved_p_extra_free;
bool saved_extra_for_extmark;
int saved_c_extra;
int saved_c_final;
@@ -147,6 +145,27 @@ typedef struct {
# include "drawline.c.generated.h"
#endif
+static char *extra_buf = NULL;
+static size_t extra_buf_size = 0;
+
+static char *get_extra_buf(size_t size)
+{
+ size = MAX(size, 64);
+ if (extra_buf_size < size) {
+ xfree(extra_buf);
+ extra_buf = xmalloc(size);
+ extra_buf_size = size;
+ }
+ return extra_buf;
+}
+
+#ifdef EXITFREE
+void drawline_free_all_mem(void)
+{
+ xfree(extra_buf);
+}
+#endif
+
/// Advance **color_cols
///
/// @return true when there are columns to draw.
@@ -349,6 +368,8 @@ static bool use_cursor_line_highlight(win_T *wp, linenr_T lnum)
&& (wp->w_p_culopt_flags & CULOPT_NBR);
}
+static char fdc_buf[MB_MAXCHAR * 10 + 1];
+
/// Setup for drawing the 'foldcolumn', if there is one.
static void handle_foldcolumn(win_T *wp, winlinevars_T *wlv)
{
@@ -357,13 +378,11 @@ static void handle_foldcolumn(win_T *wp, winlinevars_T *wlv)
return;
}
- // Allocate a buffer, "wlv->extra[]" may already be in use.
- xfree(wlv->p_extra_free);
- wlv->p_extra_free = xmalloc(MAX_MCO * (size_t)fdc + 1);
- wlv->n_extra = (int)fill_foldcolumn(wlv->p_extra_free, wp, wlv->foldinfo, wlv->lnum,
+ // Use a separate buffer as `extra_buf` might be in use.
+ wlv->n_extra = (int)fill_foldcolumn(fdc_buf, wp, wlv->foldinfo, wlv->lnum,
&wlv->n_closing);
- wlv->p_extra_free[wlv->n_extra] = NUL;
- wlv->p_extra = wlv->p_extra_free;
+ fdc_buf[wlv->n_extra] = NUL;
+ wlv->p_extra = fdc_buf;
wlv->c_extra = NUL;
wlv->c_final = NUL;
if (use_cursor_line_highlight(wp, wlv->lnum)) {
@@ -393,7 +412,7 @@ size_t fill_foldcolumn(char *p, win_T *wp, foldinfo_T foldinfo, linenr_T lnum, i
int len = 0;
bool closed = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
// Init to all spaces.
- memset(p, ' ', MAX_MCO * (size_t)fdc + 1);
+ memset(p, ' ', MB_MAXCHAR * (size_t)fdc + 1);
level = foldinfo.fi_level;
@@ -991,9 +1010,6 @@ static void win_line_start(win_T *wp, winlinevars_T *wlv, bool save_extra)
wlv->draw_state = WL_START;
wlv->saved_n_extra = wlv->n_extra;
wlv->saved_p_extra = wlv->p_extra;
- xfree(wlv->saved_p_extra_free);
- wlv->saved_p_extra_free = wlv->p_extra_free;
- wlv->p_extra_free = NULL;
wlv->saved_extra_for_extmark = wlv->extra_for_extmark;
wlv->saved_c_extra = wlv->c_extra;
wlv->saved_c_final = wlv->c_final;
@@ -1014,9 +1030,6 @@ static void win_line_continue(winlinevars_T *wlv)
wlv->c_extra = wlv->saved_c_extra;
wlv->c_final = wlv->saved_c_final;
wlv->p_extra = wlv->saved_p_extra;
- xfree(wlv->p_extra_free);
- wlv->p_extra_free = wlv->saved_p_extra_free;
- wlv->saved_p_extra_free = NULL;
wlv->extra_for_extmark = wlv->saved_extra_for_extmark;
wlv->char_attr = wlv->saved_char_attr;
} else {
@@ -1111,6 +1124,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
char buf_fold[FOLD_TEXT_LEN]; // Hold value returned by get_foldtext
VirtText fold_vt = VIRTTEXT_EMPTY;
+ char *foldtext_free = NULL;
// 'cursorlineopt' has "screenline" and cursor is in this line
bool cul_screenline = false;
@@ -1908,8 +1922,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
wlv.n_extra = (int)strlen(wlv.p_extra);
if (wlv.p_extra != buf_fold) {
- xfree(wlv.p_extra_free);
- wlv.p_extra_free = wlv.p_extra;
+ foldtext_free = wlv.p_extra;
}
wlv.c_extra = NUL;
wlv.c_final = NUL;
@@ -2415,11 +2428,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
len += wlv.n_extra - tab_len;
}
c = wp->w_p_lcs_chars.tab1;
- p = xmalloc((size_t)len + 1);
+ p = get_extra_buf((size_t)len + 1);
memset(p, ' ', (size_t)len);
p[len] = NUL;
- xfree(wlv.p_extra_free);
- wlv.p_extra_free = p;
+ wlv.p_extra = p;
for (int i = 0; i < tab_len; i++) {
if (*p == NUL) {
tab_len = i;
@@ -2434,7 +2446,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
p += utf_char2bytes(lcs, p);
wlv.n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0);
}
- wlv.p_extra = wlv.p_extra_free;
// n_extra will be increased by FIX_FOX_BOGUSCOLS
// macro below, so need to adjust for that here
@@ -2533,14 +2544,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
char *p;
c = (uint8_t)(*wlv.p_extra);
- p = xmalloc((size_t)wlv.n_extra + 1);
+ p = get_extra_buf((size_t)wlv.n_extra + 1);
memset(p, ' ', (size_t)wlv.n_extra);
strncpy(p, // NOLINT(runtime/printf)
wlv.p_extra + 1,
(size_t)strlen(wlv.p_extra) - 1);
p[wlv.n_extra] = NUL;
- xfree(wlv.p_extra_free);
- wlv.p_extra_free = wlv.p_extra = p;
+ wlv.p_extra = p;
} else {
wlv.n_extra = byte2cells(c) - 1;
c = (uint8_t)(*wlv.p_extra++);
@@ -3141,8 +3151,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
clear_virttext(&fold_vt);
kv_destroy(virt_lines);
- xfree(wlv.p_extra_free);
- xfree(wlv.saved_p_extra_free);
+ xfree(foldtext_free);
return wlv.row;
}
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index fdfd63e25f..27b1bfc105 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -17,6 +17,7 @@
#include "nvim/buffer_updates.h"
#include "nvim/context.h"
#include "nvim/decoration_provider.h"
+#include "nvim/drawline.h"
#include "nvim/eval.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
@@ -818,6 +819,7 @@ void free_all_mem(void)
check_quickfix_busy();
decor_free_all_mem();
+ drawline_free_all_mem();
ui_free_all_mem();
nlua_free_all_mem();