Karsten Hopp 512818
To: vim_dev@googlegroups.com
Karsten Hopp 512818
Subject: Patch 7.4.609
Karsten Hopp 512818
Fcc: outbox
Karsten Hopp 512818
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp 512818
Mime-Version: 1.0
Karsten Hopp 512818
Content-Type: text/plain; charset=UTF-8
Karsten Hopp 512818
Content-Transfer-Encoding: 8bit
Karsten Hopp 512818
------------
Karsten Hopp 512818
Karsten Hopp 512818
Patch 7.4.609
Karsten Hopp 512818
Problem:    For complicated list and dict use the garbage collector can run
Karsten Hopp 512818
	    out of stack space.
Karsten Hopp 512818
Solution:   Use a stack of dicts and lists to be marked, thus making it
Karsten Hopp 512818
	    iterative instead of recursive. (Ben Fritz)
Karsten Hopp 512818
Files:	    src/eval.c, src/if_lua.c, src/if_py_both.h, src/if_python.c,
Karsten Hopp 512818
	    src/if_python3.c, src/proto/eval.pro, src/proto/if_lua.pro,
Karsten Hopp 512818
	    src/proto/if_python.pro, src/proto/if_python3.pro, src/structs.h
Karsten Hopp 512818
Karsten Hopp 512818
Karsten Hopp 512818
*** ../vim-7.4.608/src/eval.c	2015-01-27 15:18:55.152333309 +0100
Karsten Hopp 512818
--- src/eval.c	2015-02-03 12:41:59.468525906 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 93,99 ****
Karsten Hopp 512818
      char_u	*ll_newkey;	/* New key for Dict in alloc. mem or NULL. */
Karsten Hopp 512818
  } lval_T;
Karsten Hopp 512818
  
Karsten Hopp 512818
- 
Karsten Hopp 512818
  static char *e_letunexp	= N_("E18: Unexpected characters in :let");
Karsten Hopp 512818
  static char *e_listidx = N_("E684: list index out of range: %ld");
Karsten Hopp 512818
  static char *e_undefvar = N_("E121: Undefined variable: %s");
Karsten Hopp 512818
--- 93,98 ----
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 6811,6816 ****
Karsten Hopp 512818
--- 6810,6816 ----
Karsten Hopp 512818
  garbage_collect()
Karsten Hopp 512818
  {
Karsten Hopp 512818
      int		copyID;
Karsten Hopp 512818
+     int		abort = FALSE;
Karsten Hopp 512818
      buf_T	*buf;
Karsten Hopp 512818
      win_T	*wp;
Karsten Hopp 512818
      int		i;
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 6841,6922 ****
Karsten Hopp 512818
       * the item is referenced elsewhere the funccal must not be freed. */
Karsten Hopp 512818
      for (fc = previous_funccal; fc != NULL; fc = fc->caller)
Karsten Hopp 512818
      {
Karsten Hopp 512818
! 	set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1);
Karsten Hopp 512818
! 	set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1);
Karsten Hopp 512818
      }
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* script-local variables */
Karsten Hopp 512818
      for (i = 1; i <= ga_scripts.ga_len; ++i)
Karsten Hopp 512818
! 	set_ref_in_ht(&SCRIPT_VARS(i), copyID);
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* buffer-local variables */
Karsten Hopp 512818
      for (buf = firstbuf; buf != NULL; buf = buf->b_next)
Karsten Hopp 512818
! 	set_ref_in_item(&buf->b_bufvar.di_tv, copyID);
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* window-local variables */
Karsten Hopp 512818
      FOR_ALL_TAB_WINDOWS(tp, wp)
Karsten Hopp 512818
! 	set_ref_in_item(&wp->w_winvar.di_tv, copyID);
Karsten Hopp 512818
  #ifdef FEAT_AUTOCMD
Karsten Hopp 512818
      if (aucmd_win != NULL)
Karsten Hopp 512818
! 	set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
  #ifdef FEAT_WINDOWS
Karsten Hopp 512818
      /* tabpage-local variables */
Karsten Hopp 512818
      for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
Karsten Hopp 512818
! 	set_ref_in_item(&tp->tp_winvar.di_tv, copyID);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* global variables */
Karsten Hopp 512818
!     set_ref_in_ht(&globvarht, copyID);
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* function-local variables */
Karsten Hopp 512818
      for (fc = current_funccal; fc != NULL; fc = fc->caller)
Karsten Hopp 512818
      {
Karsten Hopp 512818
! 	set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID);
Karsten Hopp 512818
! 	set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID);
Karsten Hopp 512818
      }
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* v: vars */
Karsten Hopp 512818
!     set_ref_in_ht(&vimvarht, copyID);
Karsten Hopp 512818
  
Karsten Hopp 512818
  #ifdef FEAT_LUA
Karsten Hopp 512818
!     set_ref_in_lua(copyID);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
  #ifdef FEAT_PYTHON
Karsten Hopp 512818
!     set_ref_in_python(copyID);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
  #ifdef FEAT_PYTHON3
