changeset 20057:612cd201aea5

(gc_sweep): Free memory blocks that contain only unused objects.
author Karl Heuer <kwzh@gnu.org>
date Wed, 15 Oct 1997 23:28:06 +0000
parents dd567e1fddd5
children 7077ba8a265b
files src/alloc.c
diffstat 1 files changed, 86 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/alloc.c	Wed Oct 15 23:15:09 1997 +0000
+++ b/src/alloc.c	Wed Oct 15 23:28:06 1997 +0000
@@ -2126,18 +2126,21 @@
   /* Put all unmarked conses on free list */
   {
     register struct cons_block *cblk;
+    struct cons_block **cprev = &cons_block;
     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)
+    for (cblk = cons_block; cblk; cblk = *cprev)
       {
 	register int i;
+	int this_free = 0;
 	for (i = 0; i < lim; i++)
 	  if (!XMARKBIT (cblk->conses[i].car))
 	    {
 	      num_free++;
+	      this_free++;
 	      *(struct Lisp_Cons **)&cblk->conses[i].cdr = cons_free_list;
 	      cons_free_list = &cblk->conses[i];
 	    }
@@ -2147,6 +2150,19 @@
 	      XUNMARK (cblk->conses[i].car);
 	    }
 	lim = CONS_BLOCK_SIZE;
+	/* If this block contains only free conses and we have already
+	   seen more than two blocks worth of free conses then deallocate
+	   this block.  */
+	if (this_free == CONS_BLOCK_SIZE && num_free > 2*CONS_BLOCK_SIZE)
+	  {
+	    num_free -= CONS_BLOCK_SIZE;
+	    *cprev = cblk->next;
+	    /* Unhook from the free list.  */
+	    cons_free_list = *(struct Lisp_Cons **) &cblk->conses[0].cdr;
+	    xfree (cblk);
+	  }
+	else
+	  cprev = &cblk->next;
       }
     total_conses = num_used;
     total_free_conses = num_free;
@@ -2156,18 +2172,21 @@
   /* Put all unmarked floats on free list */
   {
     register struct float_block *fblk;
+    struct float_block **fprev = &float_block;
     register int lim = float_block_index;
     register int num_free = 0, num_used = 0;
 
     float_free_list = 0;
   
-    for (fblk = float_block; fblk; fblk = fblk->next)
+    for (fblk = float_block; fblk; fblk = *fprev)
       {
 	register int i;
+	int this_free = 0;
 	for (i = 0; i < lim; i++)
 	  if (!XMARKBIT (fblk->floats[i].type))
 	    {
 	      num_free++;
+	      this_free++;
 	      *(struct Lisp_Float **)&fblk->floats[i].data = float_free_list;
 	      float_free_list = &fblk->floats[i];
 	    }
@@ -2177,6 +2196,19 @@
 	      XUNMARK (fblk->floats[i].type);
 	    }
 	lim = FLOAT_BLOCK_SIZE;
+	/* If this block contains only free floats and we have already
+	   seen more than two blocks worth of free floats then deallocate
+	   this block.  */
+	if (this_free == FLOAT_BLOCK_SIZE && num_free > 2*FLOAT_BLOCK_SIZE)
+	  {
+	    num_free -= FLOAT_BLOCK_SIZE;
+	    *fprev = fblk->next;
+	    /* Unhook from the free list.  */
+	    float_free_list = *(struct Lisp_Float **) &fblk->floats[0].data;
+	    xfree (fblk);
+	  }
+	else
+	  fprev = &fblk->next;
       }
     total_floats = num_used;
     total_free_floats = num_free;
