From c0d60526541a3cf977ae623471ae4a347b492af1 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 23 Aug 2022 09:33:08 +0200 Subject: perf(api): allow to use an arena for return values --- src/nvim/msgpack_rpc/channel.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/nvim/msgpack_rpc/channel.c') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 1ca68979f4..66fd79c692 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -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; } -- cgit From bcf5ee328e228d5a536b4de2069a79234f9f3e9e Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 23 Aug 2022 10:36:46 +0200 Subject: refactor(arena): use a shared block freelist This is both simpler in client code and more effective (always reuse block hottest in cache) --- src/nvim/msgpack_rpc/channel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/msgpack_rpc/channel.c') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 66fd79c692..f00c62f766 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -158,7 +158,7 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem } // frame.result was allocated in an arena - arena_mem_free(frame.result_mem, &rpc->unpacker->reuse_blk); + arena_mem_free(frame.result_mem); frame.result_mem = NULL; } @@ -244,7 +244,7 @@ static void parse_msgpack(Channel *channel) ui_client_event_raw_line(p->grid_line_event); } else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) { p->ui_handler.fn(p->result.data.array); - arena_mem_free(arena_finish(&p->arena), &p->reuse_blk); + arena_mem_free(arena_finish(&p->arena)); } } else if (p->type == kMessageTypeResponse) { ChannelCallFrame *frame = kv_last(channel->rpc.call_stack); @@ -295,7 +295,7 @@ static void handle_request(Channel *channel, Unpacker *p, Array args) if (!p->handler.fn) { send_error(channel, p->type, p->request_id, p->unpack_error.msg); api_clear_error(&p->unpack_error); - arena_mem_free(arena_finish(&p->arena), &p->reuse_blk); + arena_mem_free(arena_finish(&p->arena)); return; } @@ -364,7 +364,7 @@ static void request_event(void **argv) free_ret: // e->args (and possibly result) are allocated in an arena - arena_mem_free(arena_finish(&e->used_mem), &channel->rpc.unpacker->reuse_blk); + arena_mem_free(arena_finish(&e->used_mem)); channel_decref(channel); xfree(e); api_clear_error(&error); -- cgit From 7784dc9e0d90284b0d9c9cf0833c27d4de22b7f4 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 23 Aug 2022 13:52:09 +0200 Subject: refactor(api): provide a temporary copy solution for nvim_call_atomic Make the copy_object() family accept an optional arena. More than half of the callsites should be refactored to use an arena later anyway. --- src/nvim/msgpack_rpc/channel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/msgpack_rpc/channel.c') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index f00c62f766..d22bcb29d5 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -644,7 +644,7 @@ void rpc_set_client_info(uint64_t id, Dictionary info) Dictionary rpc_client_info(Channel *chan) { - return copy_dictionary(chan->rpc.info); + return copy_dictionary(chan->rpc.info, NULL); } const char *rpc_client_name(Channel *chan) -- cgit From 91e912f8d40284c74d4a997c8c95961eebb35d91 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 25 Sep 2022 15:26:37 +0200 Subject: refactor: move klib out of src/nvim/ #20341 It's confusing to mix vendored dependencies with neovim source code. A clean separation is simpler to keep track of and simpler to document. --- src/nvim/msgpack_rpc/channel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/msgpack_rpc/channel.c') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index d22bcb29d5..71ed5ccf81 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -7,6 +7,7 @@ #include #include +#include "klib/kvec.h" #include "nvim/api/private/helpers.h" #include "nvim/api/ui.h" #include "nvim/api/vim.h" @@ -18,7 +19,6 @@ #include "nvim/event/rstream.h" #include "nvim/event/socket.h" #include "nvim/event/wstream.h" -#include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/map.h" -- cgit From 66360675cf4d091b7460e4a8e1435c13216c1929 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 11 Sep 2022 17:12:44 +0200 Subject: build: allow IWYU to fix includes for all .c files Allow Include What You Use to remove unnecessary includes and only include what is necessary. This helps with reducing compilation times and makes it easier to visualise which dependencies are actually required. Work on https://github.com/neovim/neovim/issues/549, but doesn't close it since this only works fully for .c files and not headers. --- src/nvim/msgpack_rpc/channel.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src/nvim/msgpack_rpc/channel.c') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 71ed5ccf81..516af20fe9 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -1,36 +1,42 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +#include #include -#include +#include +#include +#include +#include #include -#include +#include +#include #include #include "klib/kvec.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/api/ui.h" -#include "nvim/api/vim.h" -#include "nvim/ascii.h" #include "nvim/channel.h" -#include "nvim/eval.h" -#include "nvim/event/libuv_process.h" +#include "nvim/event/defs.h" #include "nvim/event/loop.h" #include "nvim/event/rstream.h" -#include "nvim/event/socket.h" +#include "nvim/event/stream.h" #include "nvim/event/wstream.h" +#include "nvim/globals.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/map.h" #include "nvim/memory.h" -#include "nvim/message.h" #include "nvim/msgpack_rpc/channel.h" +#include "nvim/msgpack_rpc/channel_defs.h" #include "nvim/msgpack_rpc/helpers.h" #include "nvim/msgpack_rpc/unpacker.h" #include "nvim/os/input.h" -#include "nvim/os_unix.h" +#include "nvim/rbuffer.h" +#include "nvim/types.h" #include "nvim/ui.h" -#include "nvim/vim.h" +#include "nvim/ui_client.h" #if MIN_LOG_LEVEL > LOGLVL_DBG # define log_client_msg(...) -- cgit From 43e8ec92de9e0850e7d202cb7ff9051bc408447e Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 2 May 2022 21:10:01 +0200 Subject: fix(tui): more work in the TUI --- src/nvim/msgpack_rpc/channel.c | 56 +++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 31 deletions(-) (limited to 'src/nvim/msgpack_rpc/channel.c') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 516af20fe9..4d011dc079 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -250,8 +250,8 @@ static void parse_msgpack(Channel *channel) ui_client_event_raw_line(p->grid_line_event); } else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) { p->ui_handler.fn(p->result.data.array); - arena_mem_free(arena_finish(&p->arena)); } + arena_mem_free(arena_finish(&p->arena)); } else if (p->type == kMessageTypeResponse) { ChannelCallFrame *frame = kv_last(channel->rpc.call_stack); if (p->request_id != frame->request_id) { @@ -299,7 +299,7 @@ static void handle_request(Channel *channel, Unpacker *p, Array args) assert(p->type == kMessageTypeRequest || p->type == kMessageTypeNotification); if (!p->handler.fn) { - send_error(channel, p->type, p->request_id, p->unpack_error.msg); + send_error(channel, p->handler, p->type, p->request_id, p->unpack_error.msg); api_clear_error(&p->unpack_error); arena_mem_free(arena_finish(&p->arena)); return; @@ -358,6 +358,7 @@ static void request_event(void **argv) msgpack_packer response; msgpack_packer_init(&response, &out_buffer, msgpack_sbuffer_write); channel_write(channel, serialize_response(channel->id, + e->handler, e->type, e->request_id, &error, @@ -440,11 +441,13 @@ static void internal_read_event(void **argv) wstream_release_wbuffer(buffer); } -static void send_error(Channel *chan, MessageType type, uint32_t id, char *err) +static void send_error(Channel *chan, MsgpackRpcRequestHandler handler, MessageType type, + uint32_t id, char *err) { Error e = ERROR_INIT; api_set_error(&e, kErrorTypeException, "%s", err); channel_write(chan, serialize_response(chan->id, + handler, type, id, &e, @@ -543,26 +546,8 @@ void rpc_close(Channel *channel) channel_decref(channel); if (channel->streamtype == kChannelStreamStdio - || channel->id == ui_client_channel_id) { - multiqueue_put(main_loop.fast_events, exit_event, 0); - } -} - -static void exit_delay_cb(uv_timer_t *handle) -{ - uv_timer_stop(&main_loop.exit_delay_timer); - multiqueue_put(main_loop.fast_events, exit_event, 0); -} - -static void exit_event(void **argv) -{ - if (exit_need_delay) { - uv_timer_start(&main_loop.exit_delay_timer, exit_delay_cb, 0, 0); - return; - } - - if (!exiting) { - os_exit(0); + || (channel->id == ui_client_channel_id && channel->streamtype != kChannelStreamProc)) { + exit_from_channel(0); } } @@ -612,18 +597,27 @@ static WBuffer *serialize_request(uint64_t channel_id, uint32_t request_id, cons return rv; } -static WBuffer *serialize_response(uint64_t channel_id, MessageType type, uint32_t response_id, - Error *err, Object arg, msgpack_sbuffer *sbuffer) +static WBuffer *serialize_response(uint64_t channel_id, MsgpackRpcRequestHandler handler, + MessageType type, uint32_t response_id, Error *err, Object arg, + msgpack_sbuffer *sbuffer) { msgpack_packer pac; msgpack_packer_init(&pac, sbuffer, msgpack_sbuffer_write); if (ERROR_SET(err) && type == kMessageTypeNotification) { - Array args = ARRAY_DICT_INIT; - ADD(args, INTEGER_OBJ(err->type)); - ADD(args, STRING_OBJ(cstr_to_string(err->msg))); - msgpack_rpc_serialize_request(0, cstr_as_string("nvim_error_event"), - args, &pac); - api_free_array(args); + if (handler.fn == handle_nvim_paste) { + // TODO(bfredl): this is pretty much ad-hoc. maybe TUI and UI:s should be + // allowed to ask nvim to just scream directly in the users face + // instead of sending nvim_error_event, in general. + semsg("paste: %s", err->msg); + api_clear_error(err); + } else { + Array args = ARRAY_DICT_INIT; + ADD(args, INTEGER_OBJ(err->type)); + ADD(args, STRING_OBJ(cstr_to_string(err->msg))); + msgpack_rpc_serialize_request(0, cstr_as_string("nvim_error_event"), + args, &pac); + api_free_array(args); + } } else { msgpack_rpc_serialize_response(response_id, err, arg, &pac); } -- cgit From b2295ac4ec80e141628cea33ebee81c96e168989 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 3 Jan 2023 15:24:41 +0100 Subject: refactor(api): do not allocate temporaries for internal events --- src/nvim/msgpack_rpc/channel.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/msgpack_rpc/channel.c') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 4d011dc079..5b8e330e15 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -136,6 +136,7 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem uint32_t request_id = rpc->next_request_id++; // Send the msgpack-rpc request send_request(channel, request_id, method_name, args); + api_free_array(args); // Push the frame ChannelCallFrame frame = { request_id, false, false, NIL, NULL }; @@ -491,7 +492,6 @@ static void broadcast_event(const char *name, Array args) }); if (!kv_size(subscribed)) { - api_free_array(args); goto end; } @@ -593,7 +593,6 @@ static WBuffer *serialize_request(uint64_t channel_id, uint32_t request_id, cons refcount, xfree); msgpack_sbuffer_clear(sbuffer); - api_free_array(args); return rv; } -- cgit From bb7033a0338e9133765f9b2e1e6dc096847d17e3 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 9 Jan 2023 13:26:18 +0100 Subject: fix(rpc): don't free args on error in rpc_send_event fixup #21631 fixes #21690 --- src/nvim/msgpack_rpc/channel.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/msgpack_rpc/channel.c') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 5b8e330e15..0c23a7798c 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -100,7 +100,6 @@ bool rpc_send_event(uint64_t id, const char *name, Array args) Channel *channel = NULL; if (id && (!(channel = find_rpc_channel(id)))) { - api_free_array(args); return false; } -- cgit From 3269902a13df3bccf8705db73488c0a47f495514 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 15 Jan 2023 14:16:33 +0100 Subject: refactor: fix IWYU mapping file and use IWYU (#21802) Also add the EXITFREE definition to main_lib rather than the nvim target, as the header generation needs the EXITFREE flag to work properly. --- src/nvim/msgpack_rpc/channel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/msgpack_rpc/channel.c') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 0c23a7798c..d60e18590f 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -20,14 +20,15 @@ #include "nvim/channel.h" #include "nvim/event/defs.h" #include "nvim/event/loop.h" +#include "nvim/event/process.h" #include "nvim/event/rstream.h" #include "nvim/event/stream.h" #include "nvim/event/wstream.h" -#include "nvim/globals.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/map.h" #include "nvim/memory.h" +#include "nvim/message.h" #include "nvim/msgpack_rpc/channel.h" #include "nvim/msgpack_rpc/channel_defs.h" #include "nvim/msgpack_rpc/helpers.h" -- cgit