diff options
Diffstat (limited to 'src/nvim/memline.c')
-rw-r--r-- | src/nvim/memline.c | 43 |
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--; |