mirror of
https://github.com/neovim/neovim.git
synced 2025-10-14 13:56:05 +00:00
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
This commit is contained in:
@@ -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;
|
||||
|
Reference in New Issue
Block a user