Karsten Hopp 512818
!     set_ref_in_python3(copyID);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
!     /*
Karsten Hopp 512818
!      * 2. Free lists and dictionaries that are not referenced.
Karsten Hopp 512818
!      */
Karsten Hopp 512818
!     did_free = free_unref_items(copyID);
Karsten Hopp 512818
! 
Karsten Hopp 512818
!     /*
Karsten Hopp 512818
!      * 3. Check if any funccal can be freed now.
Karsten Hopp 512818
!      */
Karsten Hopp 512818
!     for (pfc = &previous_funccal; *pfc != NULL; )
Karsten Hopp 512818
      {
Karsten Hopp 512818
! 	if (can_free_funccal(*pfc, copyID))
Karsten Hopp 512818
  	{
Karsten Hopp 512818
! 	    fc = *pfc;
Karsten Hopp 512818
! 	    *pfc = fc->caller;
Karsten Hopp 512818
! 	    free_funccal(fc, TRUE);
Karsten Hopp 512818
! 	    did_free = TRUE;
Karsten Hopp 512818
! 	    did_free_funccal = TRUE;
Karsten Hopp 512818
  	}
Karsten Hopp 512818
! 	else
Karsten Hopp 512818
! 	    pfc = &(*pfc)->caller;
Karsten Hopp 512818
      }
Karsten Hopp 512818
-     if (did_free_funccal)
Karsten Hopp 512818
- 	/* When a funccal was freed some more items might be garbage
Karsten Hopp 512818
- 	 * collected, so run again. */
Karsten Hopp 512818
- 	(void)garbage_collect();
Karsten Hopp 512818
  
Karsten Hopp 512818
      return did_free;
Karsten Hopp 512818
  }
Karsten Hopp 512818
--- 6841,6935 ----
Karsten Hopp 512818
       * the item is referenced elsewhere the funccal must not be freed. */
Karsten Hopp 512818
      for (fc = previous_funccal; fc != NULL; fc = fc->caller)
Karsten Hopp 512818
      {
Karsten Hopp 512818
! 	abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1,
Karsten Hopp 512818
! 									NULL);
Karsten Hopp 512818
! 	abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1,
Karsten Hopp 512818
! 									NULL);
Karsten Hopp 512818
      }
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* script-local variables */
Karsten Hopp 512818
      for (i = 1; i <= ga_scripts.ga_len; ++i)
Karsten Hopp 512818
! 	abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* buffer-local variables */
Karsten Hopp 512818
      for (buf = firstbuf; buf != NULL; buf = buf->b_next)
Karsten Hopp 512818
! 	abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID,
Karsten Hopp 512818
! 								  NULL, NULL);
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* window-local variables */
Karsten Hopp 512818
      FOR_ALL_TAB_WINDOWS(tp, wp)
Karsten Hopp 512818
! 	abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
Karsten Hopp 512818
! 								  NULL, NULL);
Karsten Hopp 512818
  #ifdef FEAT_AUTOCMD
Karsten Hopp 512818
      if (aucmd_win != NULL)
Karsten Hopp 512818
! 	abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID,
Karsten Hopp 512818
! 								  NULL, NULL);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
  #ifdef FEAT_WINDOWS
Karsten Hopp 512818
      /* tabpage-local variables */
Karsten Hopp 512818
      for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
Karsten Hopp 512818
! 	abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID,
Karsten Hopp 512818
! 								  NULL, NULL);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* global variables */
Karsten Hopp 512818
!     abort = abort || set_ref_in_ht(&globvarht, copyID, NULL);
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* function-local variables */
Karsten Hopp 512818
      for (fc = current_funccal; fc != NULL; fc = fc->caller)
Karsten Hopp 512818
      {
Karsten Hopp 512818
! 	abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL);
Karsten Hopp 512818
! 	abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL);
Karsten Hopp 512818
      }
Karsten Hopp 512818
  
Karsten Hopp 512818
      /* v: vars */
Karsten Hopp 512818
!     abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL);
Karsten Hopp 512818
  
Karsten Hopp 512818
  #ifdef FEAT_LUA
Karsten Hopp 512818
!     abort = abort || set_ref_in_lua(copyID);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
  #ifdef FEAT_PYTHON
Karsten Hopp 512818
!     abort = abort || set_ref_in_python(copyID);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
  #ifdef FEAT_PYTHON3
Karsten Hopp 512818
!     abort = abort || set_ref_in_python3(copyID);
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
  
Karsten Hopp 512818
!     if (!abort)
Karsten Hopp 512818
      {
Karsten Hopp 512818
! 	/*
Karsten Hopp 512818
! 	 * 2. Free lists and dictionaries that are not referenced.
Karsten Hopp 512818
! 	 */
Karsten Hopp 512818
! 	did_free = free_unref_items(copyID);
Karsten Hopp 512818
! 
Karsten Hopp 512818
! 	/*
Karsten Hopp 512818
! 	 * 3. Check if any funccal can be freed now.
Karsten Hopp 512818
! 	 */
Karsten Hopp 512818
! 	for (pfc = &previous_funccal; *pfc != NULL; )
Karsten Hopp 512818
  	{
Karsten Hopp 512818
! 	    if (can_free_funccal(*pfc, copyID))
Karsten Hopp 512818
! 	    {
Karsten Hopp 512818
! 		fc = *pfc;
Karsten Hopp 512818
! 		*pfc = fc->caller;
Karsten Hopp 512818
! 		free_funccal(fc, TRUE);
Karsten Hopp 512818
! 		did_free = TRUE;
Karsten Hopp 512818
! 		did_free_funccal = TRUE;
Karsten Hopp 512818
! 	    }
Karsten Hopp 512818
! 	    else
Karsten Hopp 512818
! 		pfc = &(*pfc)->caller;
Karsten Hopp 512818
  	}
Karsten Hopp 512818
! 	if (did_free_funccal)
Karsten Hopp 512818
! 	    /* When a funccal was freed some more items might be garbage
Karsten Hopp 512818
! 	     * collected, so run again. */
Karsten Hopp 512818
! 	    (void)garbage_collect();
Karsten Hopp 512818
!     }
Karsten Hopp 512818
!     else if (p_verbose > 0)
Karsten Hopp 512818
!     {
Karsten Hopp 512818
! 	verb_msg((char_u *)_("Not enough memory to set references, garbage collection aborted!"));
Karsten Hopp 512818
      }
