* guardians.c (scm_guardian_zombify): Don't set marks manually ---
authorJim Blandy <jimb@red-bean.com>
Mon, 19 Jul 1999 18:45:57 +0000 (18:45 +0000)
committerJim Blandy <jimb@red-bean.com>
Mon, 19 Jul 1999 18:45:57 +0000 (18:45 +0000)
use the macros.  (Thanks to Michael Livshin.)

libguile/guardians.c

index d9cfc12..3dd28a2 100644 (file)
@@ -176,12 +176,17 @@ void
 scm_guardian_zombify ()
 {
   guardian_t *g;
+
+  /* Note that new guardians may be stuck on the end of the live
+     guardian list as we run this loop.  As we move unmarked objects
+     to the zombie list and mark them, we may find some guarded
+     guardians.  The guardian mark function will stick them on the end
+     of this list, so they'll be processed properly.  */
   for (g = first_live_guardian; g; g = g->next)
     {
       /* Loop through the live list and
         1. move unmarked objects to the zombies tconc
-        2. mark the live tconc.
-      */
+        2. mark the live tconc.  */
       SCM tconc_tail = g->live.tail;
       SCM prev_pair = SCM_BOOL_F;
       SCM pair = g->live.head;
@@ -189,6 +194,21 @@ scm_guardian_zombify ()
        {
          SCM next_pair = SCM_CDR (pair);
 
+         /* Since next_pair is never assigned to, and since pair is
+            always set to next_pair at the end of the loop, we know
+            that this loop always reaches every pair in the tconc
+            once, except the tail.
+
+            At each iteration, we either throw the pair out of the
+            live list, or we mark it.  And when we edit a pair's CDR,
+            we make sure to preserve its mark bit.  So when this loop
+            terminates, all pairs left in the live tconc (except the
+            tail) have been marked.
+
+            Whenever we throw out a pair, we always relink the tconc,
+            so the tconc list structure is valid at the end of every
+            iteration.  */
+
          if (SCM_NMARKEDP (SCM_CAR (pair)))
            {
              /* got you, zombie! */
@@ -197,28 +217,29 @@ scm_guardian_zombify ()
              if (SCM_FALSEP (prev_pair))
                g->live.head = next_pair;
              else
-                /* mark previous pair */
-               SCM_SETCDR (prev_pair, next_pair | 1);
+               {
+                 SCM_SETCDR (prev_pair, next_pair);
+                 /* Don't lose the mark bit!  */
+                 SCM_SETGCMARK (prev_pair);
+               }
 
              /* to the zombie list! */
              TCONC_IN (g->zombies, SCM_CAR (pair), pair);
            }
          else
            {
-             if (SCM_NFALSEP (prev_pair))
-                /* mark previous pair */
-               SCM_SETCDR (prev_pair, pair | 1);
+             SCM_SETGCMARK (pair);
              prev_pair = pair;
            }
 
          pair = next_pair;
        }
-      if (SCM_NFALSEP (prev_pair))
-       /* mark previous pair */
-       SCM_SETCDR (prev_pair, pair | 1);
-      /* mark live list tail */
-      SCM_SETOR_CDR (tconc_tail, 1);
       
+      /* Mark the tconc's tail cell.  All the other pairs in the tconc
+         are already marked.  */
+      SCM_SETGCMARK (tconc_tail);
+
+      /* Bring the zombies back from the dead.  */
       scm_gc_mark (g->zombies.head);
     }
 }