aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/memline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/memline.c')
-rw-r--r--src/nvim/memline.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index e463f66714..6b2f26b2d8 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -1694,7 +1694,7 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync)
if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL) {
continue; // no file
}
- ml_flush_line(buf); // flush buffered line
+ ml_flush_line(buf, false); // flush buffered line
// flush locked block
ml_find_line(buf, 0, ML_FLUSH);
if (bufIsChanged(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp)
@@ -1745,7 +1745,7 @@ void ml_preserve(buf_T *buf, bool message, bool do_fsync)
// before.
got_int = false;
- ml_flush_line(buf); // flush buffered line
+ ml_flush_line(buf, false); // flush buffered line
ml_find_line(buf, 0, ML_FLUSH); // flush locked block
int status = mf_sync(mfp, MFS_ALL | (do_fsync ? MFS_FLUSH : 0));
@@ -1862,7 +1862,7 @@ static char *ml_get_buf_impl(buf_T *buf, linenr_T lnum, bool will_change)
siemsg(_(e_ml_get_invalid_lnum_nr), (int64_t)lnum);
recursive--;
}
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
errorret:
STRCPY(questions, "???");
buf->b_ml.ml_line_lnum = lnum;
@@ -1881,7 +1881,7 @@ errorret:
// Don't use the last used line when 'swapfile' is reset, need to load all
// blocks.
if (buf->b_ml.ml_line_lnum != lnum) {
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
// Find the data block containing the line.
// This also fills the stack with the blocks from the root to the data
@@ -1964,7 +1964,7 @@ int ml_append(linenr_T lnum, char *line, colnr_T len, bool newfile)
}
if (curbuf->b_ml.ml_line_lnum != 0) {
- ml_flush_line(curbuf);
+ ml_flush_line(curbuf, false);
}
return ml_append_int(curbuf, lnum, line, len, newfile, false);
}
@@ -1984,7 +1984,7 @@ int ml_append_buf(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfi
}
if (buf->b_ml.ml_line_lnum != 0) {
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
}
return ml_append_int(buf, lnum, line, len, newfile, false);
}
@@ -2423,7 +2423,7 @@ void ml_add_deleted_len_buf(buf_T *buf, char *ptr, ssize_t len)
int ml_replace(linenr_T lnum, char *line, bool copy)
{
- return ml_replace_buf(curbuf, lnum, line, copy);
+ return ml_replace_buf(curbuf, lnum, line, copy, false);
}
/// Replace line "lnum", with buffering, in current buffer.
@@ -2438,7 +2438,7 @@ int ml_replace(linenr_T lnum, char *line, bool copy)
/// changed_lines(), unless update_screen(UPD_NOT_VALID) is used.
///
/// @return FAIL for failure, OK otherwise
-int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy)
+int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy, bool noalloc)
{
if (line == NULL) { // just checking...
return FAIL;
@@ -2450,12 +2450,13 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy)
}
if (copy) {
+ assert(!noalloc);
line = xstrdup(line);
}
if (buf->b_ml.ml_line_lnum != lnum) {
// another line is buffered, flush it
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
}
if (kv_size(buf->update_callbacks)) {
@@ -2469,6 +2470,13 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy)
buf->b_ml.ml_line_ptr = line;
buf->b_ml.ml_line_lnum = lnum;
buf->b_ml.ml_flags = (buf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
+ if (noalloc) {
+ // TODO(bfredl): this is a bit of a hack. but replacing lines in a loop is really common,
+ // and allocating a separate scratch buffer for each line which is immediately freed adds
+ // a lot of noise. A more general refactor could be to use a _fixed_ scratch buffer for
+ // all lines up to $REASONABLE_SIZE .
+ ml_flush_line(buf, true);
+ }
return OK;
}
@@ -2483,7 +2491,7 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy)
/// @return FAIL for failure, OK otherwise
int ml_delete(linenr_T lnum, bool message)
{
- ml_flush_line(curbuf);
+ ml_flush_line(curbuf, false);
return ml_delete_int(curbuf, lnum, message);
}
@@ -2496,7 +2504,7 @@ int ml_delete(linenr_T lnum, bool message)
/// @return FAIL for failure, OK otherwise
int ml_delete_buf(buf_T *buf, linenr_T lnum, bool message)
{
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
return ml_delete_int(buf, lnum, message);
}
@@ -2516,7 +2524,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message)
set_keep_msg(_(no_lines_msg), 0);
}
- int i = ml_replace_buf(buf, 1, "", true);
+ int i = ml_replace_buf(buf, 1, "", true, false);
buf->b_ml.ml_flags |= ML_EMPTY;
return i;
@@ -2724,7 +2732,7 @@ size_t ml_flush_deleted_bytes(buf_T *buf, size_t *codepoints, size_t *codeunits)
}
/// flush ml_line if necessary
-static void ml_flush_line(buf_T *buf)
+static void ml_flush_line(buf_T *buf, bool noalloc)
{
static bool entered = false;
@@ -2798,10 +2806,13 @@ static void ml_flush_line(buf_T *buf)
ml_delete_int(buf, lnum, false);
}
}
- xfree(new_line);
+ if (!noalloc) {
+ xfree(new_line);
+ }
entered = false;
} else if (buf->b_ml.ml_flags & ML_ALLOCATED) {
+ assert(!noalloc); // caller must set ML_LINE_DIRTY with noalloc, handled above
xfree(buf->b_ml.ml_line_ptr);
}
@@ -3903,7 +3914,7 @@ int ml_find_line_or_offset(buf_T *buf, linenr_T lnum, int *offp, bool no_ff)
// was never cached to start with anyway).
bool can_cache = (lnum != 0 && !ffdos && buf->b_ml.ml_line_lnum == lnum);
if (lnum == 0 || buf->b_ml.ml_line_lnum < lnum || !no_ff) {
- ml_flush_line(curbuf);
+ ml_flush_line(curbuf, false);
} else if (can_cache && buf->b_ml.ml_line_offset > 0) {
return (int)buf->b_ml.ml_line_offset;
}
@@ -4030,7 +4041,7 @@ void goto_byte(int cnt)
{
int boff = cnt;
- ml_flush_line(curbuf); // cached line may be dirty
+ ml_flush_line(curbuf, false); // cached line may be dirty
setpcmark();
if (boff) {
boff--;