# HG changeset patch # User vimboss # Date 1160944658 0 # Node ID 721ebb602db0fd2a5a9cded8e0830800d734469a # Parent 58059676e24a6fbbc686faf84c612cfa8c25485d updated for version 7.0-135 diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -191,8 +191,6 @@ struct ufunc #define FC_RANGE 2 /* function accepts range */ #define FC_DICT 4 /* Dict function, uses "self" */ -#define DEL_REFCOUNT 999999 /* list/dict is being deleted */ - /* * All user-defined functions are found in this hashtable. */ @@ -435,7 +433,7 @@ static void set_ref_in_ht __ARGS((hashta static void set_ref_in_list __ARGS((list_T *l, int copyID)); static void set_ref_in_item __ARGS((typval_T *tv, int copyID)); static void dict_unref __ARGS((dict_T *d)); -static void dict_free __ARGS((dict_T *d)); +static void dict_free __ARGS((dict_T *d, int recurse)); static dictitem_T *dictitem_alloc __ARGS((char_u *key)); static dictitem_T *dictitem_copy __ARGS((dictitem_T *org)); static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item)); @@ -4899,7 +4897,7 @@ eval_index(arg, rettv, evaluate, verbose { if (list_append_tv(l, &item->li_tv) == FAIL) { - list_free(l); + list_free(l, TRUE); return FAIL; } item = item->li_next; @@ -5299,7 +5297,7 @@ get_list_tv(arg, rettv, evaluate) EMSG2(_("E697: Missing end of List ']': %s"), *arg); failret: if (evaluate) - list_free(l); + list_free(l, TRUE); return FAIL; } @@ -5363,8 +5361,8 @@ rettv_list_alloc(rettv) list_unref(l) list_T *l; { - if (l != NULL && l->lv_refcount != DEL_REFCOUNT && --l->lv_refcount <= 0) - list_free(l); + if (l != NULL && --l->lv_refcount <= 0) + list_free(l, TRUE); } /* @@ -5372,14 +5370,12 @@ list_unref(l) * Ignores the reference count. */ void -list_free(l) - list_T *l; +list_free(l, recurse) + list_T *l; + int recurse; /* Free Lists and Dictionaries recursively. */ { listitem_T *item; - /* Avoid that recursive reference to the list frees us again. */ - l->lv_refcount = DEL_REFCOUNT; - /* Remove the list from the list of lists for garbage collection. */ if (l->lv_used_prev == NULL) first_list = l->lv_used_next; @@ -5392,7 +5388,10 @@ list_free(l) { /* Remove the item before deleting it. */ l->lv_first = item->li_next; - listitem_free(item); + if (recurse || (item->li_tv.v_type != VAR_LIST + && item->li_tv.v_type != VAR_DICT)) + clear_tv(&item->li_tv); + vim_free(item); } vim_free(l); } @@ -6113,7 +6112,10 @@ garbage_collect() for (dd = first_dict; dd != NULL; ) if (dd->dv_copyID != copyID) { - dict_free(dd); + /* Free the Dictionary and ordinary items it contains, but don't + * recurse into Lists and Dictionaries, they will be in the list + * of dicts or list of lists. */ + dict_free(dd, FALSE); did_free = TRUE; /* restart, next dict may also have been freed */ @@ -6130,7 +6132,10 @@ garbage_collect() for (ll = first_list; ll != NULL; ) if (ll->lv_copyID != copyID && ll->lv_watch == NULL) { - list_free(ll); + /* Free the List and ordinary items it contains, but don't recurse + * into Lists and Dictionaries, they will be in the list of dicts + * or list of lists. */ + list_free(ll, FALSE); did_free = TRUE; /* restart, next list may also have been freed */ @@ -6223,11 +6228,12 @@ dict_alloc() d = (dict_T *)alloc(sizeof(dict_T)); if (d != NULL) { - /* Add the list to the hashtable for garbage collection. */ + /* Add the list to the list of dicts for garbage collection. */ if (first_dict != NULL) first_dict->dv_used_prev = d; d->dv_used_next = first_dict; d->dv_used_prev = NULL; + first_dict = d; hash_init(&d->dv_hashtab); d->dv_lock = 0; @@ -6245,8 +6251,8 @@ dict_alloc() dict_unref(d) dict_T *d; { - if (d != NULL && d->dv_refcount != DEL_REFCOUNT && --d->dv_refcount <= 0) - dict_free(d); + if (d != NULL && --d->dv_refcount <= 0) + dict_free(d, TRUE); } /* @@ -6254,16 +6260,14 @@ dict_unref(d) * Ignores the reference count. */ static void -dict_free(d) - dict_T *d; +dict_free(d, recurse) + dict_T *d; + int recurse; /* Free Lists and Dictionaries recursively. */ { int todo; hashitem_T *hi; dictitem_T *di; - /* Avoid that recursive reference to the dict frees us again. */ - d->dv_refcount = DEL_REFCOUNT; - /* Remove the dict from the list of dicts for garbage collection. */ if (d->dv_used_prev == NULL) first_dict = d->dv_used_next; @@ -6283,7 +6287,10 @@ dict_free(d) * something recursive causing trouble. */ di = HI2DI(hi); hash_remove(&d->dv_hashtab, hi); - dictitem_free(di); + if (recurse || (di->di_tv.v_type != VAR_LIST + && di->di_tv.v_type != VAR_DICT)) + clear_tv(&di->di_tv); + vim_free(di); --todo; } } @@ -6734,7 +6741,7 @@ get_dict_tv(arg, rettv, evaluate) EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg); failret: if (evaluate) - dict_free(d); + dict_free(d, TRUE); return FAIL; } diff --git a/src/proto/eval.pro b/src/proto/eval.pro --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -44,7 +44,7 @@ extern void del_menutrans_vars __ARGS((v extern char_u *get_user_var_name __ARGS((expand_T *xp, int idx)); extern list_T *list_alloc __ARGS((void)); extern void list_unref __ARGS((list_T *l)); -extern void list_free __ARGS((list_T *l)); +extern void list_free __ARGS((list_T *l, int recurse)); extern dictitem_T *dict_lookup __ARGS((hashitem_T *hi)); extern int list_append_dict __ARGS((list_T *list, dict_T *dict)); extern int garbage_collect __ARGS((void)); diff --git a/src/tag.c b/src/tag.c --- a/src/tag.c +++ b/src/tag.c @@ -911,7 +911,7 @@ do_tag(tag, type, count, forceit, verbos set_errorlist(curwin, list, ' '); - list_free(list); + list_free(list, TRUE); cur_match = 0; /* Jump to the first tag */ } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -667,6 +667,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 135, +/**/ 134, /**/ 133,