Karsten Hopp 512818
  
Karsten Hopp 512818
      return did_free;
Karsten Hopp 512818
  }
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 6976,7023 ****
Karsten Hopp 512818
  
Karsten Hopp 512818
  /*
Karsten Hopp 512818
   * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
Karsten Hopp 512818
   */
Karsten Hopp 512818
!     void
Karsten Hopp 512818
! set_ref_in_ht(ht, copyID)
Karsten Hopp 512818
!     hashtab_T	*ht;
Karsten Hopp 512818
!     int		copyID;
Karsten Hopp 512818
  {
Karsten Hopp 512818
      int		todo;
Karsten Hopp 512818
      hashitem_T	*hi;
Karsten Hopp 512818
  
Karsten Hopp 512818
!     todo = (int)ht->ht_used;
Karsten Hopp 512818
!     for (hi = ht->ht_array; todo > 0; ++hi)
Karsten Hopp 512818
! 	if (!HASHITEM_EMPTY(hi))
Karsten Hopp 512818
  	{
Karsten Hopp 512818
! 	    --todo;
Karsten Hopp 512818
! 	    set_ref_in_item(&HI2DI(hi)->di_tv, copyID);
Karsten Hopp 512818
  	}
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
  /*
Karsten Hopp 512818
   * Mark all lists and dicts referenced through list "l" with "copyID".
Karsten Hopp 512818
   */
Karsten Hopp 512818
!     void
Karsten Hopp 512818
! set_ref_in_list(l, copyID)
Karsten Hopp 512818
      list_T	*l;
Karsten Hopp 512818
      int		copyID;
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     listitem_T *li;
Karsten Hopp 512818
  
Karsten Hopp 512818
!     for (li = l->lv_first; li != NULL; li = li->li_next)
Karsten Hopp 512818
! 	set_ref_in_item(&li->li_tv, copyID);
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
  /*
Karsten Hopp 512818
   * Mark all lists and dicts referenced through typval "tv" with "copyID".
Karsten Hopp 512818
   */
Karsten Hopp 512818
!     void
Karsten Hopp 512818
! set_ref_in_item(tv, copyID)
Karsten Hopp 512818
!     typval_T	*tv;
Karsten Hopp 512818
!     int		copyID;
Karsten Hopp 512818
  {
Karsten Hopp 512818
      dict_T	*dd;
Karsten Hopp 512818
      list_T	*ll;
Karsten Hopp 512818
  
Karsten Hopp 512818
      switch (tv->v_type)
Karsten Hopp 512818
      {
Karsten Hopp 512818
--- 6989,7100 ----
Karsten Hopp 512818
  
Karsten Hopp 512818
  /*
Karsten Hopp 512818
   * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
Karsten Hopp 512818
+  * "list_stack" is used to add lists to be marked.  Can be NULL.
Karsten Hopp 512818
+  *
Karsten Hopp 512818
+  * Returns TRUE if setting references failed somehow.
Karsten Hopp 512818
   */
Karsten Hopp 512818
!     int
Karsten Hopp 512818
! set_ref_in_ht(ht, copyID, list_stack)
Karsten Hopp 512818
!     hashtab_T	    *ht;
Karsten Hopp 512818
!     int		    copyID;
Karsten Hopp 512818
!     list_stack_T    **list_stack;
Karsten Hopp 512818
  {
Karsten Hopp 512818
      int		todo;
Karsten Hopp 512818
+     int		abort = FALSE;
Karsten Hopp 512818
      hashitem_T	*hi;
Karsten Hopp 512818
+     hashtab_T	*cur_ht;
Karsten Hopp 512818
+     ht_stack_T	*ht_stack = NULL;
Karsten Hopp 512818
+     ht_stack_T	*tempitem;
Karsten Hopp 512818
  
Karsten Hopp 512818
!     cur_ht = ht;
Karsten Hopp 512818
!     for (;;)
Karsten Hopp 512818
!     {
Karsten Hopp 512818
! 	if (!abort)
Karsten Hopp 512818
  	{
Karsten Hopp 512818
! 	    /* Mark each item in the hashtab.  If the item contains a hashtab
Karsten Hopp 512818
! 	     * it is added to ht_stack, if it contains a list it is added to
Karsten Hopp 512818
! 	     * list_stack. */
Karsten Hopp 512818
! 	    todo = (int)cur_ht->ht_used;
Karsten Hopp 512818
! 	    for (hi = cur_ht->ht_array; todo > 0; ++hi)
Karsten Hopp 512818
! 		if (!HASHITEM_EMPTY(hi))
Karsten Hopp 512818
! 		{
Karsten Hopp 512818
! 		    --todo;
Karsten Hopp 512818
! 		    abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID,
Karsten Hopp 512818
! 						       &ht_stack, list_stack);
Karsten Hopp 512818
! 		}
Karsten Hopp 512818
  	}
Karsten Hopp 512818
+ 
Karsten Hopp 512818
+ 	if (ht_stack == NULL)
Karsten Hopp 512818
+ 	    break;
Karsten Hopp 512818
+ 
Karsten Hopp 512818
+ 	/* take an item from the stack */
Karsten Hopp 512818
+ 	cur_ht = ht_stack->ht;
Karsten Hopp 512818
+ 	tempitem = ht_stack;
Karsten Hopp 512818
+ 	ht_stack = ht_stack->prev;
Karsten Hopp 512818
+ 	free(tempitem);
Karsten Hopp 512818
+     }
Karsten Hopp 512818
+ 
Karsten Hopp 512818
+     return abort;
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
  /*
Karsten Hopp 512818
   * Mark all lists and dicts referenced through list "l" with "copyID".
Karsten Hopp 512818
+  * "ht_stack" is used to add hashtabs to be marked.  Can be NULL.
Karsten Hopp 512818
+  *
Karsten Hopp 512818
+  * Returns TRUE if setting references failed somehow.
Karsten Hopp 512818
   */
Karsten Hopp 512818
!     int
Karsten Hopp 512818
! set_ref_in_list(l, copyID, ht_stack)
Karsten Hopp 512818
      list_T	*l;
Karsten Hopp 512818
      int		copyID;
Karsten Hopp 512818
+     ht_stack_T	**ht_stack;
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     listitem_T	 *li;
Karsten Hopp 512818
!     int		 abort = FALSE;
Karsten Hopp 512818
!     list_T	 *cur_l;
Karsten Hopp 512818
!     list_stack_T *list_stack = NULL;
Karsten Hopp 512818
!     list_stack_T *tempitem;
Karsten Hopp 512818
! 
Karsten Hopp 512818
!     cur_l = l;
Karsten Hopp 512818
!     for (;;)
Karsten Hopp 512818
!     {
Karsten Hopp 512818
! 	if (!abort)
Karsten Hopp 512818
! 	    /* Mark each item in the list.  If the item contains a hashtab
Karsten Hopp 512818
! 	     * it is added to ht_stack, if it contains a list it is added to
Karsten Hopp 512818
! 	     * list_stack. */
Karsten Hopp 512818
! 	    for (li = cur_l->lv_first; !abort && li != NULL; li = li->li_next)
Karsten Hopp 512818
! 		abort = abort || set_ref_in_item(&li->li_tv, copyID,
Karsten Hopp 512818
! 						       ht_stack, &list_stack);
Karsten Hopp 512818
! 	if (list_stack == NULL)
Karsten Hopp 512818
! 	    break;
Karsten Hopp 512818
! 
Karsten Hopp 512818
! 	/* take an item from the stack */
Karsten Hopp 512818
! 	cur_l = list_stack->list;
Karsten Hopp 512818
! 	tempitem = list_stack;
Karsten Hopp 512818
! 	list_stack = list_stack->prev;
Karsten Hopp 512818
! 	free(tempitem);
Karsten Hopp 512818
!     }
Karsten Hopp 512818
  
Karsten Hopp 512818
!     return abort;
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
  /*
Karsten Hopp 512818
   * Mark all lists and dicts referenced through typval "tv" with "copyID".
Karsten Hopp 512818
+  * "list_stack" is used to add lists to be marked.  Can be NULL.
Karsten Hopp 512818
+  * "ht_stack" is used to add hashtabs to be marked.  Can be NULL.
Karsten Hopp 512818
+  *
Karsten Hopp 512818
+  * Returns TRUE if setting references failed somehow.
Karsten Hopp 512818
   */
Karsten Hopp 512818
!     int
Karsten Hopp 512818
! set_ref_in_item(tv, copyID, ht_stack, list_stack)
Karsten Hopp 512818
!     typval_T	    *tv;
Karsten Hopp 512818
!     int		    copyID;
Karsten Hopp 512818
!     ht_stack_T	    **ht_stack;
Karsten Hopp 512818
!     list_stack_T    **list_stack;
Karsten Hopp 512818
  {
Karsten Hopp 512818
      dict_T	*dd;
Karsten Hopp 512818
      list_T	*ll;
Karsten Hopp 512818
+     int		abort = FALSE;
Karsten Hopp 512818
  
Karsten Hopp 512818
      switch (tv->v_type)
Karsten Hopp 512818
      {
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 7027,7033 ****
Karsten Hopp 512818
  	    {
Karsten Hopp 512818
  		/* Didn't see this dict yet. */
Karsten Hopp 512818
  		dd->dv_copyID = copyID;
Karsten Hopp 512818
! 		set_ref_in_ht(&dd->dv_hashtab, copyID);
Karsten Hopp 512818
  	    }
Karsten Hopp 512818
  	    break;
Karsten Hopp 512818
  
Karsten Hopp 512818
--- 7104,7126 ----
Karsten Hopp 512818
  	    {
Karsten Hopp 512818
  		/* Didn't see this dict yet. */
Karsten Hopp 512818
  		dd->dv_copyID = copyID;
Karsten Hopp 512818
! 		if (ht_stack == NULL)
Karsten Hopp 512818
! 		{
Karsten Hopp 512818
! 		    abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
Karsten Hopp 512818
! 		}
Karsten Hopp 512818
! 		else
Karsten Hopp 512818
! 		{
Karsten Hopp 512818
! 		    ht_stack_T *newitem = (ht_stack_T*)malloc(
Karsten Hopp 512818
! 							  sizeof(ht_stack_T));
Karsten Hopp 512818
! 		    if (newitem == NULL)
Karsten Hopp 512818
! 			abort = TRUE;
Karsten Hopp 512818
! 		    else
Karsten Hopp 512818
! 		    {
Karsten Hopp 512818
! 			newitem->ht = &dd->dv_hashtab;
Karsten Hopp 512818
! 			newitem->prev = *ht_stack;
Karsten Hopp 512818
! 			*ht_stack = newitem;
Karsten Hopp 512818
! 		    }
Karsten Hopp 512818
! 		}
Karsten Hopp 512818
  	    }
Karsten Hopp 512818
  	    break;
Karsten Hopp 512818
  
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 7037,7047 ****
Karsten Hopp 512818
  	    {
Karsten Hopp 512818
  		/* Didn't see this list yet. */
Karsten Hopp 512818
  		ll->lv_copyID = copyID;
Karsten Hopp 512818
! 		set_ref_in_list(ll, copyID);
Karsten Hopp 512818
  	    }
Karsten Hopp 512818
  	    break;
Karsten Hopp 512818
      }
Karsten Hopp 512818
!     return;
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
  /*
Karsten Hopp 512818
--- 7130,7156 ----
Karsten Hopp 512818
  	    {
Karsten Hopp 512818
  		/* Didn't see this list yet. */
Karsten Hopp 512818
  		ll->lv_copyID = copyID;
Karsten Hopp 512818
! 		if (list_stack == NULL)
Karsten Hopp 512818
! 		{
Karsten Hopp 512818
! 		    abort = set_ref_in_list(ll, copyID, ht_stack);
Karsten Hopp 512818
! 		}
Karsten Hopp 512818
! 		else
Karsten Hopp 512818
! 		{
Karsten Hopp 512818
! 		    list_stack_T *newitem = (list_stack_T*)malloc(
Karsten Hopp 512818
! 							sizeof(list_stack_T));
Karsten Hopp 512818
! 		    if (newitem == NULL)
Karsten Hopp 512818
! 			abort = TRUE;
Karsten Hopp 512818
! 		    else
Karsten Hopp 512818
! 		    {
Karsten Hopp 512818
! 			newitem->list = ll;
Karsten Hopp 512818
! 			newitem->prev = *list_stack;
Karsten Hopp 512818
! 			*list_stack = newitem;
Karsten Hopp 512818
! 		    }
Karsten Hopp 512818
! 		}
Karsten Hopp 512818
  	    }
Karsten Hopp 512818
  	    break;
Karsten Hopp 512818
      }
Karsten Hopp 512818
!     return abort;
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
  /*
Karsten Hopp 512818
*** ../vim-7.4.608/src/if_lua.c	2014-05-07 17:31:32.473182497 +0200
Karsten Hopp 512818
--- src/if_lua.c	2015-02-03 12:45:41.978204997 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 1523,1534 ****
Karsten Hopp 512818
      static int
Karsten Hopp 512818
  luaV_setref (lua_State *L)
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     int copyID = lua_tointeger(L, 1);
Karsten Hopp 512818
!     typval_T tv;
Karsten Hopp 512818
      luaV_getfield(L, LUAVIM_LIST);
Karsten Hopp 512818
      luaV_getfield(L, LUAVIM_DICT);
Karsten Hopp 512818
      lua_pushnil(L);
Karsten Hopp 512818
!     while (lua_next(L, lua_upvalueindex(1)) != 0) /* traverse cache table */
Karsten Hopp 512818
      {
Karsten Hopp 512818
  	lua_getmetatable(L, -1);
Karsten Hopp 512818
  	if (lua_rawequal(L, -1, 2)) /* list? */
Karsten Hopp 512818
--- 1523,1536 ----
Karsten Hopp 512818
      static int
Karsten Hopp 512818
  luaV_setref (lua_State *L)
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     int		copyID = lua_tointeger(L, 1);
Karsten Hopp 512818
!     int		abort = FALSE;
Karsten Hopp 512818
!     typval_T	tv;
Karsten Hopp 512818
! 
Karsten Hopp 512818
      luaV_getfield(L, LUAVIM_LIST);
Karsten Hopp 512818
      luaV_getfield(L, LUAVIM_DICT);
Karsten Hopp 512818
      lua_pushnil(L);
Karsten Hopp 512818
!     while (!abort && lua_next(L, lua_upvalueindex(1)) != 0) /* traverse cache table */
Karsten Hopp 512818
      {
Karsten Hopp 512818
  	lua_getmetatable(L, -1);
Karsten Hopp 512818
  	if (lua_rawequal(L, -1, 2)) /* list? */
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 1542,1550 ****
Karsten Hopp 512818
  	    tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */
Karsten Hopp 512818
  	}
Karsten Hopp 512818
  	lua_pop(L, 2); /* metatable and value */
Karsten Hopp 512818
! 	set_ref_in_item(&tv, copyID);
Karsten Hopp 512818
      }
Karsten Hopp 512818
!     return 0;
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
      static int
Karsten Hopp 512818
--- 1544,1552 ----
Karsten Hopp 512818
  	    tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */
Karsten Hopp 512818
  	}
Karsten Hopp 512818
  	lua_pop(L, 2); /* metatable and value */
Karsten Hopp 512818
! 	abort = set_ref_in_item(&tv, copyID, NULL, NULL);
Karsten Hopp 512818
      }
