From: Nattfodd <[EMAIL PROTECTED]>
   Date: Thu, 21 Jul 2005 03:22:04 +0200

   Leopold Toetsch wrote:

   >> ... Perhaps you should save your (metaphorical) breath, and I'll
   >> wait for a more detailed design.
   >
   >
   > I'm waiting too :-)

   Hi,
   I believe I found a good workaround for the cycle problems. It is a
   little bit slower and worst case (which never occurs, happily) is
   |IGP_set| passes, but should really be about 2 passes. But we need of
   course not to run it each time. We can have 'classical' gmc most of the
   time and once in a while, run NLDC (Night of the Living Dead Collection)
   to get rid of evil IGP dead cycles.

;-}

   Here is how NLDC works :

   We do not care at all about generations. First, make a normal marking
   pass, but without even considering the IGP set at all. Just see members
   of the IGP set (origin and destination of the pointer) as normal objects.
   Then, operation "Night of the Living Dead" begins (hence the name) : get
   out of their graves objects that shouldn't have been buried first. Run
   through the IGP set in reverse order of age of origin pointers. For each
   (p0 -> p1) element in the IGP, do the following : if p0 is marked dead,
   then do nothing and leave it dead. If it is marked alive, apply a
   recursive procedure :

   to_process := [p1];
   while (to_process != []) {
       p = pop (to_process);
       if (p is dead) {
           mark p alive;
           forall (p -> q) in IGP {
               push (q, to_process);
           }
           push (all childrens of p, to_process);
       }
   }

I'm still digesting it (and trying to bone up on GC algorithms at the
same time), but it does sound like it should work.  I assume that
"forall (p -> q)" above really means "forall (q0 -> q where q0 == p)",
i.e. process all IGP entries from p.

   However, except for the IGP loop, this is essentially the mark phase
of a two-pass algorithm.  So if we know that p is live, and we're going
to mark the children of p as live, then we shouldn't also have to go
through the IGP entries for p at this point, should we?

   FWIW, it might be better if you were to add only dead children to the
to_process queue:

   to_process := [p1];
   while (to_process != []) {
       p = pop (to_process);
       # assume p is dead
       mark p alive;
       forall child in children(p) {
           if (child is dead) {
               push (child, to_process);
           }
       }
   }

At the very least, this would require a smaller to_process queue in the
typical case.

   For the record, is it acceptable in Parrot to use page
write-protection to record whether oldspace objects have been modified
since the last full GC?  This is what CMUCL does on most ports, but it
occurs to me that this might be a porting headache for Parrot.

   . . .

   I discussed it with friends and think it can even be proved to work
   right (but that would take some time :/).

   Does that sound reasonable to you ?

   Regards,
   Alexandre

Even an outline of a proof would help to identify hidden assumptions.
Especially valuable would be to prove bounds on storage and time costs.
But of course it's your time, so it's your call.  (I'll holler if I find
any counterexamples, but I've been short on time lately.)

                                        -- Bob Rogers
                                           http://rgrjr.dyndns.org/

Reply via email to