mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 03:48:18 +00:00
perf(api): allow to use an arena for return values
This commit is contained in:
@@ -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))
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
ADD(results, result);
|
||||
if (!handler.arena_return && result.type != kObjectTypeNil) {
|
||||
// TODO: fix to not leak memory as fuck
|
||||
}
|
||||
|
||||
ADD(rv, ARRAY_OBJ(results));
|
||||
ADD_C(results, result);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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
@@ -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
|
||||
|
@@ -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));
|
||||
|
@@ -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), };
|
||||
|
||||
|
@@ -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])) {
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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))
|
||||
)
|
||||
|
@@ -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);
|
||||
|
@@ -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()
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
} else {
|
||||
arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
|
||||
}
|
||||
arena->pos = 0;
|
||||
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 = NULL;
|
||||
arena->size = 0;
|
||||
arena->pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -27,7 +27,7 @@ typedef struct {
|
||||
MsgpackRpcRequestHandler handler;
|
||||
Array args;
|
||||
uint32_t request_id;
|
||||
ArenaMem used_mem;
|
||||
Arena used_mem;
|
||||
} RequestEvent;
|
||||
|
||||
typedef struct {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user