Karsten Hopp 512818
!     lua_pushinteger(L, abort);
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
      static int
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 1770,1782 ****
Karsten Hopp 512818
      lua_call(L, 3, 0);
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
!     void
Karsten Hopp 512818
  set_ref_in_lua (int copyID)
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     if (!lua_isopen()) return;
Karsten Hopp 512818
!     luaV_getfield(L, LUAVIM_SETREF);
Karsten Hopp 512818
!     lua_pushinteger(L, copyID);
Karsten Hopp 512818
!     lua_call(L, 1, 0);
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
--- 1772,1794 ----
Karsten Hopp 512818
      lua_call(L, 3, 0);
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
!     int
Karsten Hopp 512818
  set_ref_in_lua (int copyID)
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     int aborted = 0;
Karsten Hopp 512818
! 
Karsten Hopp 512818
!     if (lua_isopen())
Karsten Hopp 512818
!     {
Karsten Hopp 512818
! 	luaV_getfield(L, LUAVIM_SETREF);
Karsten Hopp 512818
! 	/* call the function with 1 arg, getting 1 result back */
Karsten Hopp 512818
! 	lua_pushinteger(L, copyID);
Karsten Hopp 512818
! 	lua_call(L, 1, 1);
Karsten Hopp 512818
! 	/* get the result */
Karsten Hopp 512818
! 	aborted = lua_tointeger(L, -1);
Karsten Hopp 512818
! 	/* pop result off the stack */
Karsten Hopp 512818
! 	lua_pop(L, 1);
Karsten Hopp 512818
!     }
Karsten Hopp 512818
!     return aborted;
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
  #endif
