Benjamin Goldberg <[EMAIL PROTECTED]> writes:

> 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 is Solution 3: Explicit root set augmentation

Its not explained in so much details than the other solutions.

> 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.

In principle this is a variant of the explicit root set
augmentation. The linked list of frames is part of the root set. The
big advantages of this list is that return and longjmp automatically
drop the now unused objects, because each partial list is stored in
the C-stack-frames.

> 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.

This is a solution similar to Solution 2 / Variant 4: Generation
count.

> During a DOD run, any PMC with a generation less than or equal to the
> current generation is considered live. 

You can even use mark the current generation as free. If a function
wants to keep data it uses Parrot_do_DOD(interp, generation + 1). If
it does not have any data to keep it calls Parrot_do_DOD(interp,
generation). 

> Any PMC with a generation
> greater than the current generation gets it's generation set to 0.

You mean is marked as free. An anchored object should be 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.

If this will lead to exact and fast DOD we might bite the bullet.

> 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.

When asume the current generation as free (less than instead of less
equal) this is not problem. Only if qux calls another function with an
increased generation count without a prior call to Parrot_do_DOD the
temporaries of baz will survive. But this can be solved by:

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

> 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.

In principle your generational_dod_helper is the sweep-function of the
garbage-collector (or in parrot its called free_unused_objects). If
you are sure that no objects have been anchored since the last mark no
further mark is necessary (Parrot_do_DOD). But I'm not sure if you can
guarantee that.

I have the feeling that extending the signature of all
Parrot-functions will remove the need of walking the C-Stack
entirely. If this will be the linked list of frames or the generation
count is more or less a matter of taste: The generation count forces
some intermediate DOD-runs, whereas the linked list of stack
frames makes the creation of temporaries a little bit more
complicated.

bye
boe
-- 
Juergen Boemmels                        [EMAIL PROTECTED]
Fachbereich Physik                      Tel: ++49-(0)631-205-2817
Universitaet Kaiserslautern             Fax: ++49-(0)631-205-3906
PGP Key fingerprint = 9F 56 54 3D 45 C1 32 6F  23 F6 C7 2F 85 93 DD 47

Reply via email to