On Sun, Aug 25, 2002 at 01:34:32PM -0400, Dan Sugalski wrote:
> At 4:22 PM +0100 8/25/02, Dave Mitchell wrote:

> >Well, if understood you correctly, then a single execution of
> >
> >    my $fh = IO::File->new(...)
> >
> >anywhere in the program or its libraries would trigger this slow behaviour
> >for the rest of the program.
> 
> No. That's why we make it a counter. When a DOD run is made we recalc 
> the number of deterministci destructions needed.

But I believe that that means as long as something has an IO:File somewhere
in parrot, our DD-needed counter is non zero, and every block exit must be
a DOD run.

(although your counter is better than "the rest of the program", (for ever
and ever, world without end, Amen))

however, rambling further:

On Sun, Aug 25, 2002 at 05:27:14PM +0100, Nicholas Clark wrote:

> 0: Default interpreter state is that
>    a: there are no loose objects with deterministic destruction needed
>    b: there are no rooted objects with deterministic destruction needed
> 
> (the meaning latter becomes clear below)
> 
> 1: when you create an object with deterministic destruction needed, it is
>    flagged as such, and the interpreter is flagged as having one of these
>    loose.
> 2: Likewise, if you ever assign an object with deterministic destruction
>    needed, the interpreter is flagged as having one of these beasts loose.
> 3: And if you ever assign (and overwrite) a DD object, you need to do a DOD
>    run (as you might just have removed the last reference to it)
> 
> 4: At the end of a block, if there are no objects of either sort, you are
>    happy - just let GC work
> 
>    If there are rooted objects with deterministic destruction needed, but no
>    loose objects, then you need to force a DOD run.
> 
>    If there are loose objects, then you need to do a DOD run, *and* when you
>    find any deterministic destruction objects around that have parents that
>    aren't deterministic, then you need to propagate the deterministic flag
>    upwards (recursively, unfortunately) to the root.
>    You then clear the loose object flag.


I think that rather than having a loose object flag, a loose object *counter*
would be better.

So this is a variant on your scheme. But I'm only counting the number of DD
objects that "loose" - by which I mean DD objects that aren't rooted in DD
objects (etc) back to "the root set". (whatever that might mean, but here
it means some top level container from which everything else hangs which is
treated as DD, but in reality never goes away for the life of the GC system)

I don't think you win at all this way if the compiler is puts ops in
to  explicitly free DD objects for each reference it knows about when they
go out out of scope.

Say someone goes

{
  my $fh = IO::File->new(...)
  ...
}

the compiler knows that $fh had a reference to the IO::File object, but
that reference has just been eliminated, so it's time to check. But if you
have an op saying "the IO::File formerly pointed to by $fh may be dead"
you still have to do a full DOD run to try to find it. And you have to
carry the DOD run to completion (rather being able to stop short at the
first point when you find a rooted reference to "the IO::File formerly
pointed to by $fh") because the block may have looked like this

{
  my $fh = IO::File->new(...)
  ...
  push @global1, $fh;
  %global2{file} = $fh;
  ...
}

ie you need to ensure that both @global1 and %global2 have become marked as
DD, so that from here on the DD object is properly tracked.

But this all does smell of overhead - not as much as refcounting - because
for each object it's a 1 bit flag - but then again there's still DOD needed,
whereas refcounting doesn't need DOD.
(except to detect unreachable circular object loops)

Nicholas Clark
-- 
Even better than the real thing:        http://nms-cgi.sourceforge.net/

Reply via email to