Karsten Hopp 512818
*** ../vim-7.4.608/src/if_py_both.h	2014-12-17 14:45:56.095854545 +0100
Karsten Hopp 512818
--- src/if_py_both.h	2015-02-03 12:46:46.629530177 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 5502,5535 ****
Karsten Hopp 512818
      PyErr_Clear();
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
!     static void
Karsten Hopp 512818
  set_ref_in_py(const int copyID)
Karsten Hopp 512818
  {
Karsten Hopp 512818
      pylinkedlist_T	*cur;
Karsten Hopp 512818
      dict_T	*dd;
Karsten Hopp 512818
      list_T	*ll;
Karsten Hopp 512818
  
Karsten Hopp 512818
      if (lastdict != NULL)
Karsten Hopp 512818
! 	for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
Karsten Hopp 512818
  	{
Karsten Hopp 512818
  	    dd = ((DictionaryObject *) (cur->pll_obj))->dict;
Karsten Hopp 512818
  	    if (dd->dv_copyID != copyID)
Karsten Hopp 512818
  	    {
Karsten Hopp 512818
  		dd->dv_copyID = copyID;
Karsten Hopp 512818
! 		set_ref_in_ht(&dd->dv_hashtab, copyID);
Karsten Hopp 512818
  	    }
Karsten Hopp 512818
  	}
Karsten Hopp 512818
  
Karsten Hopp 512818
      if (lastlist != NULL)
Karsten Hopp 512818
! 	for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
Karsten Hopp 512818
  	{
Karsten Hopp 512818
  	    ll = ((ListObject *) (cur->pll_obj))->list;
Karsten Hopp 512818
  	    if (ll->lv_copyID != copyID)
Karsten Hopp 512818
  	    {
Karsten Hopp 512818
  		ll->lv_copyID = copyID;
Karsten Hopp 512818
! 		set_ref_in_list(ll, copyID);
Karsten Hopp 512818
  	    }
Karsten Hopp 512818
  	}
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
      static int
Karsten Hopp 512818
--- 5502,5542 ----
Karsten Hopp 512818
      PyErr_Clear();
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
!     static int
Karsten Hopp 512818
  set_ref_in_py(const int copyID)
Karsten Hopp 512818
  {
Karsten Hopp 512818
      pylinkedlist_T	*cur;
Karsten Hopp 512818
      dict_T	*dd;
Karsten Hopp 512818
      list_T	*ll;
Karsten Hopp 512818
+     int		abort = FALSE;
Karsten Hopp 512818
  
Karsten Hopp 512818
      if (lastdict != NULL)
Karsten Hopp 512818
!     {
Karsten Hopp 512818
! 	for(cur = lastdict ; !abort && cur != NULL ; cur = cur->pll_prev)
Karsten Hopp 512818
  	{
Karsten Hopp 512818
  	    dd = ((DictionaryObject *) (cur->pll_obj))->dict;
Karsten Hopp 512818
  	    if (dd->dv_copyID != copyID)
Karsten Hopp 512818
  	    {
Karsten Hopp 512818
  		dd->dv_copyID = copyID;
Karsten Hopp 512818
! 		abort = abort || set_ref_in_ht(&dd->dv_hashtab, copyID, NULL);
Karsten Hopp 512818
  	    }
Karsten Hopp 512818
  	}
Karsten Hopp 512818
+     }
Karsten Hopp 512818
  
Karsten Hopp 512818
      if (lastlist != NULL)
Karsten Hopp 512818
!     {
Karsten Hopp 512818
! 	for(cur = lastlist ; !abort && cur != NULL ; cur = cur->pll_prev)
Karsten Hopp 512818
  	{
Karsten Hopp 512818
  	    ll = ((ListObject *) (cur->pll_obj))->list;
Karsten Hopp 512818
  	    if (ll->lv_copyID != copyID)
Karsten Hopp 512818
  	    {
Karsten Hopp 512818
  		ll->lv_copyID = copyID;
Karsten Hopp 512818
! 		abort = abort || set_ref_in_list(ll, copyID, NULL);
Karsten Hopp 512818
  	    }
Karsten Hopp 512818
  	}
Karsten Hopp 512818
+     }
Karsten Hopp 512818
+ 
Karsten Hopp 512818
+     return abort;
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
      static int
Karsten Hopp 512818
*** ../vim-7.4.608/src/if_python.c	2014-07-23 16:56:56.587876204 +0200
Karsten Hopp 512818
--- src/if_python.c	2015-02-03 12:05:13.471422753 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 1567,1574 ****
Karsten Hopp 512818
  }
Karsten Hopp 512818
  #endif /* Python 1.4 */
Karsten Hopp 512818
  
Karsten Hopp 512818
!     void
Karsten Hopp 512818
  set_ref_in_python (int copyID)
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     set_ref_in_py(copyID);
Karsten Hopp 512818
  }
