comparison src/eval.c @ 1891:7a4ad3fb109d v7.2.188

updated for version 7.2-188
author vimboss
date Sun, 24 May 2009 11:40:58 +0000
parents e5602d92da8c
children afb740b5dfab
comparison
equal deleted inserted replaced
1890:2928a6b338c3 1891:7a4ad3fb109d
127 static hashtab_T compat_hashtab; 127 static hashtab_T compat_hashtab;
128 128
129 /* 129 /*
130 * When recursively copying lists and dicts we need to remember which ones we 130 * When recursively copying lists and dicts we need to remember which ones we
131 * have done to avoid endless recursiveness. This unique ID is used for that. 131 * have done to avoid endless recursiveness. This unique ID is used for that.
132 * The last bit is used for previous_funccal, ignored when comparing.
132 */ 133 */
133 static int current_copyID = 0; 134 static int current_copyID = 0;
135 #define COPYID_INC 2
136 #define COPYID_MASK (~0x1)
134 137
135 /* 138 /*
136 * Array to hold the hashtab with variables local to each sourced script. 139 * Array to hold the hashtab with variables local to each sourced script.
137 * Each item holds a variable (nameless) that points to the dict_T. 140 * Each item holds a variable (nameless) that points to the dict_T.
138 */ 141 */
437 static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv)); 440 static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
438 static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID)); 441 static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
439 static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2)); 442 static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
440 static char_u *list2string __ARGS((typval_T *tv, int copyID)); 443 static char_u *list2string __ARGS((typval_T *tv, int copyID));
441 static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID)); 444 static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));
445 static int free_unref_items __ARGS((int copyID));
442 static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID)); 446 static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
443 static void set_ref_in_list __ARGS((list_T *l, int copyID)); 447 static void set_ref_in_list __ARGS((list_T *l, int copyID));
444 static void set_ref_in_item __ARGS((typval_T *tv, int copyID)); 448 static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
445 static void dict_unref __ARGS((dict_T *d)); 449 static void dict_unref __ARGS((dict_T *d));
446 static void dict_free __ARGS((dict_T *d, int recurse)); 450 static void dict_free __ARGS((dict_T *d, int recurse));
6492 * Return TRUE if some memory was freed. 6496 * Return TRUE if some memory was freed.
6493 */ 6497 */
6494 int 6498 int
6495 garbage_collect() 6499 garbage_collect()
6496 { 6500 {
6497 dict_T *dd; 6501 int copyID;
6498 list_T *ll;
6499 int copyID = ++current_copyID;
6500 buf_T *buf; 6502 buf_T *buf;
6501 win_T *wp; 6503 win_T *wp;
6502 int i; 6504 int i;
6503 funccall_T *fc, **pfc; 6505 funccall_T *fc, **pfc;
6504 int did_free = FALSE; 6506 int did_free;
6507 int did_free_funccal = FALSE;
6505 #ifdef FEAT_WINDOWS 6508 #ifdef FEAT_WINDOWS
6506 tabpage_T *tp; 6509 tabpage_T *tp;
6507 #endif 6510 #endif
6508 6511
6509 /* Only do this once. */ 6512 /* Only do this once. */
6510 want_garbage_collect = FALSE; 6513 want_garbage_collect = FALSE;
6511 may_garbage_collect = FALSE; 6514 may_garbage_collect = FALSE;
6512 garbage_collect_at_exit = FALSE; 6515 garbage_collect_at_exit = FALSE;
6513 6516
6517 /* We advance by two because we add one for items referenced through
6518 * previous_funccal. */
6519 current_copyID += COPYID_INC;
6520 copyID = current_copyID;
6521
6514 /* 6522 /*
6515 * 1. Go through all accessible variables and mark all lists and dicts 6523 * 1. Go through all accessible variables and mark all lists and dicts
6516 * with copyID. 6524 * with copyID.
6517 */ 6525 */
6526
6527 /* Don't free variables in the previous_funccal list unless they are only
6528 * referenced through previous_funccal. This must be first, because if
6529 * the item is referenced elsewhere it must not be freed. */
6530 for (fc = previous_funccal; fc != NULL; fc = fc->caller)
6531 {
6532 set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1);
6533 set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1);
6534 }
6535
6518 /* script-local variables */ 6536 /* script-local variables */
6519 for (i = 1; i <= ga_scripts.ga_len; ++i) 6537 for (i = 1; i <= ga_scripts.ga_len; ++i)
6520 set_ref_in_ht(&SCRIPT_VARS(i), copyID); 6538 set_ref_in_ht(&SCRIPT_VARS(i), copyID);
6521 6539
6522 /* buffer-local variables */ 6540 /* buffer-local variables */
6544 } 6562 }
6545 6563
6546 /* v: vars */ 6564 /* v: vars */
6547 set_ref_in_ht(&vimvarht, copyID); 6565 set_ref_in_ht(&vimvarht, copyID);
6548 6566
6567 /* Free lists and dictionaries that are not referenced. */
6568 did_free = free_unref_items(copyID);
6569
6570 /* check if any funccal can be freed now */
6571 for (pfc = &previous_funccal; *pfc != NULL; )
6572 {
6573 if (can_free_funccal(*pfc, copyID))
6574 {
6575 fc = *pfc;
6576 *pfc = fc->caller;
6577 free_funccal(fc, TRUE);
6578 did_free = TRUE;
6579 did_free_funccal = TRUE;
6580 }
6581 else
6582 pfc = &(*pfc)->caller;
6583 }
6584 if (did_free_funccal)
6585 /* When a funccal was freed some more items might be garbage
6586 * collected, so run again. */
6587 (void)garbage_collect();
6588
6589 return did_free;
6590 }
6591
6592 /*
6593 * Free lists and dictionaries that are no longer referenced.
6594 */
6595 static int
6596 free_unref_items(copyID)
6597 int copyID;
6598 {
6599 dict_T *dd;
6600 list_T *ll;
6601 int did_free = FALSE;
6602
6549 /* 6603 /*
6550 * 2. Go through the list of dicts and free items without the copyID. 6604 * Go through the list of dicts and free items without the copyID.
6551 */ 6605 */
6552 for (dd = first_dict; dd != NULL; ) 6606 for (dd = first_dict; dd != NULL; )
6553 if (dd->dv_copyID != copyID) 6607 if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK))
6554 { 6608 {
6555 /* Free the Dictionary and ordinary items it contains, but don't 6609 /* Free the Dictionary and ordinary items it contains, but don't
6556 * recurse into Lists and Dictionaries, they will be in the list 6610 * recurse into Lists and Dictionaries, they will be in the list
6557 * of dicts or list of lists. */ 6611 * of dicts or list of lists. */
6558 dict_free(dd, FALSE); 6612 dict_free(dd, FALSE);
6563 } 6617 }
6564 else 6618 else
6565 dd = dd->dv_used_next; 6619 dd = dd->dv_used_next;
6566 6620
6567 /* 6621 /*
6568 * 3. Go through the list of lists and free items without the copyID. 6622 * Go through the list of lists and free items without the copyID.
6569 * But don't free a list that has a watcher (used in a for loop), these 6623 * But don't free a list that has a watcher (used in a for loop), these
6570 * are not referenced anywhere. 6624 * are not referenced anywhere.
6571 */ 6625 */
6572 for (ll = first_list; ll != NULL; ) 6626 for (ll = first_list; ll != NULL; )
6573 if (ll->lv_copyID != copyID && ll->lv_watch == NULL) 6627 if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
6628 && ll->lv_watch == NULL)
6574 { 6629 {
6575 /* Free the List and ordinary items it contains, but don't recurse 6630 /* Free the List and ordinary items it contains, but don't recurse
6576 * into Lists and Dictionaries, they will be in the list of dicts 6631 * into Lists and Dictionaries, they will be in the list of dicts
6577 * or list of lists. */ 6632 * or list of lists. */
6578 list_free(ll, FALSE); 6633 list_free(ll, FALSE);
6581 /* restart, next list may also have been freed */ 6636 /* restart, next list may also have been freed */
6582 ll = first_list; 6637 ll = first_list;
6583 } 6638 }
6584 else 6639 else
6585 ll = ll->lv_used_next; 6640 ll = ll->lv_used_next;
6586
6587 /* check if any funccal can be freed now */
6588 for (pfc = &previous_funccal; *pfc != NULL; )
6589 {
6590 if (can_free_funccal(*pfc, copyID))
6591 {
6592 fc = *pfc;
6593 *pfc = fc->caller;
6594 free_funccal(fc, TRUE);
6595 did_free = TRUE;
6596 }
6597 else
6598 pfc = &(*pfc)->caller;
6599 }
6600 6641
6601 return did_free; 6642 return did_free;
6602 } 6643 }
6603 6644
6604 /* 6645 /*
18840 dict_T *dict; 18881 dict_T *dict;
18841 dictitem_T *dict_var; 18882 dictitem_T *dict_var;
18842 { 18883 {
18843 hash_init(&dict->dv_hashtab); 18884 hash_init(&dict->dv_hashtab);
18844 dict->dv_refcount = DO_NOT_FREE_CNT; 18885 dict->dv_refcount = DO_NOT_FREE_CNT;
18886 dict->dv_copyID = 0;
18845 dict_var->di_tv.vval.v_dict = dict; 18887 dict_var->di_tv.vval.v_dict = dict;
18846 dict_var->di_tv.v_type = VAR_DICT; 18888 dict_var->di_tv.v_type = VAR_DICT;
18847 dict_var->di_tv.v_lock = VAR_FIXED; 18889 dict_var->di_tv.v_lock = VAR_FIXED;
18848 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; 18890 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
18849 dict_var->di_key[0] = NUL; 18891 dict_var->di_key[0] = NUL;
21292 21334
21293 did_emsg |= save_did_emsg; 21335 did_emsg |= save_did_emsg;
21294 current_funccal = fc->caller; 21336 current_funccal = fc->caller;
21295 --depth; 21337 --depth;
21296 21338
21297 /* if the a:000 list and the a: dict are not referenced we can free the 21339 /* If the a:000 list and the l: and a: dicts are not referenced we can
21298 * funccall_T and what's in it. */ 21340 * free the funccall_T and what's in it. */
21299 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT 21341 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
21300 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT 21342 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
21301 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT) 21343 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
21302 { 21344 {
21303 free_funccal(fc, FALSE); 21345 free_funccal(fc, FALSE);
21332 } 21374 }
21333 } 21375 }
21334 21376
21335 /* 21377 /*
21336 * Return TRUE if items in "fc" do not have "copyID". That means they are not 21378 * Return TRUE if items in "fc" do not have "copyID". That means they are not
21337 * referenced from anywhere. 21379 * referenced from anywhere that is in use.
21338 */ 21380 */
21339 static int 21381 static int
21340 can_free_funccal(fc, copyID) 21382 can_free_funccal(fc, copyID)
21341 funccall_T *fc; 21383 funccall_T *fc;
21342 int copyID; 21384 int copyID;