diff options
author | Jim Blandy <jimb@red-bean.com> | 1999-07-19 18:45:57 +0000 |
---|---|---|
committer | Jim Blandy <jimb@red-bean.com> | 1999-07-19 18:45:57 +0000 |
commit | 55b7e0bd829bf604387aae1898c9b7e1e17d4ea8 (patch) | |
tree | 8c69e36c549ca624d1d71c18a202d114e504249f /libguile/guardians.c | |
parent | 6d8500ad76b5bac0e9fb6d7796ed7eaf052e53e0 (diff) | |
download | guile-55b7e0bd829bf604387aae1898c9b7e1e17d4ea8.tar.gz |
* guardians.c (scm_guardian_zombify): Don't set marks manually ---
use the macros. (Thanks to Michael Livshin.)
Diffstat (limited to 'libguile/guardians.c')
-rw-r--r-- | libguile/guardians.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/libguile/guardians.c b/libguile/guardians.c index d9cfc129b..3dd28a27c 100644 --- a/libguile/guardians.c +++ b/libguile/guardians.c @@ -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); } } |