[gclist] What wrong with the GC in xemacs

Nick Barnes nickb@harlequin.co.uk
Wed, 03 Apr 1996 10:56:24 +0100


> Emacs does not return Lisp storage to the system, only buffer space, which
> are allocated differently from Lisp storage.  buffers are not GC'ed -- the
> buffer space is released and others possibly relocated as soon as the
> buffer is killed.  (the Lisp buffer object is gc'ed.)

Looking at gc_sweep(), it seems that you are both partly right. Cons
cells are _not_ returned to the system. Neither are floats, symbols,
or "text intervals". Buffers &c _are_ allocated differently. But
unmarked buffers, vectors, large strings, and string blocks _are_
returned to the system. Look for uses of xfree()...

Nick Barnes

/* Storage allocation and gc for GNU Emacs Lisp interpreter.
   Copyright (C) 1985, 86, 88, 93, 94, 95 Free Software Foundation, Inc.

This code used to be part of GNU Emacs. It has been hacked about for
presentation reasons by Nick Barnes, 1996-04-03.

GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

*/

static void gc_sweep ()
{
  total_string_size = 0;
  compact_strings ();

/* compact_strings compacts the contents of all "small string		*/
/* blocks", and frees any resulting free blocks. NB. 			*/

  /* Put all unmarked conses on free list */
  {
    register struct cons_block *cblk;
    register int lim = cons_block_index;
    register int num_free = 0, num_used = 0;

    cons_free_list = 0;
  
    for (cblk = cons_block; cblk; cblk = cblk->next)
      {
	register int i;
	for (i = 0; i < lim; i++)
	  if (!XMARKBIT (cblk->conses[i].car))
	    {
	      num_free++;
	      *(struct Lisp_Cons **)&cblk->conses[i].car = cons_free_list;
	      cons_free_list = &cblk->conses[i];
	    }
	  else
	    {
	      num_used++;
	      XUNMARK (cblk->conses[i].car);
	    }
	lim = CONS_BLOCK_SIZE;
      }
    total_conses = num_used;
    total_free_conses = num_free;
  }

#ifdef LISP_FLOAT_TYPE
  /* Put all unmarked floats on free list */
  /* [... removed code similar to above conses code ... NB] */
#endif /* LISP_FLOAT_TYPE */

#ifdef USE_TEXT_PROPERTIES
  /* Put all unmarked intervals on free list */
  /* [... removed code similar to above conses code ... NB] */
#endif /* USE_TEXT_PROPERTIES */

  /* Put all unmarked symbols on free list */
  /* [... removed code similar to above conses code ... NB] */

#ifndef standalone
  /* Put all unmarked markers on free list.
     Dechain each one first from the buffer it points into,
     but only if it's a real marker.  */
  /* [... removed code similar to above conses code ... NB] */

  /* Free all unmarked buffers */
  {
    register struct buffer *buffer = all_buffers, *prev = 0, *next;

    while (buffer)
      if (!XMARKBIT (buffer->name))
	{
	  if (prev)
	    prev->next = buffer->next;
	  else
	    all_buffers = buffer->next;
	  next = buffer->next;
	  xfree (buffer);
	  buffer = next;
	}
      else
	{
	  XUNMARK (buffer->name);
	  UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer));

	  prev = buffer, buffer = buffer->next;
	}
  }

#endif /* standalone */

  /* Free all unmarked vectors */
  /* [... removed code similar to above buffers code ... NB] */

  /* Free all "large strings" not marked with ARRAY_MARK_FLAG.  */
  /* [... removed code similar to above buffers code ... NB] */
}