@@ -2187,14 +2219,16 @@
   /* Put all unmarked intervals on free list */
   {
     register struct interval_block *iblk;
+    struct interval_block **iprev = &interval_block;
     register int lim = interval_block_index;
     register int num_free = 0, num_used = 0;
 
     interval_free_list = 0;
 
-    for (iblk = interval_block; iblk; iblk = iblk->next)
+    for (iblk = interval_block; iblk; iblk = *iprev)
       {
 	register int i;
+	int this_free = 0;
 
 	for (i = 0; i < lim; i++)
 	  {
@@ -2203,6 +2237,7 @@
 		iblk->intervals[i].parent = interval_free_list;
 		interval_free_list = &iblk->intervals[i];
 		num_free++;
+		this_free++;
 	      }
 	    else
 	      {
@@ -2211,6 +2246,20 @@
 	      }
 	  }
 	lim = INTERVAL_BLOCK_SIZE;
+	/* If this block contains only free intervals and we have already
+	   seen more than two blocks worth of free intervals then
+	   deallocate this block.  */
+	if (this_free == INTERVAL_BLOCK_SIZE
+	    && num_free > 2*INTERVAL_BLOCK_SIZE)
+	  {
+	    num_free -= INTERVAL_BLOCK_SIZE;
+	    *iprev = iblk->next;
+	    /* Unhook from the free list.  */
+	    interval_free_list = iblk->intervals[0].parent;
+	    xfree (iblk);
+	  }
+	else
+	  iprev = &iblk->next;
       }
     total_intervals = num_used;
     total_free_intervals = num_free;
@@ -2220,20 +2269,23 @@
   /* Put all unmarked symbols on free list */
   {
     register struct symbol_block *sblk;
+    struct symbol_block **sprev = &symbol_block;
     register int lim = symbol_block_index;
     register int num_free = 0, num_used = 0;
 
     symbol_free_list = 0;
   
-    for (sblk = symbol_block; sblk; sblk = sblk->next)
+    for (sblk = symbol_block; sblk; sblk = *sprev)
       {
 	register int i;
+	int this_free = 0;
 	for (i = 0; i < lim; i++)
 	  if (!XMARKBIT (sblk->symbols[i].plist))
 	    {
 	      *(struct Lisp_Symbol **)&sblk->symbols[i].value = symbol_free_list;
 	      symbol_free_list = &sblk->symbols[i];
 	      num_free++;
+	      this_free++;
 	    }
 	  else
 	    {
@@ -2243,6 +2295,19 @@
 	      XUNMARK (sblk->symbols[i].plist);
 	    }
 	lim = SYMBOL_BLOCK_SIZE;
+	/* If this block contains only free symbols and we have already
+	   seen more than two blocks worth of free symbols then deallocate
+	   this block.  */
+	if (this_free == SYMBOL_BLOCK_SIZE && num_free > 2*SYMBOL_BLOCK_SIZE)
+	  {
+	    num_free -= SYMBOL_BLOCK_SIZE;
+	    *sprev = sblk->next;
+	    /* Unhook from the free list.  */
+	    symbol_free_list = *(struct Lisp_Symbol **)&sblk->symbols[0].value;
+	    xfree (sblk);
+	  }
+	else
+	  sprev = &sblk->next;
       }
     total_symbols = num_used;
     total_free_symbols = num_free;
@@ -2254,14 +2319,16 @@
      but only if it's a real marker.  */
   {
     register struct marker_block *mblk;
+    struct marker_block **mprev = &marker_block;
     register int lim = marker_block_index;
     register int num_free = 0, num_used = 0;
 
     marker_free_list = 0;
   
-    for (mblk = marker_block; mblk; mblk = mblk->next)
+    for (mblk = marker_block; mblk; mblk = *mprev)
       {
 	register int i;
+	int this_free = 0;
 	EMACS_INT already_free = -1;
 
 	for (i = 0; i < lim; i++)
@@ -2305,6 +2372,7 @@
 		mblk->markers[i].u_free.chain = marker_free_list;
 		marker_free_list = &mblk->markers[i];
 		num_free++;
+		this_free++;
 	      }
 	    else
 	      {
@@ -2314,6 +2382,19 @@
 	      }
 	  }
 	lim = MARKER_BLOCK_SIZE;
+	/* If this block contains only free markers and we have already
+	   seen more than two blocks worth of free markers then deallocate
+	   this block.  */
+	if (this_free == MARKER_BLOCK_SIZE && num_free > 2*MARKER_BLOCK_SIZE)
+	  {
+	    num_free -= MARKER_BLOCK_SIZE;
+	    *mprev = mblk->next;
+	    /* Unhook from the free list.  */
+	    marker_free_list = mblk->markers[0].u_free.chain;
+	    xfree (mblk);
+	  }
+	else
+	  mprev = &mblk->next;
       }
 
     total_markers = num_used;