commit 1fe1b2525f7e54dee17a3303e2a2f1f184ef5493
parent 9288357d59d2c6bbc88c7db4eda5fc888c896a90
Author: zeertzjq <zeertzjq@outlook.com>
Date: Thu, 26 Feb 2026 08:15:57 +0800
vim-patch:9.2.0054: eval_addblob() is inefficient (#38067)
Problem: eval_addblob() is inefficient
Solution: Replace per-byte ga_append() loop with a single ga_grow() and
mch_memmove() for each source blob. This eliminates N grow
checks and function call overhead for blob concatenation
(Yasuhiro Matsumoto).
closes: vim/vim#19494
https://github.com/vim/vim/commit/c389ae8c4467e93827a9737abd907ebc27b998b3
Omit the pointless int -> long changes in other functions.
Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Diffstat:
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
@@ -2233,11 +2233,19 @@ static void eval_addblob(typval_T *tv1, typval_T *tv2)
const blob_T *const b2 = tv2->vval.v_blob;
blob_T *const b = tv_blob_alloc();
- for (int i = 0; i < tv_blob_len(b1); i++) {
- ga_append(&b->bv_ga, tv_blob_get(b1, i));
- }
- for (int i = 0; i < tv_blob_len(b2); i++) {
- ga_append(&b->bv_ga, tv_blob_get(b2, i));
+ int64_t len1 = tv_blob_len(b1);
+ int64_t len2 = tv_blob_len(b2);
+ int64_t totallen = len1 + len2;
+
+ if (totallen >= 0 && totallen <= INT_MAX) {
+ ga_grow(&b->bv_ga, (int)totallen);
+ if (len1 > 0) {
+ memmove((char *)b->bv_ga.ga_data, b1->bv_ga.ga_data, (size_t)len1);
+ }
+ if (len2 > 0) {
+ memmove((char *)b->bv_ga.ga_data + len1, b2->bv_ga.ga_data, (size_t)len2);
+ }
+ b->bv_ga.ga_len = (int)totallen;
}
tv_clear(tv1);