Having applied a bit more thought, having the generation field as part of the PMC isn't all that great -- it makes PMCs larger, but it's really only needed for new/neonate pmcs.
Instead of attatching the generation directly to the pmc, have a global (per-interpreter) stack of neonate pmcs. Each stack entry contains both the generation it was added, and the pointer to the pmc. When a pmc is created, it does something like: while( size(neonate_stack) && top(neonate_stack).gen > cur_gen ) pop(neonate_stack); push(neonate_stack, { self, cur_gen }); During DOD, we do: foreach(pmc in all_pmcs) mark pmc as dead while( size(neonate_stack) && top(neonate_stack).gen > cur_gen ) pop(neonate_stack) foreach( pmc in root_set and on the neonate_stack ) { if( pmc is alive ) next; mark pmc as live if( pmc is an aggregate ) add pmc to the list of pmcs to be traced } foreach( pmc in all_pmcs ) if( pmc is dead ) add pmc to free list; -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}