Blob Blame History Raw
To: vim-dev@vim.org
Subject: Patch 7.0.084
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
------------

Patch 7.0.084
Problem:    The garbage collector may do its work while some Lists or
	    Dictionaries are used internally, e.g., by ":echo" that runs into
	    the more-prompt or ":echo [garbagecollect()]".
Solution:   Only do garbage collection when waiting for a character at the
	    toplevel.  Let garbagecollect() set a flag that is handled at the
	    toplevel before waiting for a character.
Files:	    src/eval.c, src/getchar.c, src/globals.h, src/main.c


*** ../vim-7.0.083/src/eval.c	Sun Sep  3 15:38:02 2006
--- src/eval.c	Tue Sep  5 11:49:38 2006
***************
*** 6074,6079 ****
--- 6074,6083 ----
      tabpage_T	*tp;
  #endif
  
+     /* Only do this once. */
+     want_garbage_collect = FALSE;
+     may_garbage_collect = FALSE;
+ 
      /*
       * 1. Go through all accessible variables and mark all lists and dicts
       *    with copyID.
***************
*** 9636,9642 ****
      typval_T	*argvars;
      typval_T	*rettv;
  {
!     garbage_collect();
  }
  
  /*
--- 9640,9648 ----
      typval_T	*argvars;
      typval_T	*rettv;
  {
!     /* This is postponed until we are back at the toplevel, because we may be
!      * using Lists and Dicts internally.  E.g.: ":echo [garbagecollect()]". */
!     want_garbage_collect = TRUE;
  }
  
  /*
*** ../vim-7.0.083/src/getchar.c	Wed May  3 23:19:24 2006
--- src/getchar.c	Tue Sep  5 12:55:54 2006
***************
*** 1451,1457 ****
  {
      updatescript(0);
  #ifdef FEAT_EVAL
!     garbage_collect();
  #endif
  }
  
--- 1451,1458 ----
  {
      updatescript(0);
  #ifdef FEAT_EVAL
!     if (may_garbage_collect)
! 	garbage_collect();
  #endif
  }
  
***************
*** 1502,1507 ****
--- 1503,1515 ----
      int		i;
  #endif
  
+ #ifdef FEAT_EVAL
+     /* Do garbage collection when garbagecollect() was called previously and
+      * we are now at the toplevel. */
+     if (may_garbage_collect && want_garbage_collect)
+ 	garbage_collect();
+ #endif
+ 
      /*
       * If a character was put back with vungetc, it was already processed.
       * Return it directly.
***************
*** 1511,1523 ****
  	c = old_char;
  	old_char = -1;
  	mod_mask = old_mod_mask;
- 	return c;
      }
! 
!     mod_mask = 0x0;
!     last_recorded_len = 0;
!     for (;;)			/* this is done twice if there are modifiers */
      {
  	if (mod_mask)		/* no mapping after modifier has been read */
  	{
  	    ++no_mapping;
--- 1519,1531 ----
  	c = old_char;
  	old_char = -1;
  	mod_mask = old_mod_mask;
      }
!     else
      {
+       mod_mask = 0x0;
+       last_recorded_len = 0;
+       for (;;)			/* this is done twice if there are modifiers */
+       {
  	if (mod_mask)		/* no mapping after modifier has been read */
  	{
  	    ++no_mapping;
***************
*** 1695,1702 ****
  	}
  #endif
  
! 	return c;
      }
  }
  
  /*
--- 1703,1722 ----
  	}
  #endif
  
! 	break;
!       }
      }
+ 
+ #ifdef FEAT_EVAL
+     /*
+      * In the main loop "may_garbage_collect" can be set to do garbage
+      * collection in the first next vgetc().  It's disabled after that to
+      * avoid internally used Lists and Dicts to be freed.
+      */
+     may_garbage_collect = FALSE;
+ #endif
+ 
+     return c;
  }
  
  /*
*** ../vim-7.0.083/src/globals.h	Sat Sep  2 14:52:41 2006
--- src/globals.h	Tue Sep  5 11:46:10 2006
***************
*** 300,308 ****
  #endif
  
  #ifdef FEAT_EVAL
! EXTERN scid_T	current_SID INIT(= 0);	    /* ID of script being sourced or
! 					       was sourced to define the
! 					       current function. */
  #endif
  
  #if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
--- 300,315 ----
  #endif
  
  #ifdef FEAT_EVAL
! /* Garbage collection can only take place when we are sure there are no Lists
!  * or Dictionaries being used internally.  This is flagged with
!  * "may_garbage_collect" when we are at the toplevel.
!  * "want_garbage_collect" is set by the garbagecollect() function, which means
!  * we do garbage collection before waiting for a char at the toplevel. */
! EXTERN int	may_garbage_collect INIT(= FALSE);
! EXTERN int	want_garbage_collect INIT(= FALSE);
! 
! /* ID of script being sourced or was sourced to define the current function. */
! EXTERN scid_T	current_SID INIT(= 0);
  #endif
  
  #if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
*** ../vim-7.0.083/src/main.c	Tue Aug 29 17:28:56 2006
--- src/main.c	Tue Sep  5 12:33:47 2006
***************
*** 1130,1135 ****
--- 1130,1145 ----
  	 */
  	update_curswant();
  
+ #ifdef FEAT_EVAL
+ 	/*
+ 	 * May perform garbage collection when waiting for a character, but
+ 	 * only at the very toplevel.  Otherwise we may be using a List or
+ 	 * Dict internally somewhere.
+ 	 * "may_garbage_collect" is reset in vgetc() which is invoked through
+ 	 * do_exmode() and normal_cmd().
+ 	 */
+ 	may_garbage_collect = (!cmdwin && !noexmode);
+ #endif
  	/*
  	 * If we're invoked as ex, do a round of ex commands.
  	 * Otherwise, get and execute a normal mode command.
*** ../vim-7.0.083/src/version.c	Sun Sep  3 16:39:51 2006
--- src/version.c	Tue Sep  5 12:51:28 2006
***************
*** 668,669 ****
--- 668,671 ----
  {   /* Add new patch number below this line */
+ /**/
+     84,
  /**/

-- 
LAUNCELOT: At last!   A call!  A cry of distress ...
           (he draws his sword, and turns to CONCORDE)
           Concorde!  Brave, Concorde ... you shall not have died in vain!
CONCORDE:  I'm not quite dead, sir ...
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\        download, build and distribute -- http://www.A-A-P.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///