From 8fd3d31329ba428a8624da869c24c5df38623ea3 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Jan 2017 13:52:51 +0300 Subject: unittest: Allow mocking allocator calls --- src/nvim/memory.c | 55 +++++++++++++++++++++++++++++++++++++++---------------- src/nvim/memory.h | 10 ++++++++++ 2 files changed, 49 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 1884d55999..3c0d001848 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -17,10 +17,31 @@ // Force je_ prefix on jemalloc functions. # define JEMALLOC_NO_DEMANGLE # include -# define malloc(size) je_malloc(size) -# define calloc(count, size) je_calloc(count, size) -# define realloc(ptr, size) je_realloc(ptr, size) -# define free(ptr) je_free(ptr) +#endif + +#ifdef UNIT_TESTING +# define malloc(size) mem_malloc(size) +# define calloc(count, size) mem_calloc(count, size) +# define realloc(ptr, size) mem_realloc(ptr, size) +# define free(ptr) mem_free(ptr) +# ifdef HAVE_JEMALLOC +MemMalloc mem_malloc = &je_malloc; +MemFree mem_free = &je_free; +MemCalloc mem_calloc = &je_calloc; +MemRealloc mem_realloc = &je_realloc; +# else +MemMalloc mem_malloc = &malloc; +MemFree mem_free = &free; +MemCalloc mem_calloc = &calloc; +MemRealloc mem_realloc = &realloc; +# endif +#else +# ifdef HAVE_JEMALLOC +# define malloc(size) je_malloc(size) +# define calloc(count, size) je_calloc(count, size) +# define realloc(ptr, size) je_realloc(ptr, size) +# define free(ptr) je_free(ptr) +# endif #endif #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -353,15 +374,15 @@ char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen) size_t xstrlcpy(char *restrict dst, const char *restrict src, size_t size) FUNC_ATTR_NONNULL_ALL { - size_t ret = strlen(src); + size_t ret = strlen(src); - if (size) { - size_t len = (ret >= size) ? size - 1 : ret; - memcpy(dst, src, len); - dst[len] = '\0'; - } + if (size) { + size_t len = (ret >= size) ? size - 1 : ret; + memcpy(dst, src, len); + dst[len] = '\0'; + } - return ret; + return ret; } /// strdup() wrapper @@ -371,6 +392,7 @@ size_t xstrlcpy(char *restrict dst, const char *restrict src, size_t size) /// @return pointer to a copy of the string char *xstrdup(const char *str) FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET + FUNC_ATTR_NONNULL_ALL { return xmemdupz(str, strlen(str)); } @@ -401,6 +423,7 @@ void *xmemrchr(const void *src, uint8_t c, size_t len) /// @return pointer to a copy of the string char *xstrndup(const char *str, size_t len) FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET + FUNC_ATTR_NONNULL_ALL { char *p = memchr(str, '\0', len); return xmemdupz(str, p ? (size_t)(p - str) : len); @@ -488,13 +511,13 @@ void time_to_bytes(time_t time_, uint8_t buf[8]) void free_all_mem(void) { buf_T *buf, *nextbuf; + static bool entered = false; - // When we cause a crash here it is caught and Vim tries to exit cleanly. - // Don't try freeing everything again. - if (entered_free_all_mem) { + /* When we cause a crash here it is caught and Vim tries to exit cleanly. + * Don't try freeing everything again. */ + if (entered) return; - } - entered_free_all_mem = true; + entered = true; // Don't want to trigger autocommands from here on. block_autocmds(); diff --git a/src/nvim/memory.h b/src/nvim/memory.h index 62cc78360c..0b422957d5 100644 --- a/src/nvim/memory.h +++ b/src/nvim/memory.h @@ -5,6 +5,16 @@ #include // for size_t #include // for time_t +typedef void *(*MemMalloc)(size_t); +typedef void (*MemFree)(void *); +typedef void *(*MemCalloc)(size_t, size_t); +typedef void *(*MemRealloc)(void *, size_t); + +extern MemMalloc mem_malloc; +extern MemFree mem_free; +extern MemCalloc mem_calloc; +extern MemRealloc mem_realloc; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "memory.h.generated.h" #endif -- cgit From 7d0a892b374a8e5e025905a28e54b98b4f62f533 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Jan 2017 14:59:42 +0300 Subject: eval/typval_encode.h: Use only a single macros with _INNER[_2] hack --- src/nvim/eval/typval_encode.h | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index 6517efa961..ba325b8f55 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -108,37 +108,38 @@ static inline size_t tv_strlen(const typval_T *const tv) } \ } while (0) -#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER_2(name) \ - _typval_encode_##name##_check_self_reference -#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER(name) \ - _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER_2(name) +#define _TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf) \ + pref##name##suf +#define _TYPVAL_ENCODE_FUNC_NAME_INNER(pref, name, suf) \ + _TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf) + +/// Construct function name, possibly using macros +/// +/// Is used to expand macros that may appear in arguments. +/// +/// @note Expands all arguments, even if only one is needed. +/// +/// @param[in] pref Prefix. +/// @param[in] suf Suffix. +/// +/// @return Concat: pref + #TYPVAL_ENCODE_NAME + suf. +#define _TYPVAL_ENCODE_FUNC_NAME(pref, suf) \ + _TYPVAL_ENCODE_FUNC_NAME_INNER(pref, TYPVAL_ENCODE_NAME, suf) /// Self reference checker function name #define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE \ - _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER(TYPVAL_ENCODE_NAME) - -#define _TYPVAL_ENCODE_ENCODE_INNER_2(name) encode_vim_to_##name -#define _TYPVAL_ENCODE_ENCODE_INNER(name) _TYPVAL_ENCODE_ENCODE_INNER_2(name) + _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _check_self_reference) /// Entry point function name -#define _TYPVAL_ENCODE_ENCODE _TYPVAL_ENCODE_ENCODE_INNER(TYPVAL_ENCODE_NAME) - -#define _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER_2(name) \ - _typval_encode_##name##_convert_one_value -#define _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER(name) \ - _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER_2(name) +#define _TYPVAL_ENCODE_ENCODE \ + _TYPVAL_ENCODE_FUNC_NAME(encode_vim_to_, ) /// Name of the …convert_one_value function #define _TYPVAL_ENCODE_CONVERT_ONE_VALUE \ - _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER(TYPVAL_ENCODE_NAME) - -#define _TYPVAL_ENCODE_NODICT_VAR_INNER_2(name) \ - _typval_encode_##name##_nodict_var -#define _TYPVAL_ENCODE_NODICT_VAR_INNER(name) \ - _TYPVAL_ENCODE_NODICT_VAR_INNER_2(name) + _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _convert_one_value) /// Name of the dummy const dict_T *const variable #define TYPVAL_ENCODE_NODICT_VAR \ - _TYPVAL_ENCODE_NODICT_VAR_INNER(TYPVAL_ENCODE_NAME) + _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _nodict_var) #endif // NVIM_EVAL_TYPVAL_ENCODE_H -- cgit From a970c1a95785cce9176274ffd4b783c79372afed Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Jan 2017 15:15:14 +0300 Subject: eval: Make sure that copyID is reset when needed Works by making value pushed on stack represent the exhausted list. Fixes #5901, except for dictionaries which need similar adjustment. --- src/nvim/api/private/helpers.c | 3 +++ src/nvim/eval.c | 15 +++++++++------ src/nvim/eval/encode.c | 6 ++++++ src/nvim/eval/typval_encode.c.h | 11 +++++++++++ 4 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 701a1cbf2b..4eff21bc26 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -387,6 +387,8 @@ static inline void typval_encode_list_start(EncodedData *const edata, #define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ typval_encode_list_start(edata, (size_t)(len)) +#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) + static inline void typval_encode_between_list_items(EncodedData *const edata) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL { @@ -499,6 +501,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata) #undef TYPVAL_ENCODE_CONV_FUNC_END #undef TYPVAL_ENCODE_CONV_EMPTY_LIST #undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_EMPTY_DICT #undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_BOOL diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 4501c2e0a6..f355b3eac4 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -19147,23 +19147,25 @@ static inline void _nothing_conv_func_end(typval_T *const tv, const int copyID) } \ } while (0) -static inline int _nothing_conv_list_start(typval_T *const tv) +static inline int _nothing_conv_real_list_after_start( + typval_T *const tv, MPConvStackVal *const mpsv) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT { - if (tv == NULL) { - return NOTDONE; - } + assert(tv != NULL); tv->v_lock = VAR_UNLOCKED; if (tv->vval.v_list->lv_refcount > 1) { tv->vval.v_list->lv_refcount--; tv->vval.v_list = NULL; + mpsv->data.l.li = NULL; return OK; } return NOTDONE; } -#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ +#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) + +#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) \ do { \ - if (_nothing_conv_list_start(tv) != NOTDONE) { \ + if (_nothing_conv_real_list_after_start(tv, &mpsv) != NOTDONE) { \ goto typval_encode_stop_converting_one_item; \ } \ } while (0) @@ -19253,6 +19255,7 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, #undef TYPVAL_ENCODE_CONV_EMPTY_LIST #undef TYPVAL_ENCODE_CONV_EMPTY_DICT #undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS #undef TYPVAL_ENCODE_CONV_LIST_END #undef TYPVAL_ENCODE_CONV_DICT_START diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 071fbc3923..48741abea2 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -369,6 +369,8 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, #define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ ga_append(gap, '[') +#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) + #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ ga_concat(gap, "{}") @@ -789,6 +791,7 @@ bool encode_check_json_key(const typval_T *const tv) #undef TYPVAL_ENCODE_CONV_FUNC_END #undef TYPVAL_ENCODE_CONV_EMPTY_LIST #undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_EMPTY_DICT #undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_BOOL @@ -933,6 +936,8 @@ char *encode_tv2json(typval_T *tv, size_t *len) #define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ msgpack_pack_array(packer, (size_t)(len)) +#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) + #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ msgpack_pack_map(packer, 0) @@ -994,6 +999,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) #undef TYPVAL_ENCODE_CONV_FUNC_END #undef TYPVAL_ENCODE_CONV_EMPTY_LIST #undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START #undef TYPVAL_ENCODE_CONV_EMPTY_DICT #undef TYPVAL_ENCODE_CONV_NIL #undef TYPVAL_ENCODE_CONV_BOOL diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index 3e1170b8fa..bade067ea6 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -129,6 +129,16 @@ /// point to a special dictionary. /// @param len List length. Is an expression which evaluates to an integer. +/// @def TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START +/// @brief Macros used after pushing list onto the stack +/// +/// Only used for real list_T* lists, not for special dictionaries or partial +/// arguments. +/// +/// @param tv Pointer to typval where value is stored. May be NULL. May +/// point to a special dictionary. +/// @param mpsv Pushed MPConvStackVal value. + /// @def TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS /// @brief Macros used after finishing converting non-last list item /// @@ -354,6 +364,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( }, }, })); + TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, _mp_last(*mpstack)); break; } case VAR_SPECIAL: { -- cgit From 728367a196c8396c8b186f1dbe2cf878a7fec038 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Jan 2017 15:26:34 +0300 Subject: unittest: Add dict_items function --- src/nvim/eval.c | 2 +- src/nvim/globals.h | 4 ---- src/nvim/hashtab.c | 12 ++++++++++++ src/nvim/hashtab.h | 9 +++++++-- 4 files changed, 20 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index f355b3eac4..a96cc82260 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6445,7 +6445,7 @@ void dict_free(dict_T *d) { */ dictitem_T *dictitem_alloc(char_u *key) FUNC_ATTR_NONNULL_RET { - dictitem_T *di = xmalloc(sizeof(dictitem_T) + STRLEN(key)); + dictitem_T *di = xmalloc(offsetof(dictitem_T, di_key) + STRLEN(key) + 1); #ifndef __clang_analyzer__ STRCPY(di->di_key, key); #endif diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 872ff8d5b8..2b9abb1cc5 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -409,10 +409,6 @@ EXTERN struct caller_scope { } provider_caller_scope; EXTERN int provider_call_nesting INIT(= 0); -/* Magic number used for hashitem "hi_key" value indicating a deleted item. - * Only the address is used. */ -EXTERN char_u hash_removed; - EXTERN int t_colors INIT(= 256); // int value of T_CCO diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c index fa4077f22f..376f33e23e 100644 --- a/src/nvim/hashtab.c +++ b/src/nvim/hashtab.c @@ -36,6 +36,8 @@ # include "hashtab.c.generated.h" #endif +char hash_removed; + /// Initialize an empty hash table. void hash_init(hashtab_T *ht) { @@ -380,3 +382,13 @@ hash_T hash_hash(char_u *key) return hash; } + +/// Function to get HI_KEY_REMOVED value +/// +/// Used for testing because luajit ffi does not allow getting addresses of +/// globals. +const char_u *_hash_key_removed(void) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return HI_KEY_REMOVED; +} diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h index 7233d8c47c..0da2b13f2e 100644 --- a/src/nvim/hashtab.h +++ b/src/nvim/hashtab.h @@ -5,14 +5,19 @@ #include "nvim/types.h" +/// Magic number used for hashitem "hi_key" value indicating a deleted item +/// +/// Only the address is used. +extern char hash_removed; + /// Type for hash number (hash calculation result). typedef size_t hash_T; /// The address of "hash_removed" is used as a magic number /// for hi_key to indicate a removed item. -#define HI_KEY_REMOVED &hash_removed +#define HI_KEY_REMOVED ((char_u *)&hash_removed) #define HASHITEM_EMPTY(hi) ((hi)->hi_key == NULL \ - || (hi)->hi_key == &hash_removed) + || (hi)->hi_key == (char_u *)&hash_removed) /// A hastable item. /// -- cgit From 9a09ffa883ea34d07405af9617201958e5a4c861 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Jan 2017 15:54:46 +0300 Subject: eval: Fix failing test --- src/nvim/api/private/helpers.c | 3 +++ src/nvim/eval.c | 18 +++++++++++------- src/nvim/eval/encode.c | 6 ++++++ src/nvim/eval/typval_encode.c.h | 15 +++++++++++++++ 4 files changed, 35 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 4eff21bc26..7daa4d7207 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -429,6 +429,8 @@ static inline void typval_encode_dict_start(EncodedData *const edata, #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ typval_encode_dict_start(edata, (size_t)(len)) +#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) + #define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, kv_pair) static inline void typval_encode_after_key(EncodedData *const edata) @@ -507,6 +509,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata) #undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER #undef TYPVAL_ENCODE_CONV_DICT_START +#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START #undef TYPVAL_ENCODE_CONV_DICT_END #undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY #undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS diff --git a/src/nvim/eval.c b/src/nvim/eval.c index a96cc82260..b7a30a4c12 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -19185,9 +19185,9 @@ static inline void _nothing_conv_list_end(typval_T *const tv) } #define TYPVAL_ENCODE_CONV_LIST_END(tv) _nothing_conv_list_end(tv) -static inline int _nothing_conv_dict_start(typval_T *const tv, - dict_T **const dictp, - const void *const nodictvar) +static inline int _nothing_conv_real_dict_after_start( + typval_T *const tv, dict_T **const dictp, const void *const nodictvar, + MPConvStackVal *const mpsv) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT { if (tv != NULL) { @@ -19196,15 +19196,18 @@ static inline int _nothing_conv_dict_start(typval_T *const tv, if ((const void *)dictp != nodictvar && (*dictp)->dv_refcount > 1) { (*dictp)->dv_refcount--; *dictp = NULL; + mpsv->data.d.todo = 0; return OK; } return NOTDONE; } -#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) + +#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) \ do { \ - if (_nothing_conv_dict_start(tv, (dict_T **)&dict, \ - (void *)&TYPVAL_ENCODE_NODICT_VAR) \ - != NOTDONE) { \ + if (_nothing_conv_real_dict_after_start( \ + tv, (dict_T **)&dict, (void *)&TYPVAL_ENCODE_NODICT_VAR, \ + &mpsv) != NOTDONE) { \ goto typval_encode_stop_converting_one_item; \ } \ } while (0) @@ -19259,6 +19262,7 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, #undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS #undef TYPVAL_ENCODE_CONV_LIST_END #undef TYPVAL_ENCODE_CONV_DICT_START +#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START #undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK #undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY #undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 48741abea2..ee66b7cf09 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -385,6 +385,8 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ ga_append(gap, '{') +#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) + #define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ ga_append(gap, '}') @@ -797,6 +799,7 @@ bool encode_check_json_key(const typval_T *const tv) #undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER #undef TYPVAL_ENCODE_CONV_DICT_START +#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START #undef TYPVAL_ENCODE_CONV_DICT_END #undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY #undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS @@ -959,6 +962,8 @@ char *encode_tv2json(typval_T *tv, size_t *len) #define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ msgpack_pack_map(packer, (size_t)(len)) +#define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) + #define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) #define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) @@ -1005,6 +1010,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) #undef TYPVAL_ENCODE_CONV_BOOL #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER #undef TYPVAL_ENCODE_CONV_DICT_START +#undef TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START #undef TYPVAL_ENCODE_CONV_DICT_END #undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY #undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index bade067ea6..365eb2dd77 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -152,6 +152,9 @@ /// @def TYPVAL_ENCODE_CONV_DICT_START /// @brief Macros used before starting to convert non-empty dictionary /// +/// Only used for real dict_T* dictionaries, not for special dictionaries. Also +/// used for partial self dictionary. +/// /// @param tv Pointer to typval where dictionary is stored. May be NULL. May /// point to a special dictionary. /// @param dict Converted dictionary, lvalue or #TYPVAL_ENCODE_NODICT_VAR @@ -159,6 +162,14 @@ /// @param len Dictionary length. Is an expression which evaluates to an /// integer. +/// @def TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START +/// @brief Macros used after pushing dictionary onto the stack +/// +/// @param tv Pointer to typval where dictionary is stored. May be NULL. +/// May not point to a special dictionary. +/// @param dict Converted dictionary, lvalue. +/// @param mpsv Pushed MPConvStackVal value. + /// @def TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK /// @brief Macros used to check special dictionary key /// @@ -575,6 +586,8 @@ _convert_one_value_regular_dict: }, }, })); + TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, tv->vval.v_dict, + _mp_last(*mpstack)); break; } case VAR_UNKNOWN: { @@ -743,6 +756,8 @@ typval_encode_stop_converting_one_item: }, }, })); + TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(NULL, pt->pt_dict, + _mp_last(mpstack)); } else { TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1); } -- cgit From 35416e89bcef1de97881a14dc2d2408144bd8a7f Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Jan 2017 17:52:53 +0300 Subject: memory: Restore entered_free_all_mem functionality --- src/nvim/eval.c | 7 +++++-- src/nvim/globals.h | 4 ---- src/nvim/memory.c | 15 ++++++++++----- src/nvim/memory.h | 4 ++++ 4 files changed, 19 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index b7a30a4c12..a046b2a288 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -21665,9 +21665,12 @@ void func_unref(char_u *name) fp = find_func(name); if (fp == NULL) { #ifdef EXITFREE - if (!entered_free_all_mem) // NOLINT(readability/braces) -#endif + if (!entered_free_all_mem) { EMSG2(_(e_intern2), "func_unref()"); + } +#else + EMSG2(_(e_intern2), "func_unref()"); +#endif } else { user_func_unref(fp); } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 2b9abb1cc5..5ee04ad982 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -632,10 +632,6 @@ EXTERN int exiting INIT(= FALSE); /* TRUE when planning to exit Vim. Might * still keep on running if there is a changed * buffer. */ -#if defined(EXITFREE) -// true when in or after free_all_mem() -EXTERN bool entered_free_all_mem INIT(= false); -#endif // volatile because it is used in signal handler deathtrap(). EXTERN volatile int full_screen INIT(= false); // TRUE when doing full-screen output diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 3c0d001848..a5045dfffc 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -48,6 +48,11 @@ MemRealloc mem_realloc = &realloc; # include "memory.c.generated.h" #endif +#ifdef EXITFREE +/// Indicates that free_all_mem function was or is running +bool entered_free_all_mem = false; +#endif + /// Try to free memory. Used when trying to recover from out of memory errors. /// @see {xmalloc} void try_to_free_memory(void) @@ -511,13 +516,13 @@ void time_to_bytes(time_t time_, uint8_t buf[8]) void free_all_mem(void) { buf_T *buf, *nextbuf; - static bool entered = false; - /* When we cause a crash here it is caught and Vim tries to exit cleanly. - * Don't try freeing everything again. */ - if (entered) + // When we cause a crash here it is caught and Vim tries to exit cleanly. + // Don't try freeing everything again. + if (entered_free_all_mem) { return; - entered = true; + } + entered_free_all_mem = true; // Don't want to trigger autocommands from here on. block_autocmds(); diff --git a/src/nvim/memory.h b/src/nvim/memory.h index 0b422957d5..d82972cffc 100644 --- a/src/nvim/memory.h +++ b/src/nvim/memory.h @@ -15,6 +15,10 @@ extern MemFree mem_free; extern MemCalloc mem_calloc; extern MemRealloc mem_realloc; +#ifdef EXITFREE +extern bool entered_free_all_mem; +#endif + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "memory.h.generated.h" #endif -- cgit From 6f267b3968d54f8bcd41d584a71bef9020ff773e Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Jan 2017 17:58:29 +0300 Subject: memory: Document new additions to memory.h --- src/nvim/memory.c | 1 - src/nvim/memory.h | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/memory.c b/src/nvim/memory.c index a5045dfffc..92ead873ae 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -49,7 +49,6 @@ MemRealloc mem_realloc = &realloc; #endif #ifdef EXITFREE -/// Indicates that free_all_mem function was or is running bool entered_free_all_mem = false; #endif diff --git a/src/nvim/memory.h b/src/nvim/memory.h index d82972cffc..f65947d449 100644 --- a/src/nvim/memory.h +++ b/src/nvim/memory.h @@ -5,17 +5,34 @@ #include // for size_t #include // for time_t +/// `malloc()` function signature typedef void *(*MemMalloc)(size_t); + +/// `free()` function signature typedef void (*MemFree)(void *); + +/// `calloc()` function signature typedef void *(*MemCalloc)(size_t, size_t); + +/// `realloc()` function signature typedef void *(*MemRealloc)(void *, size_t); +#ifdef UNIT_TESTING +/// When unit testing: pointer to the `malloc()` function, may be altered extern MemMalloc mem_malloc; + +/// When unit testing: pointer to the `free()` function, may be altered extern MemFree mem_free; + +/// When unit testing: pointer to the `calloc()` function, may be altered extern MemCalloc mem_calloc; + +/// When unit testing: pointer to the `realloc()` function, may be altered extern MemRealloc mem_realloc; +#endif #ifdef EXITFREE +/// Indicates that free_all_mem function was or is running extern bool entered_free_all_mem; #endif -- cgit From dea4bb33dc13a65e303b77ccda28601ebc246b85 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Jan 2017 19:07:32 +0300 Subject: unittest,memory: Fix tests --- src/nvim/memory.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/memory.h b/src/nvim/memory.h index f65947d449..250ac3e08f 100644 --- a/src/nvim/memory.h +++ b/src/nvim/memory.h @@ -1,9 +1,10 @@ #ifndef NVIM_MEMORY_H #define NVIM_MEMORY_H +#include // for bool #include // for uint8_t #include // for size_t -#include // for time_t +#include // for time_t /// `malloc()` function signature typedef void *(*MemMalloc)(size_t); -- cgit