From 50fecba92d4a163fb19fe0115e1ba1df339d3cdc Mon Sep 17 00:00:00 2001 From: Michael Livshin Date: Mon, 3 Apr 2000 13:55:54 +0000 Subject: [PATCH] * guardians.c (scm_guardian_zombify): mark all zombies in a separate loop after processing all the currently known live guardians, so as to not introduce order dependencies (thanks to Gary Houston). also, make another outer loop to process zombified guardians (which are uncovered while marking zombies). --- libguile/ChangeLog | 22 +++++--- libguile/guardians.c | 117 +++++++++++++++++++++++-------------------- 2 files changed, 79 insertions(+), 60 deletions(-) diff --git a/libguile/ChangeLog b/libguile/ChangeLog index 4565be6c6..d21f7c7e8 100644 --- a/libguile/ChangeLog +++ b/libguile/ChangeLog @@ -1,3 +1,11 @@ +2000-04-03 Michael Livshin + + * guardians.c (scm_guardian_zombify): mark all zombies in a + separate loop after processing all the currently known live + guardians, so as to not introduce order dependencies (thanks to + Gary Houston). also, make another outer loop to process zombified + guardians (which are uncovered while marking zombies). + 2000-04-03 Dirk Herrmann * evalext.c (scm_definedp, scm_m_undefine), gc.c @@ -531,22 +539,22 @@ 2000-03-18 Michael Livshin - * tags.h: (SCM_DOUBLE_CELLP, SCM_NDOUBLE_CELLP): new macros. + * tags.h: (SCM_DOUBLE_CELLP, SCM_NDOUBLE_CELLP): new macros (bad + names, anyone got any better ones?) * gc.h: (typedef struct scm_freelist_t) remove from here. - * gc.c: (CELL_UP, CELL_DN) make these macros take additional + * gc.c: (CELL_UP, CELL_DN) made these macros take additional parameter (the span). (CLUSTER_SIZE_IN_BYTES, ALIGNMENT_SLACK) new macros. - (typedef struct scm_freelist_t) move here from gc.h, it had no + (typedef struct scm_freelist_t) moved here from gc.h, it had no business being externally visible. (typedef struct scm_heap_seg_data_t) renamed from scm_heap_seg_data, to be style-compliant. (scm_mark_locations) if the possible pointer points to a - multy-cell, check that it's properly aligned. - (init_heap_seg) alighn multy-cells properly, work with the - assumption that the segment size divides cleanly by cluster size - (so that there's no spill). + double-cell, check that it's properly aligned. + (init_heap_seg) align double-cells properly, work with the + assumption that the segment size divides cleanly by cluster size. (round_to_cluster_size) new function. (alloc_some_heap, make_initial_segment) use round_to_cluster_size to satisfy the new init_heap_seg invariant. diff --git a/libguile/guardians.c b/libguile/guardians.c index ccf0d284c..73348f898 100644 --- a/libguile/guardians.c +++ b/libguile/guardians.c @@ -232,7 +232,8 @@ g_mark (SCM ptr) its live list (tconc) to its zombie list (tconc). */ void scm_guardian_zombify (void) { - guardian_t *g; + guardian_t *first_guardian; + guardian_t **link_field = &first_live_guardian; /* 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 @@ -240,59 +241,69 @@ void scm_guardian_zombify (void) 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) - { - SCM tconc_tail = g->live.tail; - SCM *prev_ptr = &g->live.head; - SCM pair = g->live.head; - - while (! SCM_EQ_P (pair, tconc_tail)) - { - SCM next_pair = SCM_CDR (pair); - - if (SCM_NMARKEDP (SCM_CAR (pair))) - { - /* got you, zombie! */ - - /* out of the live list! */ - *prev_ptr = next_pair; - - /* into the zombie list! */ - TCONC_IN (g->zombies, SCM_CAR (pair), pair); - } - else - prev_ptr = SCM_CDRLOC (pair); - - pair = next_pair; - } - - /* Mark the cells of the live list (yes, the cells in the list, - even though we don't care about objects pointed to by the list - cars, since we know they are already marked). */ - for (pair = g->live.head; SCM_NIMP (pair); pair = SCM_GCCDR (pair)) - SCM_SETGCMARK (pair); - - /* Preserve the zombies in their undead state, by marking to - prevent collection. */ - - /* ghouston: possible bug: this may mark objects which are - protected by other guardians, but which have no references - from outside of the guardian system. section 3 of the paper - mentions shared and cyclic objects and it seems that all - parts should be made available for collection. Currently the - behaviour depends on the order in which guardians are - scanned. - - Doesn't it seem a bit disturbing that if a zombie is returned - to full life after getting returned from the guardian - procedure, it may reference objects which are in a guardian's - zombie list? Is it not necessary to move such zombies back - to the live list, to avoid allowing the guardian procedure to - return an object which is referenced, so not collectable? - The paper doesn't give this impression. */ - + do { + guardian_t *g; + + first_guardian = *link_field; + link_field = current_link_field; + + /* first, scan all the guardians that are currently known to be live + and move their unmarked objects to zombie lists. */ + + for (g = first_guardian; g; g = g->next) + { + SCM tconc_tail = g->live.tail; + SCM *prev_ptr = &g->live.head; + SCM pair = g->live.head; + + while (! SCM_EQ_P (pair, tconc_tail)) + { + SCM next_pair = SCM_CDR (pair); + + if (SCM_NMARKEDP (SCM_CAR (pair))) + { + /* got you, zombie! */ + + /* out of the live list! */ + *prev_ptr = next_pair; + + /* into the zombie list! */ + TCONC_IN (g->zombies, SCM_CAR (pair), pair); + } + else + prev_ptr = SCM_CDRLOC (pair); + + pair = next_pair; + } + + /* Mark the cells of the live list (yes, the cells in the list, + even though we don't care about objects pointed to by the list + cars, since we know they are already marked). */ + for (pair = g->live.head; SCM_NIMP (pair); pair = SCM_GCCDR (pair)) + SCM_SETGCMARK (pair); + } + + /* ghouston: Doesn't it seem a bit disturbing that if a zombie + is returned to full life after getting returned from the + guardian procedure, it may reference objects which are in a + guardian's zombie list? Is it not necessary to move such + zombies back to the live list, to avoid allowing the + guardian procedure to return an object which is referenced, + so not collectable? The paper doesn't give this + impression. + + cmm: the paper does explicitly say that an object that is + guarded more than once should be returned more than once. + I believe this covers the above scenario. */ + + /* Preserve the zombies in their undead state, by marking to + prevent collection. Note that this may uncover zombified + guardians -- if so, they'll be processed in the next loop. */ + + for (g = first_guardian; g && (!*link_field || g != *link_field); g = g->next) scm_gc_mark (g->zombies.head); - } + + } while (current_link_field != link_field); } /* not generally used, since guardian smob is wrapped in a closure. -- 2.20.1