diff options
author | bfredl <bjorn.linse@gmail.com> | 2022-08-23 13:52:09 +0200 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2022-08-24 14:22:26 +0200 |
commit | 7784dc9e0d90284b0d9c9cf0833c27d4de22b7f4 (patch) | |
tree | 297ed9f2974d08b1c83c829c4fe265fba101b629 /src/nvim/api | |
parent | bcf5ee328e228d5a536b4de2069a79234f9f3e9e (diff) | |
download | rneovim-7784dc9e0d90284b0d9c9cf0833c27d4de22b7f4.tar.gz rneovim-7784dc9e0d90284b0d9c9cf0833c27d4de22b7f4.tar.bz2 rneovim-7784dc9e0d90284b0d9c9cf0833c27d4de22b7f4.zip |
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.
Diffstat (limited to 'src/nvim/api')
-rw-r--r-- | src/nvim/api/autocmd.c | 4 | ||||
-rw-r--r-- | src/nvim/api/extmark.c | 2 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c | 33 | ||||
-rw-r--r-- | src/nvim/api/ui.c | 6 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 46 |
5 files changed, 48 insertions, 43 deletions
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 79ae7994f7..1cf0211f43 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -887,12 +887,12 @@ static bool check_autocmd_string_array(Array arr, char *k, Error *err) static bool unpack_string_or_array(Array *array, Object *v, char *k, bool required, Error *err) { if (v->type == kObjectTypeString) { - ADD(*array, copy_object(*v)); + ADD(*array, copy_object(*v, NULL)); } else if (v->type == kObjectTypeArray) { if (!check_autocmd_string_array(v->data.array, k, err)) { return false; } - *array = copy_array(v->data.array); + *array = copy_array(v->data.array, NULL); } else { if (required) { api_set_error(err, diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 933aa85530..1d6eaa42b0 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -51,7 +51,7 @@ Integer nvim_create_namespace(String name) } id = next_namespace_id++; if (name.size > 0) { - String name_alloc = copy_string(name); + String name_alloc = copy_string(name, NULL); map_put(String, handle_T)(&namespace_ids, name_alloc, id); } return (Integer)id; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index c466fc53e1..e35c58bf1b 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -618,6 +618,7 @@ void api_clear_error(Error *value) value->type = kErrorTypeNone; } +/// @returns a shared value. caller must not modify it! Dictionary api_metadata(void) { static Dictionary metadata = ARRAY_DICT_INIT; @@ -630,7 +631,7 @@ Dictionary api_metadata(void) init_type_metadata(&metadata); } - return copy_object(DICTIONARY_OBJ(metadata)).data.dictionary; + return metadata; } static void init_function_metadata(Dictionary *metadata) @@ -715,36 +716,40 @@ static void init_type_metadata(Dictionary *metadata) PUT(*metadata, "types", DICTIONARY_OBJ(types)); } -String copy_string(String str) +// all the copy_[object] functions allow arena=NULL, +// then global allocations are used, and the resulting object +// should be freed with an api_free_[object] function + +String copy_string(String str, Arena *arena) { if (str.data != NULL) { - return (String){ .data = xmemdupz(str.data, str.size), .size = str.size }; + return (String){ .data = arena_memdupz(arena, str.data, str.size), .size = str.size }; } else { return (String)STRING_INIT; } } -Array copy_array(Array array) +Array copy_array(Array array, Arena *arena) { - Array rv = ARRAY_DICT_INIT; + Array rv = arena_array(arena, array.size); for (size_t i = 0; i < array.size; i++) { - ADD(rv, copy_object(array.items[i])); + ADD(rv, copy_object(array.items[i], arena)); } return rv; } -Dictionary copy_dictionary(Dictionary dict) +Dictionary copy_dictionary(Dictionary dict, Arena *arena) { - Dictionary rv = ARRAY_DICT_INIT; + Dictionary rv = arena_dict(arena, dict.size); for (size_t i = 0; i < dict.size; i++) { KeyValuePair item = dict.items[i]; - PUT(rv, item.key.data, copy_object(item.value)); + PUT_C(rv, copy_string(item.key, arena).data, copy_object(item.value, arena)); } return rv; } /// Creates a deep clone of an object -Object copy_object(Object obj) +Object copy_object(Object obj, Arena *arena) { switch (obj.type) { case kObjectTypeBuffer: @@ -757,13 +762,13 @@ Object copy_object(Object obj) return obj; case kObjectTypeString: - return STRING_OBJ(copy_string(obj.data.string)); + return STRING_OBJ(copy_string(obj.data.string, arena)); case kObjectTypeArray: - return ARRAY_OBJ(copy_array(obj.data.array)); + return ARRAY_OBJ(copy_array(obj.data.array, arena)); case kObjectTypeDictionary: - return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary)); + return DICTIONARY_OBJ(copy_dictionary(obj.data.dictionary, arena)); case kObjectTypeLuaRef: return LUAREF_OBJ(api_new_luaref(obj.data.luaref)); @@ -844,7 +849,7 @@ HlMessage parse_hl_msg(Array chunks, Error *err) goto free_exit; } - String str = copy_string(chunk.items[0].data.string); + String str = copy_string(chunk.items[0].data.string, NULL); int attr = 0; if (chunk.size == 2) { diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 6f7bfa244a..e34dcbdb46 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -965,7 +965,7 @@ static Array translate_contents(UI *ui, Array contents) } else { ADD(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT)); } - ADD(new_item, copy_object(item.items[1])); + ADD(new_item, copy_object(item.items[1], NULL)); ADD(new_contents, ARRAY_OBJ(new_item)); } return new_contents; @@ -978,7 +978,7 @@ static Array translate_firstarg(UI *ui, Array args) ADD(new_args, ARRAY_OBJ(translate_contents(ui, contents))); for (size_t i = 1; i < args.size; i++) { - ADD(new_args, copy_object(args.items[i])); + ADD(new_args, copy_object(args.items[i], NULL)); } return new_args; } @@ -1024,7 +1024,7 @@ static void remote_ui_event(UI *ui, char *name, Array args) Array items = args.items[0].data.array; Array new_items = ARRAY_DICT_INIT; for (size_t i = 0; i < items.size; i++) { - ADD(new_items, copy_object(items.items[i].data.array.items[0])); + ADD(new_items, copy_object(items.items[i].data.array.items[0], NULL)); } ADD_C(new_args, ARRAY_OBJ(new_items)); push_call(ui, "wildmenu_show", new_args); diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index c333db1b37..7b70de7b12 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1479,14 +1479,14 @@ void nvim_del_keymap(uint64_t channel_id, String mode, String lhs, Error *err) /// 1 is the |api-metadata| map (Dictionary). /// /// @returns 2-tuple [{channel-id}, {api-metadata}] -Array nvim_get_api_info(uint64_t channel_id) +Array nvim_get_api_info(uint64_t channel_id, Arena *arena) FUNC_API_SINCE(1) FUNC_API_FAST FUNC_API_REMOTE_ONLY { - Array rv = ARRAY_DICT_INIT; + Array rv = arena_array(arena, 2); assert(channel_id <= INT64_MAX); - ADD(rv, INTEGER_OBJ((int64_t)channel_id)); - ADD(rv, DICTIONARY_OBJ(api_metadata())); + ADD_C(rv, INTEGER_OBJ((int64_t)channel_id)); + ADD_C(rv, DICTIONARY_OBJ(api_metadata())); return rv; } @@ -1545,9 +1545,9 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY { Dictionary info = ARRAY_DICT_INIT; - PUT(info, "name", copy_object(STRING_OBJ(name))); + PUT(info, "name", copy_object(STRING_OBJ(name), NULL)); - version = copy_dictionary(version); + version = copy_dictionary(version, NULL); bool has_major = false; for (size_t i = 0; i < version.size; i++) { if (strequal(version.items[i].key.data, "major")) { @@ -1560,9 +1560,9 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, } PUT(info, "version", DICTIONARY_OBJ(version)); - PUT(info, "type", copy_object(STRING_OBJ(type))); - PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods))); - PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes))); + PUT(info, "type", copy_object(STRING_OBJ(type), NULL)); + PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods, NULL))); + PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes, NULL))); rpc_set_client_info(channel_id, info); } @@ -1642,21 +1642,21 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er api_set_error(err, kErrorTypeValidation, "Items in calls array must be arrays"); - goto validation_error; + goto theend; } Array call = calls.items[i].data.array; if (call.size != 2) { api_set_error(err, kErrorTypeValidation, "Items in calls array must be arrays of size 2"); - goto validation_error; + goto theend; } if (call.items[0].type != kObjectTypeString) { api_set_error(err, kErrorTypeValidation, "Name must be String"); - goto validation_error; + goto theend; } String name = call.items[0].data.string; @@ -1664,7 +1664,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er api_set_error(err, kErrorTypeValidation, "Args must be Array"); - goto validation_error; + goto theend; } Array args = call.items[1].data.array; @@ -1682,11 +1682,13 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er // error handled after loop break; } - if (!handler.arena_return && result.type != kObjectTypeNil) { - // TODO: fix to not leak memory as fuck + // TODO(bfredl): wastefull copy. It could be avoided to encoding to msgpack + // directly here. But `result` might become invalid when next api function + // is called in the loop. + ADD_C(results, copy_object(result, arena)); + if (!handler.arena_return) { + api_free_object(result); } - - ADD_C(results, result); } ADD_C(rv, ARRAY_OBJ(results)); @@ -1694,14 +1696,12 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er 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(errval, STRING_OBJ(copy_string(cstr_as_string(nested_error.msg), arena))); ADD_C(rv, ARRAY_OBJ(errval)); } else { ADD_C(rv, NIL); } - goto theend; -validation_error: theend: api_clear_error(&nested_error); return rv; @@ -1754,7 +1754,7 @@ static void write_msg(String message, bool to_err) /// @return its argument. Object nvim__id(Object obj) { - return copy_object(obj); + return copy_object(obj, NULL); } /// Returns array given as argument. @@ -1767,7 +1767,7 @@ Object nvim__id(Object obj) /// @return its argument. Array nvim__id_array(Array arr) { - return copy_object(ARRAY_OBJ(arr)).data.array; + return copy_array(arr, NULL); } /// Returns dictionary given as argument. @@ -1780,7 +1780,7 @@ Array nvim__id_array(Array arr) /// @return its argument. Dictionary nvim__id_dictionary(Dictionary dct) { - return copy_object(DICTIONARY_OBJ(dct)).data.dictionary; + return copy_dictionary(dct, NULL); } /// Returns floating-point value given as argument. |