-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RDY] Remove recursion from various serializers/converters #4607
[RDY] Remove recursion from various serializers/converters #4607
Conversation
There is also a question: now I can treat special dictionaries specially in vim_to_object, but currently chosen not to do so. Most interesting part of them is that you may pass strings with NUL bytes through API undamaged, assuming object_to_vim will support this enhancement. If you think it is good idea to treat special dictionaries specially what do you think should be done? Current variant is:
|
f6a587f
to
2460ea4
Compare
Removed recursion from three functions just to find out there is recursion which crashes my ASAN build when doing clear_tv. I also remember garbage_collect being not fine with something like this. |
What is the disadvantage? |
Breaks backwards compatibility. Makes hack created because of flaws in the existing data types more official: if we e.g. will ever have normal objects (even internally: i.e. VAR_OBJECT which consists of void *data and struct { BinaryOp add; ... } *type which will be used for some types, but without a way to construct them provided by user) it will be harder to get rid of special dictionaries if they are that common. Though this is minor. More major is that not all special dictionaries can be expressed with Object: specifically:
This is either extending of the API types or admitting that some special dictionaries are even more special - and result in a NIL. |
f3ca24b
to
20c5d5a
Compare
0ccb90e
to
23f929f
Compare
336d89b
to
fed833b
Compare
Rebase should clear up the build. |
#define API_INTEGER_MAX INT64_MAX | ||
|
||
/// Minimum value of an Integer | ||
#define API_INTEGER_MIN INT64_MIN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not used anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API_INTEGER_MIN was added because I added API_INTEGER_MAX (which is used), not because it is used.
7288131
to
e6c2988
Compare
do { \ | ||
if (tv->vval.v_list->lv_refcount > 1) { \ | ||
tv->vval.v_list->lv_refcount--; \ | ||
tv->vval.v_list = NULL; \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This macro is called before we push a new element on the stack in nothing_convert_one_value()
.
When constructing the pushed element, tv->vval.v_list->lv_first
is read after tv->vval.v_list
was set to NULL
.
e6c2988
to
a865a4b
Compare
if ((r = did_set_string_option(opt_idx, varp, (int)true, oldval, NULL, | ||
opt_flags)) == NULL) | ||
did_set_option(opt_idx, opt_flags, TRUE); | ||
char *r = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initialize with function output did_set_string_option()
instead of NULL
.
This ought to prevent stack overflow, but I do not see this actually working: *lua* code crashes with stack overflow when trying to deserialize msgpack from Neovim, Neovim is fine even if nesting level is increased 100x (though test becomes very slow); not sure how recursive function may survive this. So it looks like there are currently only two positive effects: 1. NULL lists are returned as empty (neovim#4596). 2. Functional tests are slightly more fast. Very slightly. Checked for Release build for test/functional/eval tests because benchmarking of debug mode is not very useful.
This removes some stack overflows in new test regarding deeply nested variables. Now in place of crashing vim_to_object/msgpack_rpc_from_object/etc it crashes clear_tv with stack overflow.
It appears that used msgpack library is not able to parse back message created by msgpack_rpc_from_object() if nesting level is too high, so log_server_msg now cares about msgpack_unpack_next() return value. Also error message from server_notifications_spec.lua is not readable if something is wrong (though at least now it does not crash when parsing deeply nested structures). log_server_msg() in the test reports [msgpack-rpc] nvim -> client(1) [error] "parse error"
d0de23b
to
458a4d0
Compare
This avoids gcc warnings about undefined behaviour.
Also adds one exception to linter rules: typedef struct { kvec_t(Object) stack; } EncodedData; is completely valid (from the style guide point of view) code.
Tests pass, so this looks like RDY. |
I will do some benchmarks regarding kv vs kvi now though. |
Benchmarks still confirm that kvi is good when working with not too nested (did not actually confirm, but I expect that it should be better with up to 8 nesting levels) objects while kv variant is slightly better when working with deeply nested objects. Since I guess that slightly nested objects are more common, this should be left as-is.
|
Marking this as RDY. |
For kv tests apply diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h
index 98fa7b2..fa8bf5f 100644
--- a/src/nvim/eval/typval_encode.h
+++ b/src/nvim/eval/typval_encode.h
@@ -169,13 +169,13 @@ typedef struct {
} MPConvStackVal;
/// Stack used to convert VimL values to messagepack.
-typedef kvec_withinit_t(MPConvStackVal, 8) MPConvStack;
+typedef kvec_t(MPConvStackVal) MPConvStack;
// Defines for MPConvStack
#define _mp_size kv_size
-#define _mp_init kvi_init
-#define _mp_destroy kvi_destroy
-#define _mp_push kvi_push
+#define _mp_init kv_init
+#define _mp_destroy kv_destroy
+#define _mp_push kv_push
#define _mp_pop kv_pop
#define _mp_last kv_last
|
|
||
#define TYPVAL_ENCODE_CONV_NUMBER(ignored) \ | ||
do { \ | ||
(void)ignored; \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the purpose of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@justinmk If you see me writing something like this it means I got compiler warning. I cannot recall details now, but I do not use such code without purpose. If I am not mistaking problem is code in the unreachable if(TYPVAL_ENCODE_ALLOW_SPECIALS && …)
: even though it is unreachable, compiler still checks this before optimizing out.
Ups: 2968dc7. Forgot to |
@ZyX-I Is this a false positive (coverity)?
|
@justinmk Cannot say now, maybe this is not a false positive if |
Contains:
Also fixes #4596.
Extracted from #4411.