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

@@ -801,7 +801,7 @@ def extract_from_xml(filename, target, width, fmt_vimhelp):
prefix = '%s(' % name
suffix = '%s)' % ', '.join('{%s}' % a[1] for a in params
if a[0] not in ('void', 'Error'))
if a[0] not in ('void', 'Error', 'Arena'))
if not fmt_vimhelp:
c_decl = '%s %s(%s);' % (return_type, name, ', '.join(c_args))

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;
}

View File

@@ -1074,7 +1074,7 @@ char *arg_all(void)
}
/// "argc([window id])" function
void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_argc(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type == VAR_UNKNOWN) {
// use the current window
@@ -1095,13 +1095,13 @@ void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "argidx()" function
void f_argidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_argidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = curwin->w_arg_idx;
}
/// "arglistid()" function
void f_arglistid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_arglistid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
win_T *wp = find_tabwin(&argvars[0], &argvars[1]);
@@ -1123,7 +1123,7 @@ static void get_arglist_as_rettv(aentry_T *arglist, int argcount, typval_T *rett
}
/// "argv(nr)" function
void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_argv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
aentry_T *arglist = NULL;
int argcount = -1;

View File

@@ -2751,7 +2751,7 @@ void wildmenu_cleanup(CmdlineInfo *cclp)
}
/// "getcompletion()" function
void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u *pat;
expand_T xpc;

View File

@@ -494,7 +494,7 @@ static int del_history_idx(int histype, int idx)
}
/// "histadd()" function
void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_histadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
HistoryType histype;
@@ -517,7 +517,7 @@ void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "histdel()" function
void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_histdel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int n;
const char *const str = tv_get_string_chk(&argvars[0]); // NULL on type error
@@ -540,7 +540,7 @@ void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "histget()" function
void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_histget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
HistoryType type;
int idx;
@@ -562,7 +562,7 @@ void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "histnr()" function
void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_histnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const histname = tv_get_string_chk(&argvars[0]);
HistoryType i = histname == NULL

View File

