I was recently reading the following:

   http://www.parrotcode.org/docs/dev/infant.dev.html

It's missing some things.  One of which is the (currently used?) way of
preventing infant mortality: anchor right away, or else turn off DoD
until the new object isn't needed.

This document doesn't mention another technique, which was mentioned
recently:

   http://groups.google.com/groups?
      selm=m2k7asg87i.fsf%40helium.physik.uni-kl.de

, at the "use a linked list of frames" part.


Another similar idea (one which I thought of myself, so feel free to
shoot it down!) is to use a generational system, with the "current
generation" as a value on the C stack, passed as an argument after the
interpreter.  That is, something like:

foo(struct ParrotInterp *interpreter, int generation, ...)
  {
    PMC * temp = bar(interpreter, generation);
    baz(interpreter, generation+1);
  }

Because inside baz(), generation is a higher value than it was when temp
was created, a DOD run inside of baz() won't kill foo.

During a DOD run, any PMC with a generation less than or equal to the
current generation is considered live.  Any PMC with a generation
greater than the current generation gets it's generation set to 0.

Like the linked list scheme, this works through longjmps and recursive
run_cores, and it's much simpler for the user, too: just add one to the
generation to prevent all temporaries in scope from being freed.

It similarly has the drawback of altering the signature of every parrot
function.

There's another drawback I can think of... consider:

foo(struct ParrotInterp *interpreter, int generation, ...)
  {
    PMC * temp = bar(interpreter, generation);
    baz(interpreter, generation+1);
    qux(interpreter, generation+1);
  }

If baz creates a temporary object and returns, then qux performs a DOD,
baz's (dead) object won't get cleaned up.

This could be solved by keeping a stack of newly created objects, and
providing some sort of generational_dod_helper() function, which would
do something like:
   while( neonates && neonates->top->generation > current_generation ) {
      neonates->top->generation = 0;
      neonates = neonates->next;
   }
, and calling that in foo between baz and qux.  (And maybe sometimes at
toplevel, between opcodes... at times when the generation count in a
"normal" generation count scheme (with a global counter) would be
incremented)  You lost a bit of simplicity, by having to call this
function occcasionally, but it can save a bit of memory.

-- 
$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;}

Reply via email to