mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #15509 from bfredl/miniperf
perf(api): avoid spurious allocations when converting small objects
This commit is contained in:
commit
636ecd0c3b
@ -29,7 +29,7 @@ set(API_UI_EVENTS_GENERATOR ${GENERATOR_DIR}/gen_api_ui_events.lua)
|
||||
set(GENERATOR_C_GRAMMAR ${GENERATOR_DIR}/c_grammar.lua)
|
||||
set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack)
|
||||
set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
|
||||
set(MSGPACK_LUA_C_BINDINGS ${GENERATED_DIR}/msgpack_lua_c_bindings.generated.c)
|
||||
set(LUA_API_C_BINDINGS ${GENERATED_DIR}/lua_api_c_bindings.generated.c)
|
||||
set(HEADER_GENERATOR ${GENERATOR_DIR}/gen_declarations.lua)
|
||||
set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include)
|
||||
set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.generated.h)
|
||||
@ -305,11 +305,11 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES}
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA}
|
||||
${API_METADATA} ${MSGPACK_LUA_C_BINDINGS}
|
||||
${API_METADATA} ${LUA_API_C_BINDINGS}
|
||||
COMMAND ${LUA_PRG} ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
|
||||
${GENERATED_API_DISPATCH}
|
||||
${GENERATED_FUNCS_METADATA} ${API_METADATA}
|
||||
${MSGPACK_LUA_C_BINDINGS}
|
||||
${LUA_API_C_BINDINGS}
|
||||
${API_HEADERS}
|
||||
DEPENDS
|
||||
${API_HEADERS}
|
||||
@ -333,7 +333,7 @@ add_custom_command(
|
||||
)
|
||||
|
||||
list(APPEND NVIM_GENERATED_SOURCES
|
||||
"${MSGPACK_LUA_C_BINDINGS}"
|
||||
"${LUA_API_C_BINDINGS}"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
/// Helper structure for vim_to_object
|
||||
typedef struct {
|
||||
kvec_t(Object) stack; ///< Object stack.
|
||||
kvec_withinit_t(Object, 2) stack; ///< Object stack.
|
||||
} EncodedData;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
@ -418,28 +418,25 @@ void set_option_to(uint64_t channel_id, void *to, int type,
|
||||
#define TYPVAL_ENCODE_ALLOW_SPECIALS false
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_NIL(tv) \
|
||||
kv_push(edata->stack, NIL)
|
||||
kvi_push(edata->stack, NIL)
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
|
||||
kv_push(edata->stack, BOOLEAN_OBJ((Boolean)(num)))
|
||||
kvi_push(edata->stack, BOOLEAN_OBJ((Boolean)(num)))
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \
|
||||
kv_push(edata->stack, INTEGER_OBJ((Integer)(num)))
|
||||
kvi_push(edata->stack, INTEGER_OBJ((Integer)(num)))
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \
|
||||
kv_push(edata->stack, FLOAT_OBJ((Float)(flt)))
|
||||
kvi_push(edata->stack, FLOAT_OBJ((Float)(flt)))
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \
|
||||
do { \
|
||||
const size_t len_ = (size_t)(len); \
|
||||
const char *const str_ = (const char *)(str); \
|
||||
assert(len_ == 0 || str_ != NULL); \
|
||||
kv_push(edata->stack, STRING_OBJ(((String) { \
|
||||
.data = xmemdupz((len_?str_:""), len_), \
|
||||
.size = len_ \
|
||||
}))); \
|
||||
kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_?str_:""), len_))); \
|
||||
} while (0)
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING
|
||||
@ -458,17 +455,17 @@ void set_option_to(uint64_t channel_id, void *to, int type,
|
||||
#define TYPVAL_ENCODE_CONV_FUNC_END(tv)
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \
|
||||
kv_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 })))
|
||||
kvi_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 })))
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
|
||||
kv_push(edata->stack, \
|
||||
DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 })))
|
||||
kvi_push(edata->stack, \
|
||||
DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 })))
|
||||
|
||||
static inline void typval_encode_list_start(EncodedData *const edata,
|
||||
const size_t len)
|
||||
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
kv_push(edata->stack, ARRAY_OBJ(((Array) {
|
||||
kvi_push(edata->stack, ARRAY_OBJ(((Array) {
|
||||
.capacity = len,
|
||||
.size = 0,
|
||||
.items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.array.items)),
|
||||
@ -510,7 +507,7 @@ static inline void typval_encode_dict_start(EncodedData *const edata,
|
||||
const size_t len)
|
||||
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
kv_push(edata->stack, DICTIONARY_OBJ(((Dictionary) {
|
||||
kvi_push(edata->stack, DICTIONARY_OBJ(((Dictionary) {
|
||||
.capacity = len,
|
||||
.size = 0,
|
||||
.items = xmalloc(len * sizeof(
|
||||
@ -618,14 +615,15 @@ static inline void typval_encode_dict_end(EncodedData *const edata)
|
||||
/// @return The converted value
|
||||
Object vim_to_object(typval_T *obj)
|
||||
{
|
||||
EncodedData edata = { .stack = KV_INITIAL_VALUE };
|
||||
EncodedData edata;
|
||||
kvi_init(edata.stack);
|
||||
const int evo_ret = encode_vim_to_object(&edata, obj,
|
||||
"vim_to_object argument");
|
||||
(void)evo_ret;
|
||||
assert(evo_ret == OK);
|
||||
Object ret = kv_A(edata.stack, 0);
|
||||
assert(kv_size(edata.stack) == 1);
|
||||
kv_destroy(edata.stack);
|
||||
kvi_destroy(edata.stack);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ if arg[1] == '--help' then
|
||||
print(' 2: dispatch output file (dispatch_wrappers.generated.h)')
|
||||
print(' 3: functions metadata output file (funcs_metadata.generated.h)')
|
||||
print(' 4: API metadata output file (api_metadata.mpack)')
|
||||
print(' 5: lua C bindings output file (msgpack_lua_c_bindings.generated.c)')
|
||||
print(' 5: lua C bindings output file (lua_api_c_bindings.generated.c)')
|
||||
print(' rest: C files where API functions are defined')
|
||||
end
|
||||
assert(#arg >= 4)
|
||||
@ -378,7 +378,7 @@ output:write('\n')
|
||||
local lua_c_functions = {}
|
||||
|
||||
local function process_function(fn)
|
||||
local lua_c_function_name = ('nlua_msgpack_%s'):format(fn.name)
|
||||
local lua_c_function_name = ('nlua_api_%s'):format(fn.name)
|
||||
write_shifted_output(output, string.format([[
|
||||
|
||||
static int %s(lua_State *lstate)
|
||||
|
@ -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;
|
||||
|
@ -86,8 +86,9 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
bool ret = true;
|
||||
kvec_t(MPToAPIObjectStackItem) stack = KV_INITIAL_VALUE;
|
||||
kv_push(stack, ((MPToAPIObjectStackItem) {
|
||||
kvec_withinit_t(MPToAPIObjectStackItem, 2) stack = KV_INITIAL_VALUE;
|
||||
kvi_init(stack);
|
||||
kvi_push(stack, ((MPToAPIObjectStackItem) {
|
||||
.mobj = obj,
|
||||
.aobj = arg,
|
||||
.container = false,
|
||||
@ -155,7 +156,7 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
|
||||
const size_t idx = cur.idx;
|
||||
cur.idx++;
|
||||
kv_last(stack) = cur;
|
||||
kv_push(stack, ((MPToAPIObjectStackItem) {
|
||||
kvi_push(stack, ((MPToAPIObjectStackItem) {
|
||||
.mobj = &cur.mobj->via.array.ptr[idx],
|
||||
.aobj = &cur.aobj->data.array.items[idx],
|
||||
.container = false,
|
||||
@ -209,7 +210,7 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
|
||||
}
|
||||
}
|
||||
if (ret) {
|
||||
kv_push(stack, ((MPToAPIObjectStackItem) {
|
||||
kvi_push(stack, ((MPToAPIObjectStackItem) {
|
||||
.mobj = &cur.mobj->via.map.ptr[idx].val,
|
||||
.aobj = &cur.aobj->data.dictionary.items[idx].value,
|
||||
.container = false,
|
||||
@ -265,7 +266,7 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
|
||||
(void)kv_pop(stack);
|
||||
}
|
||||
}
|
||||
kv_destroy(stack);
|
||||
kvi_destroy(stack);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -375,8 +376,9 @@ typedef struct {
|
||||
void msgpack_rpc_from_object(const Object result, msgpack_packer *const res)
|
||||
FUNC_ATTR_NONNULL_ARG(2)
|
||||
{
|
||||
kvec_t(APIToMPObjectStackItem) stack = KV_INITIAL_VALUE;
|
||||
kv_push(stack, ((APIToMPObjectStackItem) { &result, false, 0 }));
|
||||
kvec_withinit_t(APIToMPObjectStackItem, 2) stack = KV_INITIAL_VALUE;
|
||||
kvi_init(stack);
|
||||
kvi_push(stack, ((APIToMPObjectStackItem) { &result, false, 0 }));
|
||||
while (kv_size(stack)) {
|
||||
APIToMPObjectStackItem cur = kv_last(stack);
|
||||
STATIC_ASSERT(kObjectTypeWindow == kObjectTypeBuffer + 1
|
||||
@ -428,7 +430,7 @@ void msgpack_rpc_from_object(const Object result, msgpack_packer *const res)
|
||||
const size_t idx = cur.idx;
|
||||
cur.idx++;
|
||||
kv_last(stack) = cur;
|
||||
kv_push(stack, ((APIToMPObjectStackItem) {
|
||||
kvi_push(stack, ((APIToMPObjectStackItem) {
|
||||
.aobj = &cur.aobj->data.array.items[idx],
|
||||
.container = false,
|
||||
}));
|
||||
@ -451,7 +453,7 @@ void msgpack_rpc_from_object(const Object result, msgpack_packer *const res)
|
||||
kv_last(stack) = cur;
|
||||
msgpack_rpc_from_string(cur.aobj->data.dictionary.items[idx].key,
|
||||
res);
|
||||
kv_push(stack, ((APIToMPObjectStackItem) {
|
||||
kvi_push(stack, ((APIToMPObjectStackItem) {
|
||||
.aobj = &cur.aobj->data.dictionary.items[idx].value,
|
||||
.container = false,
|
||||
}));
|
||||
@ -468,7 +470,7 @@ void msgpack_rpc_from_object(const Object result, msgpack_packer *const res)
|
||||
(void)kv_pop(stack);
|
||||
}
|
||||
}
|
||||
kv_destroy(stack);
|
||||
kvi_destroy(stack);
|
||||
}
|
||||
|
||||
void msgpack_rpc_from_array(Array result, msgpack_packer *res)
|
||||
|
Loading…
Reference in New Issue
Block a user