Commit: patch 9.2.0054: eval_addblob() is inefficient

0 views
Skip to first unread message

Christian Brabandt

unread,
Feb 25, 2026, 3:01:49 PM (7 days ago) Feb 25
to vim...@googlegroups.com
patch 9.2.0054: eval_addblob() is inefficient

Commit: https://github.com/vim/vim/commit/c389ae8c4467e93827a9737abd907ebc27b998b3
Author: Yasuhiro Matsumoto <matt...@gmail.com>
Date: Wed Feb 25 19:57:13 2026 +0000

patch 9.2.0054: eval_addblob() is inefficient

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: #19494

Signed-off-by: Yasuhiro Matsumoto <matt...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/blob.c b/src/blob.c
index 691c67958..bbdf2873d 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -165,8 +165,8 @@ blob_equal(
blob_T *b2)
{
int i;
- int len1 = blob_len(b1);
- int len2 = blob_len(b2);
+ long len1 = blob_len(b1);
+ long len2 = blob_len(b2);

// empty and NULL are considered the same
if (len1 == 0 && len2 == 0)
@@ -821,14 +821,14 @@ blob_reduce(
void
blob_reverse(blob_T *b, typval_T *rettv)
{
- int i, len = blob_len(b);
+ long i, len = blob_len(b);

for (i = 0; i < len / 2; i++)
{
- int tmp = blob_get(b, i);
+ int tmp = blob_get(b, (int)i);

- blob_set(b, i, blob_get(b, len - i - 1));
- blob_set(b, len - i - 1, tmp);
+ blob_set(b, (int)i, blob_get(b, (int)(len - i - 1)));
+ blob_set(b, (int)(len - i - 1), tmp);
}
rettv_blob_set(rettv, b);
}
@@ -841,7 +841,7 @@ f_blob2list(typval_T *argvars, typval_T *rettv)
{
blob_T *blob;
list_T *l;
- int i;
+ long i;

if (rettv_list_alloc(rettv) == FAIL)
return;
@@ -851,8 +851,8 @@ f_blob2list(typval_T *argvars, typval_T *rettv)

blob = argvars->vval.v_blob;
l = rettv->vval.v_list;
- for (i = 0; i < blob_len(blob); i++)
- list_append_number(l, blob_get(blob, i));
+ for (i = 0; i < (long)blob_len(blob); i++)
+ list_append_number(l, blob_get(blob, (int)i));
}

/*
diff --git a/src/eval.c b/src/eval.c
index da95f90e8..a23089498 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -4132,15 +4132,27 @@ eval_addblob(typval_T *tv1, typval_T *tv2)
blob_T *b1 = tv1->vval.v_blob;
blob_T *b2 = tv2->vval.v_blob;
blob_T *b = blob_alloc();
- int i;
+ long len1, len2;
+ long totallen;

if (b == NULL)
return;

- for (i = 0; i < blob_len(b1); i++)
- ga_append(&b->bv_ga, blob_get(b1, i));
- for (i = 0; i < blob_len(b2); i++)
- ga_append(&b->bv_ga, blob_get(b2, i));
+ len1 = blob_len(b1);
+ len2 = blob_len(b2);
+ totallen = len1 + len2;
+
+ if (totallen > 0 && totallen <= INT_MAX
+ && ga_grow(&b->bv_ga, (int)totallen) == OK)
+ {
+ if (len1 > 0)
+ mch_memmove((char_u *)b->bv_ga.ga_data,
+ (char_u *)b1->bv_ga.ga_data, (size_t)len1);
+ if (len2 > 0)
+ mch_memmove((char_u *)b->bv_ga.ga_data + len1,
+ (char_u *)b2->bv_ga.ga_data, (size_t)len2);
+ b->bv_ga.ga_len = (int)totallen;
+ }

clear_tv(tv1);
rettv_blob_set(tv1, b);
diff --git a/src/version.c b/src/version.c
index fe8ce15a1..473a64fb5 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 54,
/**/
53,
/**/
Reply all
Reply to author
Forward
0 new messages