Karsten Hopp 512818
--- 1567,1574 ----
Karsten Hopp 512818
  }
Karsten Hopp 512818
  #endif /* Python 1.4 */
Karsten Hopp 512818
  
Karsten Hopp 512818
!     int
Karsten Hopp 512818
  set_ref_in_python (int copyID)
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     return set_ref_in_py(copyID);
Karsten Hopp 512818
  }
Karsten Hopp 512818
*** ../vim-7.4.608/src/if_python3.c	2014-03-30 16:11:37.180530823 +0200
Karsten Hopp 512818
--- src/if_python3.c	2015-02-03 12:05:13.471422753 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 1649,1656 ****
Karsten Hopp 512818
      }
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
!     void
Karsten Hopp 512818
  set_ref_in_python3 (int copyID)
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     set_ref_in_py(copyID);
Karsten Hopp 512818
  }
Karsten Hopp 512818
--- 1649,1656 ----
Karsten Hopp 512818
      }
Karsten Hopp 512818
  }
Karsten Hopp 512818
  
Karsten Hopp 512818
!     int
Karsten Hopp 512818
  set_ref_in_python3 (int copyID)
Karsten Hopp 512818
  {
Karsten Hopp 512818
!     int set_ref_in_py(copyID);
Karsten Hopp 512818
  }
