perf(api): allow to use an arena for return values

This commit is contained in:
bfredl
2022-08-23 09:33:08 +02:00
parent baaaa1f2b3
commit c0d6052654
36 changed files with 584 additions and 497 deletions

View File

@@ -1021,7 +1021,7 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err)
/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
/// @return Buffer name
String nvim_buf_get_name(Buffer buffer, Error *err)
String nvim_buf_get_name(Buffer buffer, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
String rv = STRING_INIT;
@@ -1031,7 +1031,7 @@ String nvim_buf_get_name(Buffer buffer, Error *err)
return rv;
}
return cstr_to_string((char *)buf->b_ffname);
return cstr_as_string((char *)buf->b_ffname);
}
/// Sets the full file name for a buffer

View File

@@ -5,18 +5,23 @@
typedef Object (*ApiDispatchWrapper)(uint64_t channel_id,
Array args,
Arena *arena,
Error *error);
/// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores
/// functions of this type.
typedef struct {
struct MsgpackRpcRequestHandler {
const char *name;
ApiDispatchWrapper fn;
bool fast; // Function is safe to be executed immediately while running the
// uv loop (the loop is run very frequently due to breakcheck).
// If "fast" is false, the function is deferred, i e the call will
// be put in the event queue, for safe handling later.
} MsgpackRpcRequestHandler;
bool arena_return; // return value is allocated in the arena (or statically)
// and should not be freed as such.
};
extern const MsgpackRpcRequestHandler method_handlers[];
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/dispatch.h.generated.h"

View File

@@ -1629,11 +1629,11 @@ Array nvim_list_chans(void)
/// an error, it is a three-element array with the zero-based index of the call
/// which resulted in an error, the error type and the error message. If an
/// error occurred, the values from all preceding calls will still be returned.
Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{
Array rv = ARRAY_DICT_INIT;
Array results = ARRAY_DICT_INIT;
Array rv = arena_array(arena, 2);
Array results = arena_array(arena, calls.size);
Error nested_error = ERROR_INIT;
size_t i; // also used for freeing the variables
@@ -1676,29 +1676,32 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
if (ERROR_SET(&nested_error)) {
break;
}
Object result = handler.fn(channel_id, args, &nested_error);
Object result = handler.fn(channel_id, args, arena, &nested_error);
if (ERROR_SET(&nested_error)) {
// error handled after loop
break;
}
if (!handler.arena_return && result.type != kObjectTypeNil) {
// TODO: fix to not leak memory as fuck
}
ADD(results, result);
ADD_C(results, result);
}
ADD(rv, ARRAY_OBJ(results));
ADD_C(rv, ARRAY_OBJ(results));
if (ERROR_SET(&nested_error)) {
Array errval = ARRAY_DICT_INIT;
ADD(errval, INTEGER_OBJ((Integer)i));
ADD(errval, INTEGER_OBJ(nested_error.type));
ADD(errval, STRING_OBJ(cstr_to_string(nested_error.msg)));
ADD(rv, ARRAY_OBJ(errval));
Array errval = arena_array(arena, 3);
ADD_C(errval, INTEGER_OBJ((Integer)i));
ADD_C(errval, INTEGER_OBJ(nested_error.type));
ADD_C(errval, STRING_OBJ(cstr_to_string(nested_error.msg))); // TODO
ADD_C(rv, ARRAY_OBJ(errval));
} else {
ADD(rv, NIL);
ADD_C(rv, NIL);
}
goto theend;
validation_error:
api_free_array(results);
theend:
api_clear_error(&nested_error);
return rv;
@@ -1803,6 +1806,7 @@ Dictionary nvim__stats(void)
PUT(rv, "log_skip", INTEGER_OBJ(g_stats.log_skip));
PUT(rv, "lua_refcount", INTEGER_OBJ(nlua_get_global_ref_count()));
PUT(rv, "redraw", INTEGER_OBJ(g_stats.redraw));
PUT(rv, "arena_alloc_count", INTEGER_OBJ((Integer)arena_alloc_count));
return rv;
}