From 705e8f10ac83f32dea5bfa0569aba12a692fe522 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 28 Aug 2021 11:42:43 +0200 Subject: 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 --- src/nvim/lua/converter.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'src/nvim/lua/converter.c') 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; -- cgit