Karsten Hopp 512818
*** ../vim-7.4.608/src/proto/eval.pro	2014-12-17 14:36:10.363090985 +0100
Karsten Hopp 512818
--- src/proto/eval.pro	2015-02-03 12:47:58.472780049 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 62,70 ****
Karsten Hopp 512818
  void list_insert __ARGS((list_T *l, listitem_T *ni, listitem_T *item));
Karsten Hopp 512818
  void vimlist_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
Karsten Hopp 512818
  int garbage_collect __ARGS((void));
Karsten Hopp 512818
! void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
Karsten Hopp 512818
! void set_ref_in_list __ARGS((list_T *l, int copyID));
Karsten Hopp 512818
! void set_ref_in_item __ARGS((typval_T *tv, int copyID));
Karsten Hopp 512818
  dict_T *dict_alloc __ARGS((void));
Karsten Hopp 512818
  void dict_unref __ARGS((dict_T *d));
Karsten Hopp 512818
  void dict_free __ARGS((dict_T *d, int recurse));
Karsten Hopp 512818
--- 62,70 ----
Karsten Hopp 512818
  void list_insert __ARGS((list_T *l, listitem_T *ni, listitem_T *item));
Karsten Hopp 512818
  void vimlist_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
Karsten Hopp 512818
  int garbage_collect __ARGS((void));
Karsten Hopp 512818
! int set_ref_in_ht __ARGS((hashtab_T *ht, int copyID, list_stack_T **list_stack));
Karsten Hopp 512818
! int set_ref_in_list __ARGS((list_T *l, int copyID, ht_stack_T **ht_stack));
Karsten Hopp 512818
! int set_ref_in_item __ARGS((typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack_T **list_stack));
Karsten Hopp 512818
  dict_T *dict_alloc __ARGS((void));
Karsten Hopp 512818
  void dict_unref __ARGS((dict_T *d));
Karsten Hopp 512818
  void dict_free __ARGS((dict_T *d, int recurse));
Karsten Hopp 512818
*** ../vim-7.4.608/src/proto/if_lua.pro	2012-04-05 16:41:35.000000000 +0200
Karsten Hopp 512818
--- src/proto/if_lua.pro	2015-02-03 12:05:13.475422711 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 7,11 ****
Karsten Hopp 512818
  void lua_buffer_free __ARGS((buf_T *buf));
Karsten Hopp 512818
  void lua_window_free __ARGS((win_T *win));
Karsten Hopp 512818
  void do_luaeval __ARGS((char_u *str, typval_T *arg, typval_T *rettv));
Karsten Hopp 512818
! void set_ref_in_lua __ARGS((int copyID));
Karsten Hopp 512818
  /* vim: set ft=c : */
Karsten Hopp 512818
--- 7,11 ----
Karsten Hopp 512818
  void lua_buffer_free __ARGS((buf_T *buf));
