aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lua
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2021-08-28 11:42:43 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2021-08-28 16:52:01 +0200
commit705e8f10ac83f32dea5bfa0569aba12a692fe522 (patch)
treecb98ca33c25cdcc127a167ae557fb6af398ae44f /src/nvim/lua
parent469652d0d5540f646a52edda853e7d87e879d457 (diff)
downloadrneovim-705e8f10ac83f32dea5bfa0569aba12a692fe522.tar.gz
rneovim-705e8f10ac83f32dea5bfa0569aba12a692fe522.tar.bz2
rneovim-705e8f10ac83f32dea5bfa0569aba12a692fe522.zip
perf(api): avoid spurious allocations when converting small objects
Converter functions use a heap-allocated stack to handle complex nested objects. However, these are often called with simple, primitive values like integers or bools wrapped in an Object. Avoid the memory allocation in this case using kvec_withinit_t
Diffstat (limited to 'src/nvim/lua')
-rw-r--r--src/nvim/lua/converter.c40
1 files changed, 21 insertions, 19 deletions
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index ce8c9b0d06..1a59cd94ae 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -196,8 +196,9 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
{
bool ret = true;
const int initial_size = lua_gettop(lstate);
- kvec_t(TVPopStackItem) stack = KV_INITIAL_VALUE;
- kv_push(stack, ((TVPopStackItem) { ret_tv, false, false, 0 }));
+ kvec_withinit_t(TVPopStackItem, 2) stack = KV_INITIAL_VALUE;
+ kvi_init(stack);
+ kvi_push(stack, ((TVPopStackItem) { ret_tv, false, false, 0 }));
while (ret && kv_size(stack)) {
if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) {
emsgf(_("E1502: Lua failed to grow stack to %i"), lua_gettop(lstate) + 3);
@@ -234,7 +235,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
tv_list_append_owned_tv(kv_pair, (typval_T) {
.v_type = VAR_UNKNOWN,
});
- kv_push(stack, cur);
+ kvi_push(stack, cur);
tv_list_append_list(cur.tv->vval.v_list, kv_pair);
cur = (TVPopStackItem) {
.tv = TV_LIST_ITEM_TV(tv_list_last(kv_pair)),
@@ -247,7 +248,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
if (tv_dict_add(cur.tv->vval.v_dict, di) == FAIL) {
abort();
}
- kv_push(stack, cur);
+ kvi_push(stack, cur);
cur = (TVPopStackItem) { &di->di_tv, false, false, 0 };
}
} else {
@@ -265,7 +266,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
tv_list_append_owned_tv(cur.tv->vval.v_list, (typval_T) {
.v_type = VAR_UNKNOWN,
});
- kv_push(stack, cur);
+ kvi_push(stack, cur);
// TODO(ZyX-I): Use indexes, here list item *will* be reallocated.
cur = (TVPopStackItem) {
.tv = TV_LIST_ITEM_TV(tv_list_last(cur.tv->vval.v_list)),
@@ -343,7 +344,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
if (table_props.maxidx != 0) {
cur.container = true;
cur.idx = lua_gettop(lstate);
- kv_push(stack, cur);
+ kvi_push(stack, cur);
}
break;
}
@@ -373,7 +374,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
}
cur.container = true;
cur.idx = lua_gettop(lstate);
- kv_push(stack, cur);
+ kvi_push(stack, cur);
lua_pushnil(lstate);
}
break;
@@ -434,7 +435,7 @@ nlua_pop_typval_table_processing_end:
lua_pop(lstate, 1);
}
}
- kv_destroy(stack);
+ kvi_destroy(stack);
if (!ret) {
tv_clear(ret_tv);
*ret_tv = (typval_T) {
@@ -1060,15 +1061,16 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
{
Object ret = NIL;
const int initial_size = lua_gettop(lstate);
- kvec_t(ObjPopStackItem) stack = KV_INITIAL_VALUE;
- kv_push(stack, ((ObjPopStackItem) { &ret, false }));
+ kvec_withinit_t(ObjPopStackItem, 2) stack = KV_INITIAL_VALUE;
+ kvi_init(stack);
+ kvi_push(stack, ((ObjPopStackItem) { &ret, false }));
while (!ERROR_SET(err) && kv_size(stack)) {
- if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) {
- api_set_error(err, kErrorTypeException, "Lua failed to grow stack");
- break;
- }
ObjPopStackItem cur = kv_pop(stack);
if (cur.container) {
+ if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) {
+ api_set_error(err, kErrorTypeException, "Lua failed to grow stack");
+ break;
+ }
if (cur.obj->type == kObjectTypeDictionary) {
// stack: …, dict, key
if (cur.obj->data.dictionary.size
@@ -1095,7 +1097,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
.data = xmemdupz(s, len),
.size = len,
};
- kv_push(stack, cur);
+ kvi_push(stack, cur);
cur = (ObjPopStackItem) {
.obj = &cur.obj->data.dictionary.items[idx].value,
.container = false,
@@ -1117,7 +1119,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
lua_pop(lstate, 2);
continue;
}
- kv_push(stack, cur);
+ kvi_push(stack, cur);
cur = (ObjPopStackItem) {
.obj = &cur.obj->data.array.items[idx],
.container = false,
@@ -1169,7 +1171,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
sizeof(cur.obj->data.array.items[0]));
cur.obj->data.array.capacity = table_props.maxidx;
cur.container = true;
- kv_push(stack, cur);
+ kvi_push(stack, cur);
}
break;
}
@@ -1185,7 +1187,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
sizeof(cur.obj->data.dictionary.items[0]));
cur.obj->data.dictionary.capacity = table_props.string_keys_num;
cur.container = true;
- kv_push(stack, cur);
+ kvi_push(stack, cur);
lua_pushnil(lstate);
}
break;
@@ -1239,7 +1241,7 @@ type_error:
lua_pop(lstate, 1);
}
}
- kv_destroy(stack);
+ kvi_destroy(stack);
if (ERROR_SET(err)) {
api_free_object(ret);
ret = NIL;