@@ -1917,7 +1917,7 @@ static bool digraph_set_common(const typval_T *argchars, const typval_T *argdigr
}
/// "digraph_get()" function
void f_digraph_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_digraph_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; // Return empty string for failure
@@ -1938,7 +1938,7 @@ void f_digraph_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "digraph_getlist()" function
void f_digraph_getlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_digraph_getlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
bool flag_list_all;
@@ -1957,7 +1957,7 @@ void f_digraph_getlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "digraph_set()" function
void f_digraph_set(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_digraph_set(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_BOOL;
rettv->vval.v_bool = kBoolVarFalse;
@@ -1970,7 +1970,7 @@ void f_digraph_set(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "digraph_setlist()" function
void f_digraph_setlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_digraph_setlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_BOOL;
rettv->vval.v_bool = kBoolVarFalse;

View File

@@ -4968,7 +4968,7 @@ theend:
return retval;
}
void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref, FunPtr fptr)
void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
{
char *s;
char *name;

View File

@@ -23,7 +23,7 @@ end
return {
funcs={
abs={args=1, base=1},
acos={args=1, base=1, func="float_op_wrapper", data="&acos"}, -- WJMc
acos={args=1, base=1, float_func="acos"}, -- WJMc
add={args=2, base=1},
['and']={args=2, base=1},
api_info={},
@@ -33,7 +33,7 @@ return {
argidx={},
arglistid={args={0, 2}},
argv={args={0, 2}},
asin={args=1, base=1, func="float_op_wrapper", data="&asin"}, -- WJMc
asin={args=1, base=1, float_func="asin"}, -- WJMc
assert_beeps={args=1, base=1},
assert_equal={args={2, 3}, base=2},
assert_equalfile={args={2, 3}, base=1},
@@ -47,7 +47,7 @@ return {
assert_notmatch={args={2, 3}, base=2},
assert_report={args=1, base=1},
assert_true={args={1, 2}, base=1},
atan={args=1, base=1, func="float_op_wrapper", data="&atan"},
atan={args=1, base=1, float_func="atan"},
atan2={args=2, base=1},
browse={args=4},
browsedir={args=2},
@@ -67,7 +67,7 @@ return {
byteidx={args=2, base=1},
byteidxcomp={args=2, base=1},
call={args={2, 3}, base=1},
ceil={args=1, base=1, func="float_op_wrapper", data="&ceil"},
ceil={args=1, base=1, float_func="ceil"},
changenr={},
chanclose={args={1, 2}},
chansend={args=2},
@@ -85,8 +85,8 @@ return {
complete_info={args={0, 1}, base=1},
confirm={args={1, 4}, base=1},
copy={args=1, base=1},
cos={args=1, base=1, func="float_op_wrapper", data="&cos"},
cosh={args=1, base=1, func="float_op_wrapper", data="&cosh"},
cos={args=1, base=1, float_func="cos"},
cosh={args=1, base=1, float_func="cosh"},
count={args={2, 4}, base=1},
cscope_connection={args={0, 3}},
ctxget={args={0, 1}},
@@ -117,7 +117,7 @@ return {
execute={args={1, 2}, base=1},
exepath={args=1, base=1},
exists={args=1, base=1},
exp={args=1, base=1, func="float_op_wrapper", data="&exp"},
exp={args=1, base=1, float_func="exp"},
expand={args={1, 3}, base=1},
expandcmd={args=1, base=1},
extend={args={2, 3}, base=1},
@@ -130,7 +130,7 @@ return {
findfile={args={1, 3}, base=1},
flatten={args={1, 2}, base=1},
float2nr={args=1, base=1},
floor={args=1, base=1, func="float_op_wrapper", data="&floor"},
floor={args=1, base=1, float_func="floor"},
fmod={args=2, base=1},
fnameescape={args=1, base=1},
fnamemodify={args=2, base=1},
@@ -245,8 +245,8 @@ return {
lispindent={args=1, base=1},
list2str={args={1, 2}, base=1},
localtime={},
log={args=1, base=1, func="float_op_wrapper", data="&log"},
log10={args=1, base=1, func="float_op_wrapper", data="&log10"},
log={args=1, base=1, float_func="log"},
log10={args=1, base=1, float_func="log10"},
luaeval={args={1, 2}, base=1},
map={args=2, base=1},
maparg={args={1, 4}, base=1},
@@ -304,7 +304,7 @@ return {
['repeat']={args=2, base=1},
resolve={args=1, base=1},
reverse={args=1, base=1},
round={args=1, base=1, func="float_op_wrapper", data="&round"},
round={args=1, base=1, float_func="round"},
rpcnotify={args=varargs(2)},
rpcrequest={args=varargs(2)},
rpcstart={args={1, 2}},
@@ -358,8 +358,8 @@ return {
sign_unplace={args={1, 2}, base=1},
sign_unplacelist={args=1, base=1},
simplify={args=1, base=1},
sin={args=1, base=1, func="float_op_wrapper", data="&sin"},
sinh={args=1, base=1, func="float_op_wrapper", data="&sinh"},
sin={args=1, base=1, float_func="sin"},
sinh={args=1, base=1, float_func="sinh"},
sockconnect={args={2,3}},
sort={args={1, 3}, base=1},
soundfold={args=1, base=1},
@@ -367,7 +367,7 @@ return {
spellbadword={args={0, 1}, base=1},
spellsuggest={args={1, 3}, base=1},
split={args={1, 3}, base=1},
sqrt={args=1, base=1, func="float_op_wrapper", data="&sqrt"},
sqrt={args=1, base=1, float_func="sqrt"},
srand={args={0, 1}, base=1},
stdpath={args=1},
str2float={args=1, base=1},
@@ -402,8 +402,8 @@ return {
tabpagewinnr={args={1, 2}, base=1},
tagfiles={},
taglist={args={1, 2}, base=1},
tan={args=1, base=1, func="float_op_wrapper", data="&tan"},
tanh={args=1, base=1, func="float_op_wrapper", data="&tanh"},
tan={args=1, base=1, float_func="tan"},
tanh={args=1, base=1, float_func="tanh"},
tempname={},
termopen={args={1, 2}},
test_garbagecollect_now={},
@@ -417,7 +417,7 @@ return {
toupper={args=1, base=1},
tr={args=3, base=1},
trim={args={1, 3}, base=1},
trunc={args=1, base=1, func="float_op_wrapper", data="&trunc"},
trunc={args=1, base=1, float_func="trunc"},
type={args=1, base=1},
undofile={args=1, base=1},
undotree={},

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,12 @@
#ifndef NVIM_EVAL_FUNCS_H
#define NVIM_EVAL_FUNCS_H
#include "nvim/api/private/dispatch.h"
#include "nvim/buffer_defs.h"
#include "nvim/eval/typval.h"
/// Prototype of C function that implements VimL function
typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, FunPtr data);
typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, EvalFuncData data);
/// Special flags for base_arg @see EvalFuncDef
#define BASE_NONE 0 ///< Not a method (no base argument).
@@ -19,7 +20,7 @@ typedef struct {
uint8_t base_arg; ///< Method base arg # (1-indexed), BASE_NONE or BASE_LAST.
bool fast; ///< Can be run in |api-fast| events
VimLFunc func; ///< Function implementation.
FunPtr data; ///< Userdata for function implementation.
EvalFuncData data; ///< Userdata for function implementation.
} EvalFuncDef;
#ifdef INCLUDE_GENERATED_DECLARATIONS

View File

@@ -831,7 +831,7 @@ int tv_list_join(garray_T *const gap, list_T *const l, const char *const sep)
}
/// "join()" function
void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_join(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_LIST) {
emsg(_(e_listreq));
@@ -855,7 +855,7 @@ void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "list2str()" function
void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_list2str(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
garray_T ga;
@@ -1267,13 +1267,13 @@ theend:
}
/// "sort"({list})" function
void f_sort(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sort(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
do_sort_uniq(argvars, rettv, true);
}
/// "uniq({list})" function
void f_uniq(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_uniq(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
do_sort_uniq(argvars, rettv, false);
}
@@ -2806,25 +2806,25 @@ static void tv_dict_list(typval_T *const tv, typval_T *const rettv, const DictLi
}
/// "items(dict)" function
void f_items(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_items(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_list(argvars, rettv, 2);
}
/// "keys()" function
void f_keys(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_keys(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_list(argvars, rettv, 0);
}
/// "values(dict)" function
void f_values(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_values(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_list(argvars, rettv, 1);
}
/// "has_key()" function
void f_has_key(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_has_key(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_DICT) {
emsg(_(e_dictreq));

View File

@@ -25,9 +25,6 @@
typedef int64_t varnumber_T;
typedef uint64_t uvarnumber_T;
/// Type used for VimL VAR_FLOAT values
typedef double float_T;
/// Refcount for dict or list that should not be freed
enum { DO_NOT_FREE_CNT = (INT_MAX / 2), };

View File

@@ -1702,7 +1702,7 @@ bool var_exists(const char *var)
}
/// "gettabvar()" function
void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_gettabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const varname = tv_get_string_chk(&argvars[1]);
tabpage_T *const tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
@@ -1716,19 +1716,19 @@ void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "gettabwinvar()" function
void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_gettabwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getwinvar(argvars, rettv, 1);
}
/// "getwinvar()" function
void f_getwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_getwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getwinvar(argvars, rettv, 0);
}
/// "getbufvar()" function
void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_getbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const varname = tv_get_string_chk(&argvars[1]);
buf_T *const buf = tv_get_buf_from_arg(&argvars[0]);
@@ -1737,7 +1737,7 @@ void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "settabvar()" function
void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = 0;
@@ -1768,19 +1768,19 @@ void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "settabwinvar()" function
void f_settabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_settabwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
setwinvar(argvars, rettv, 1);
}
/// "setwinvar()" function
void f_setwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_setwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
setwinvar(argvars, rettv, 0);
}
/// "setbufvar()" function
void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_setbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (check_secure()
|| !tv_check_str_or_nr(&argvars[0])) {

View File

@@ -3047,7 +3047,7 @@ int cmd_exists(const char *const name)
}
/// "fullcommand" function
void f_fullcommand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_fullcommand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char *name = argvars[0].vval.v_string;

View File

@@ -3212,19 +3212,19 @@ static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end)
}
/// "foldclosed()" function
void f_foldclosed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_foldclosed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
foldclosed_both(argvars, rettv, false);
}
/// "foldclosedend()" function
void f_foldclosedend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_foldclosedend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
foldclosed_both(argvars, rettv, true);
}
/// "foldlevel()" function
void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_foldlevel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const linenr_T lnum = tv_get_lnum(argvars);
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) {
@@ -3233,7 +3233,7 @@ void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "foldtext()" function
void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_foldtext(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
@@ -3279,7 +3279,7 @@ void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "foldtextresult(lnum)" function
void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_foldtextresult(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char_u buf[FOLD_TEXT_LEN];
static bool entered = false;

View File

@@ -26,6 +26,7 @@ local c_id = (
local c_void = P('void')
local c_param_type = (
((P('Error') * fill * P('*') * fill) * Cc('error')) +
((P('Arena') * fill * P('*') * fill) * Cc('arena')) +
C((P('const ') ^ -1) * (c_id) * (ws ^ 1) * P('*')) +
(C(c_id) * (ws ^ 1))
)

View File

@@ -17,6 +17,7 @@ local nvimdir = arg[1]
package.path = nvimdir .. '/?.lua;' .. package.path
_G.vim = loadfile(nvimdir..'/../../runtime/lua/vim/shared.lua')()
_G.vim.inspect = loadfile(nvimdir..'/../../runtime/lua/vim/inspect.lua')()
local hashy = require'generators.hashy'
@@ -72,6 +73,11 @@ for i = 6, #arg do
-- for specifying errors
fn.parameters[#fn.parameters] = nil
end
if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'arena' then
-- return value is allocated in an arena
fn.arena_return = true
fn.parameters[#fn.parameters] = nil
end
end
end
input:close()
@@ -210,7 +216,7 @@ for i = 1, #functions do
if fn.impl_name == nil and fn.remote then
local args = {}
output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Error *error)')
output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Arena* arena, Error *error)')
output:write('\n{')
output:write('\n#if MIN_LOG_LEVEL <= LOGLVL_DBG')
output:write('\n logmsg(LOGLVL_DBG, "RPC: ", NULL, -1, true, "ch %" PRIu64 ": invoke '
@@ -319,6 +325,10 @@ for i = 1, #functions do
output:write(call_args)
end
if fn.arena_return then
output:write(', arena')
end
if fn.can_fail then
-- if the function can fail, also pass a pointer to the local error object
if #args > 0 then
@@ -355,11 +365,12 @@ local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", vim.t
return "method_handlers["..idx.."].name"
end)
output:write("static const MsgpackRpcRequestHandler method_handlers[] = {\n")
for _, name in ipairs(hashorder) do
output:write("const MsgpackRpcRequestHandler method_handlers[] = {\n")
for n, name in ipairs(hashorder) do
local fn = remote_fns[name]
fn.handler_id = n-1
output:write(' { .name = "'..name..'", .fn = handle_'.. (fn.impl_name or fn.name)..
', .fast = '..tostring(fn.fast)..'},\n')
', .fast = '..tostring(fn.fast)..', .arena_return = '..tostring(not not fn.arena_return)..'},\n')
end
output:write("};\n\n")
output:write(hashfun)
@@ -400,6 +411,10 @@ output:write([[
#include "nvim/api/private/helpers.h"
#include "nvim/lua/converter.h"
#include "nvim/lua/executor.h"
#include "nvim/memory.h"
static ArenaMem lua_reuse_blk = { 0 };
]])
include_headers(output, headers)
output:write('\n')
@@ -477,6 +492,14 @@ local function process_function(fn)
if fn.receives_channel_id then
cparams = 'LUA_INTERNAL_CALL, ' .. cparams
end
if fn.arena_return then
cparams = cparams .. '&arena, '
write_shifted_output(output, [[
Arena arena = ARENA_EMPTY;
arena_start(&arena, &lua_reuse_blk);
]])
end
if fn.can_fail then
cparams = cparams .. '&err'
else
@@ -511,15 +534,21 @@ local function process_function(fn)
else
return_type = fn.return_type
end
local free_retval
if fn.arena_return then
free_retval = "arena_mem_free(arena_finish(&arena), &lua_reuse_blk);"
else
free_retval = "api_free_"..return_type:lower().."(ret);"
end
write_shifted_output(output, string.format([[
const %s ret = %s(%s);
nlua_push_%s(lstate, ret, true);
api_free_%s(ret);
%s
%s
%s
return 1;
]], fn.return_type, fn.name, cparams, return_type, return_type:lower(),
free_at_exit_code, err_throw_code))
]], fn.return_type, fn.name, cparams, return_type,
free_retval, free_at_exit_code, err_throw_code))
else
write_shifted_output(output, string.format([[
%s(%s);

View File

@@ -28,13 +28,20 @@ local hashy = require'generators.hashy'
local hashpipe = io.open(funcsfname, 'wb')
local funcs = require('eval').funcs
for _, func in pairs(funcs) do
if func.float_func then
func.func = "float_op_wrapper"
func.data = "{ .float_func = &"..func.float_func.." }"
end
end
local metadata = mpack.unpack(io.open(metadata_file, 'rb'):read("*all"))
for _,fun in ipairs(metadata) do
if fun.eval then
funcs[fun.name] = {
args=#fun.parameters,
func='api_wrapper',
data='&handle_'..fun.name,
data='{ .api_handler = &method_handlers['..fun.handler_id..'] }'
}
end
end
@@ -60,12 +67,12 @@ for _, name in ipairs(neworder) do
end
local base = def.base or "BASE_NONE"
local func = def.func or ('f_' .. name)
local data = def.data or "NULL"
local data = def.data or "{ .nullptr = NULL }"
local fast = def.fast and 'true' or 'false'
hashpipe:write((' { "%s", %s, %s, %s, %s, &%s, (FunPtr)%s },\n')
hashpipe:write((' { "%s", %s, %s, %s, %s, &%s, %s },\n')
:format(name, args[1], args[2], base, fast, func, data))
end
hashpipe:write(' { NULL, 0, 0, BASE_NONE, false, NULL, NULL },\n')
hashpipe:write(' { NULL, 0, 0, BASE_NONE, false, NULL, { .nullptr = NULL } },\n')
hashpipe:write("};\n\n")
hashpipe:write(hashfun)
hashpipe:close()

View File

@@ -1810,13 +1810,13 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
}
/// "getchar()" function
void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_getchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getchar_common(argvars, rettv);
}
/// "getcharstr()" function
void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_getcharstr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
getchar_common(argvars, rettv);
@@ -1836,7 +1836,7 @@ void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getcharmod()" function
void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_getcharmod(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = mod_mask;
}

View File

@@ -2256,7 +2256,7 @@ static void set_completion(colnr_T startcol, list_T *list)
}
/// "complete()" function
void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_complete(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if ((State & MODE_INSERT) == 0) {
emsg(_("E785: complete() can only be used in Insert mode"));
@@ -2280,13 +2280,13 @@ void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "complete_add()" function
void f_complete_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_complete_add(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0, false);
}
/// "complete_check()" function
void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_complete_check(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int saved = RedrawingDisabled;
@@ -2441,7 +2441,7 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
}
/// "complete_info()" function
void f_complete_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_complete_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);

View File

@@ -1967,7 +1967,7 @@ char_u *check_map(char_u *keys, int mode, int exact, int ign_mod, int abbr, mapb
}
/// "hasmapto()" function
void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_hasmapto(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *mode;
const char *const name = tv_get_string(&argvars[0]);
@@ -2127,7 +2127,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
}
/// "mapset()" function
void f_mapset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char buf[NUMBUFLEN];
const char *which = tv_get_string_buf_chk(&argvars[0], buf);
@@ -2195,13 +2195,13 @@ void f_mapset(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "maparg()" function
void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_maparg(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_maparg(argvars, rettv, true);
}
/// "mapcheck()" function
void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_mapcheck(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_maparg(argvars, rettv, false);
}

View File

@@ -859,7 +859,7 @@ static int matchadd_dict_arg(typval_T *tv, const char **conceal_char, win_T **wi
}
/// "clearmatches()" function
void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_clearmatches(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *win = get_optional_window(argvars, 0);
@@ -869,7 +869,7 @@ void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "getmatches()" function
void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_getmatches(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
matchitem_T *cur;
int i;
@@ -924,7 +924,7 @@ void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "setmatches()" function
void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_setmatches(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
dict_T *d;
list_T *s = NULL;
@@ -1027,7 +1027,7 @@ void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "matchadd()" function
void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_matchadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char grpbuf[NUMBUFLEN];
char patbuf[NUMBUFLEN];
@@ -1069,7 +1069,7 @@ void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "matchaddpo()" function
void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_matchaddpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
@@ -1120,7 +1120,7 @@ void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "matcharg()" function
void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_matcharg(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const int id = (int)tv_get_number(&argvars[0]);
@@ -1143,7 +1143,7 @@ void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "matchdelete()" function
void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_matchdelete(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *win = get_optional_window(argvars, 1);
if (win == NULL) {

View File

@@ -2748,7 +2748,7 @@ static int tv_nr_compare(const void *a1, const void *a2)
}
/// "setcellwidths()" function
void f_setcellwidths(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL) {
emsg(_(e_listreq));
@@ -2860,7 +2860,7 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, FunPtr fptr)
redraw_all_later(NOT_VALID);
}
void f_charclass(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_charclass(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (tv_check_for_string(&argvars[0]) == FAIL
|| argvars[0].vval.v_string == NULL) {

View File

@@ -534,15 +534,18 @@ void arena_start(Arena *arena, ArenaMem *reuse_blk)
if (reuse_blk && *reuse_blk) {
arena->cur_blk = (char *)(*reuse_blk);
*reuse_blk = NULL;
arena->size = ARENA_BLOCK_SIZE;
arena->pos = 0;
// address is the same as as (struct consumed_blk *)arena->cur_blk
struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
assert((char *)blk == (char *)arena->cur_blk);
blk->prev = NULL;
} else {
arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
arena->cur_blk = NULL;
arena->size = 0;
arena->pos = 0;
}
arena->pos = 0;
arena->size = ARENA_BLOCK_SIZE;
// address is the same as as (struct consumed_blk *)arena->cur_blk
struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
assert((char *)blk == (char *)arena->cur_blk);
blk->prev = NULL;
}
/// Finnish the allocations in an arena.
@@ -558,17 +561,35 @@ ArenaMem arena_finish(Arena *arena)
return res;
}
void alloc_block(Arena *arena)
{
struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk;
arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
arena->pos = 0;
arena->size = ARENA_BLOCK_SIZE;
struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
blk->prev = prev_blk;
arena_alloc_count++;
}
/// @param size if zero, will still return a non-null pointer, but not a unique one
void *arena_alloc(Arena *arena, size_t size, bool align)
{
if (align) {
arena->pos = (arena->pos + (ARENA_ALIGN - 1)) & ~(ARENA_ALIGN - 1);
}
if (arena->pos + size > arena->size) {
if (size > (arena->size - sizeof(struct consumed_blk)) >> 1) {
if (arena->pos + size > arena->size || !arena->cur_blk) {
if (size > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk)) >> 1) {
// if allocation is too big, allocate a large block with the requested
// size, but still with block pointer head. We do this even for
// arena->size / 2, as there likely is space left for the next
// small allocation in the current block.
if (!arena->cur_blk) {
// to simplify free-list management, arena->cur_blk must
// always be a normal, ARENA_BLOCK_SIZE sized, block
alloc_block(arena);
}
arena_alloc_count++;
char *alloc = xmalloc(size + sizeof(struct consumed_blk));
struct consumed_blk *cur_blk = (struct consumed_blk *)arena->cur_blk;
struct consumed_blk *fix_blk = (struct consumed_blk *)alloc;
@@ -576,12 +597,7 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
cur_blk->prev = fix_blk;
return (alloc + sizeof(struct consumed_blk));
} else {
struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk;
arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
arena->pos = 0;
arena->size = ARENA_BLOCK_SIZE;
struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
blk->prev = prev_blk;
alloc_block(arena);
}
}

View File

@@ -6,6 +6,8 @@
#include <stdint.h> // for uint8_t
#include <time.h> // for time_t
#include "nvim/macros.h"
/// `malloc()` function signature
typedef void *(*MemMalloc)(size_t);
@@ -37,6 +39,8 @@ extern MemRealloc mem_realloc;
extern bool entered_free_all_mem;
#endif
EXTERN size_t arena_alloc_count INIT(=0);
typedef struct consumed_blk {
struct consumed_blk *prev;
} *ArenaMem;

View File

@@ -1945,7 +1945,7 @@ static void menuitem_getinfo(const char *menu_name, const vimmenu_T *menu, int m
/// "menu_info()" function
/// Return information about a menu (including all the child menus)
void f_menu_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_menu_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
tv_dict_alloc_ret(rettv);
dict_T *const retdict = rettv->vval.v_dict;

View File

@@ -304,7 +304,8 @@ static void handle_request(Channel *channel, Unpacker *p, Array args)
evdata->channel = channel;
evdata->handler = p->handler;
evdata->args = args;
evdata->used_mem = arena_finish(&p->arena);
evdata->used_mem = p->arena;
p->arena = (Arena)ARENA_EMPTY;
evdata->request_id = p->request_id;
channel_incref(channel);
if (p->handler.fast) {
@@ -344,7 +345,8 @@ static void request_event(void **argv)
// channel was closed, abort any pending requests
goto free_ret;
}
Object result = handler.fn(channel->id, e->args, &error);
Object result = handler.fn(channel->id, e->args, &e->used_mem, &error);
if (e->type == kMessageTypeRequest || ERROR_SET(&error)) {
// Send the response.
msgpack_packer response;
@@ -355,13 +357,14 @@ static void request_event(void **argv)
&error,
result,
&out_buffer));
} else {
}
if (!handler.arena_return) {
api_free_object(result);
}
free_ret:
// e->args is allocated in an arena
arena_mem_free(e->used_mem, &channel->rpc.unpacker->reuse_blk);
// e->args (and possibly result) are allocated in an arena
arena_mem_free(arena_finish(&e->used_mem), &channel->rpc.unpacker->reuse_blk);
channel_decref(channel);
xfree(e);
api_clear_error(&error);
@@ -624,7 +627,6 @@ static WBuffer *serialize_response(uint64_t channel_id, MessageType type, uint32
1, // responses only go though 1 channel
xfree);
msgpack_sbuffer_clear(sbuffer);
api_free_object(arg);
return rv;
}

View File

@@ -27,7 +27,7 @@ typedef struct {
MsgpackRpcRequestHandler handler;
Array args;
uint32_t request_id;
ArenaMem used_mem;
Arena used_mem;
} RequestEvent;
typedef struct {

View File

@@ -7169,14 +7169,14 @@ static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *
}
/// "getloclist()" function
void f_getloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_getloclist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
win_T *wp = find_win_by_nr_or_id(&argvars[0]);
get_qf_loc_list(false, wp, &argvars[1], rettv);
}
/// "getqflist()" functions
void f_getqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_getqflist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
get_qf_loc_list(true, NULL, &argvars[0], rettv);
}
@@ -7263,7 +7263,7 @@ skip_args:
}
/// "setloclist()" function
void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_setloclist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = -1;
@@ -7274,7 +7274,7 @@ void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "setqflist()" function
void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_setqflist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
set_qf_ll_list(NULL, argvars, rettv);
}

View File

@@ -4637,7 +4637,7 @@ static void update_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, searchst
}
// "searchcount()" function
void f_searchcount(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_searchcount(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
pos_T pos = curwin->w_cursor;
char_u *pattern = NULL;
@@ -5287,13 +5287,13 @@ static void do_fuzzymatch(const typval_T *const argvars, typval_T *const rettv,
}
/// "matchfuzzy()" function
void f_matchfuzzy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_matchfuzzy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
do_fuzzymatch(argvars, rettv, false);
}
/// "matchfuzzypos()" function
void f_matchfuzzypos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_matchfuzzypos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
do_fuzzymatch(argvars, rettv, true);
}

View File

@@ -1964,7 +1964,7 @@ static void sign_define_multiple(list_T *l, list_T *retlist)
}
/// "sign_define()" function
void f_sign_define(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sign_define(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *name;
@@ -1995,7 +1995,7 @@ void f_sign_define(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_getdefined()" function
void f_sign_getdefined(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sign_getdefined(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *name = NULL;
@@ -2009,7 +2009,7 @@ void f_sign_getdefined(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_getplaced()" function
void f_sign_getplaced(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sign_getplaced(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
buf_T *buf = NULL;
dict_T *dict;
@@ -2067,7 +2067,7 @@ void f_sign_getplaced(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_jump()" function
void f_sign_jump(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sign_jump(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int sign_id;
char *sign_group = NULL;
@@ -2225,7 +2225,7 @@ cleanup:
}
/// "sign_place()" function
void f_sign_place(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sign_place(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
dict_T *dict = NULL;
@@ -2243,7 +2243,7 @@ void f_sign_place(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_placelist()" function. Place multiple signs.
void f_sign_placelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sign_placelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int sign_id;
@@ -2283,7 +2283,7 @@ static void sign_undefine_multiple(list_T *l, list_T *retlist)
}
/// "sign_undefine()" function
void f_sign_undefine(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sign_undefine(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *name;
@@ -2373,7 +2373,7 @@ cleanup:
}
/// "sign_unplace()" function
void f_sign_unplace(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sign_unplace(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
dict_T *dict = NULL;
@@ -2396,7 +2396,7 @@ void f_sign_unplace(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "sign_unplacelist()" function
void f_sign_unplacelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_sign_unplacelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int retval;

View File

@@ -326,19 +326,19 @@ static int assert_beeps(typval_T *argvars, bool no_beep)
}
/// "assert_beeps(cmd [, error])" function
void f_assert_beeps(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_beeps(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_beeps(argvars, false);
}
/// "assert_nobeep(cmd [, error])" function
void f_assert_nobeep(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_nobeep(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_beeps(argvars, true);
}
/// "assert_equal(expected, actual[, msg])" function
void f_assert_equal(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_equal(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_equal_common(argvars, ASSERT_EQUAL);
}
@@ -433,19 +433,19 @@ static int assert_equalfile(typval_T *argvars)
}
/// "assert_equalfile(fname-one, fname-two[, msg])" function
void f_assert_equalfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_equalfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_equalfile(argvars);
}
/// "assert_notequal(expected, actual[, msg])" function
void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_notequal(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_equal_common(argvars, ASSERT_NOTEQUAL);
}
/// "assert_exception(string[, msg])" function
void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_exception(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
garray_T ga;
@@ -468,7 +468,7 @@ void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "assert_fails(cmd [, error [, msg]])" function
void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const cmd = tv_get_string_chk(&argvars[0]);
garray_T ga;
@@ -513,7 +513,7 @@ void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
// "assert_false(actual[, msg])" function
void f_assert_false(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_false(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_bool(argvars, false);
}
@@ -574,25 +574,25 @@ static int assert_inrange(typval_T *argvars)
}
/// "assert_inrange(lower, upper[, msg])" function
void f_assert_inrange(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_inrange(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_inrange(argvars);
}
/// "assert_match(pattern, actual[, msg])" function
void f_assert_match(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_match(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_match_common(argvars, ASSERT_MATCH);
}
/// "assert_notmatch(pattern, actual[, msg])" function
void f_assert_notmatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_notmatch(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_match_common(argvars, ASSERT_NOTMATCH);
}
/// "assert_report(msg)" function
void f_assert_report(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_report(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
garray_T ga;
@@ -604,13 +604,13 @@ void f_assert_report(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "assert_true(actual[, msg])" function
void f_assert_true(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_assert_true(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->vval.v_number = assert_bool(argvars, true);
}
/// "test_garbagecollect_now()" function
void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, FunPtr fptr)
void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
// This is dangerous, any Lists and Dicts used internally may be freed
// while still in use.
@@ -618,7 +618,7 @@ void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// "test_write_list_log()" function
void f_test_write_list_log(typval_T *const argvars, typval_T *const rettv, FunPtr fptr)
void f_test_write_list_log(typval_T *const argvars, typval_T *const rettv, EvalFuncData fptr)
{
const char *const fname = tv_get_string_chk(&argvars[0]);
if (fname == NULL) {

View File

@@ -22,7 +22,17 @@ typedef int handle_T;
// absent callback etc.
typedef int LuaRef;
typedef void (*FunPtr)(void);
/// Type used for VimL VAR_FLOAT values
typedef double float_T;
typedef struct MsgpackRpcRequestHandler MsgpackRpcRequestHandler;
typedef union {
float_T (*float_func)(float_T);
const MsgpackRpcRequestHandler *api_handler;
void *nullptr;
} EvalFuncData;
typedef handle_T NS;

View File

@@ -55,7 +55,7 @@ UIClientHandler ui_client_get_redraw_handler(const char *name, size_t name_len,
/// async 'redraw' events, which are expected when nvim acts as an ui client.
/// get handled in msgpack_rpc/unpacker.c and directly dispatched to handlers
/// of specific ui events, like ui_client_event_grid_resize and so on.
Object handle_ui_client_redraw(uint64_t channel_id, Array args, Error *error)
Object handle_ui_client_redraw(uint64_t channel_id, Array args, Arena *arena, Error *error)
{
api_set_error(error, kErrorTypeValidation, "'redraw' cannot be sent as a request");
return NIL;