Karsten Hopp 512818
  void lua_window_free __ARGS((win_T *win));
Karsten Hopp 512818
  void do_luaeval __ARGS((char_u *str, typval_T *arg, typval_T *rettv));
Karsten Hopp 512818
! int set_ref_in_lua __ARGS((int copyID));
Karsten Hopp 512818
  /* vim: set ft=c : */
Karsten Hopp 512818
*** ../vim-7.4.608/src/proto/if_python.pro	2013-08-10 13:37:15.000000000 +0200
Karsten Hopp 512818
--- src/proto/if_python.pro	2015-02-03 12:48:02.936733431 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 9,13 ****
Karsten Hopp 512818
  void python_window_free __ARGS((win_T *win));
Karsten Hopp 512818
  void python_tabpage_free __ARGS((tabpage_T *tab));
Karsten Hopp 512818
  void do_pyeval __ARGS((char_u *str, typval_T *rettv));
Karsten Hopp 512818
! void set_ref_in_python __ARGS((int copyID));
Karsten Hopp 512818
  /* vim: set ft=c : */
Karsten Hopp 512818
--- 9,13 ----
Karsten Hopp 512818
  void python_window_free __ARGS((win_T *win));
Karsten Hopp 512818
  void python_tabpage_free __ARGS((tabpage_T *tab));
Karsten Hopp 512818
  void do_pyeval __ARGS((char_u *str, typval_T *rettv));
Karsten Hopp 512818
! int set_ref_in_python __ARGS((int copyID));
Karsten Hopp 512818
  /* vim: set ft=c : */
Karsten Hopp 512818
*** ../vim-7.4.608/src/proto/if_python3.pro	2013-08-10 13:37:16.000000000 +0200
Karsten Hopp 512818
--- src/proto/if_python3.pro	2015-02-03 12:48:03.292729714 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 9,13 ****
Karsten Hopp 512818
  void python3_window_free __ARGS((win_T *win));
Karsten Hopp 512818
  void python3_tabpage_free __ARGS((tabpage_T *tab));
Karsten Hopp 512818
  void do_py3eval __ARGS((char_u *str, typval_T *rettv));
Karsten Hopp 512818
! void set_ref_in_python3 __ARGS((int copyID));
Karsten Hopp 512818
  /* vim: set ft=c : */
Karsten Hopp 512818
--- 9,13 ----
Karsten Hopp 512818
  void python3_window_free __ARGS((win_T *win));
Karsten Hopp 512818
  void python3_tabpage_free __ARGS((tabpage_T *tab));
Karsten Hopp 512818
  void do_py3eval __ARGS((char_u *str, typval_T *rettv));
Karsten Hopp 512818
! int set_ref_in_python3 __ARGS((int copyID));
Karsten Hopp 512818
  /* vim: set ft=c : */
Karsten Hopp 512818
*** ../vim-7.4.608/src/structs.h	2015-01-14 12:44:38.407422077 +0100
Karsten Hopp 512818
--- src/structs.h	2015-02-03 12:05:13.475422711 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 1223,1228 ****
Karsten Hopp 512818
--- 1223,1242 ----
Karsten Hopp 512818
      dict_T	*dv_used_prev;	/* previous dict in used dicts list */
Karsten Hopp 512818
  };
Karsten Hopp 512818
  
Karsten Hopp 512818
+ /* structure used for explicit stack while garbage collecting hash tables */
Karsten Hopp 512818
+ typedef struct ht_stack_S
Karsten Hopp 512818
+ {
Karsten Hopp 512818
+     hashtab_T		*ht;
Karsten Hopp 512818
+     struct ht_stack_S	*prev;
Karsten Hopp 512818
+ } ht_stack_T;
Karsten Hopp 512818
+ 
Karsten Hopp 512818
+ /* structure used for explicit stack while garbage collecting lists */
Karsten Hopp 512818
+ typedef struct list_stack_S
Karsten Hopp 512818
+ {
Karsten Hopp 512818
+     list_T		*list;
Karsten Hopp 512818
+     struct list_stack_S	*prev;
Karsten Hopp 512818
+ } list_stack_T;
Karsten Hopp 512818
+ 
Karsten Hopp 512818
  /* values for b_syn_spell: what to do with toplevel text */
Karsten Hopp 512818
  #define SYNSPL_DEFAULT	0	/* spell check if @Spell not defined */
Karsten Hopp 512818
  #define SYNSPL_TOP	1	/* spell check toplevel text */
Karsten Hopp 512818
*** ../vim-7.4.608/src/version.c	2015-01-27 22:52:10.713524965 +0100
Karsten Hopp 512818
--- src/version.c	2015-02-03 12:09:19.324876918 +0100
Karsten Hopp 512818
***************
Karsten Hopp 512818
*** 743,744 ****
Karsten Hopp 512818
--- 743,746 ----
Karsten Hopp 512818
  {   /* Add new patch number below this line */
Karsten Hopp 512818
+ /**/
Karsten Hopp 512818
+     609,
Karsten Hopp 512818
  /**/
Karsten Hopp 512818
Karsten Hopp 512818
-- 
Karsten Hopp 512818
hundred-and-one symptoms of being an internet addict:
Karsten Hopp 512818
167. You have more than 200 websites bookmarked.
Karsten Hopp 512818
Karsten Hopp 512818
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp 512818
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp 512818
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
Karsten Hopp 512818
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///