[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: (fwd) Re: Ada GC and a bunch of other stuff



>  Date: Mon, 12 Feb 96 15:32:38 +1000
>  From: Frank Copeland <fjc@wossname.apana.org.au>
>  
>  Hi folks,
>  
>  This caught my eye, and I thought it would be of interest. I'll see if I
>  can turn up anything else on the subject. As far as I can tell an ETH-style
>  mark-and-sweep collector such as the one I use is what Chase is calling a
>  'precise' collector. I've put a few comments in square brackets in the body
>  of the article.

I have a few comments myself from the GSA point of view.
>  
>  From: chase@centerline.com (David Chase)
>  ...
>  
>  1. Basic pointer arithmetic optimizations.  Any decent optimizer is
>  likely to take expressions like A[i+j] and form some sort of
>  addressing subexpression involving the address of the array A and i,
>  j, or both.  The resulting subexpression could point *anywhere*, since
>  there are no constraints (generally) on the values in i and j,
>  considered separately (the sum is constrained, of course).

This is a problem if you calculate the address of A[i+j], discard the
base pointer to A because it's no longer needed, start up the GC, and
only after that use the address of A[i+j] to get a value from the
heap.  The optimizers can build code like this, and it can be
artificially created by using SYSTEM.ADR.  So it can happen (and
probably will) and I don't see an easy way to solve this.

>  2. Initialization.  If the collector is "precise", meaning that it is
>  designed with the assumption that it will find all pointers, then you
>  have to be careful with newly allocated memory/variables.  If it
>  contains junk, this could cause problems for the collector.  Note that
>  an optimizer might notice that the "initialization" of a variable is
>  later overwritten, and remove the initialization -- after all, it
>  isn't used, is it?

Yes, unused initialization for scalar values (incl pointers) are
detected and are dead code, as far as GSA is concerned.  This is
further complicated by the fact that a GSA back-end can't just
allocate storage for local variables (simply because GSA knows nothing
about variables), but rather has to allocate for as many values as
necessary.  So, even if initialization is kept in the code, it doesn't
guarantee that every possible location that can keep a pointer value
for a procedure's lifetime is set to zero.

>  4. Undoing the programmer's good intentions.  Suppose that you,
>  Mr./Ms.  Programmer, notices that you have a reference in a
>  non-longer-useful variable, as you are about to make a truly recursive
>  call, as in:
>  
>    f(p) {
>      q = <something allocating memory>
>      ... q ...
>      f( r );
>      <no further occurrences of q>
>      }
>  
>  This could lead to unnecessarily retained storage.  But, we know what
>  to do here:
>  
>    f(p) {
>      q = <something allocating memory>
>      ... q ...
>      q := NIL; /* Stomp on last reference to that memory, so
>                   it will be collected. */
>      f( r );
>      <no further occurrences of q>
>      }
>  
>  Too bad for you that the dead code eliminator got rid of that inserted
>  assignment to q, isn't it?  (I hate it when that happens.)
>  
>    [ This is something that will have to be watched. Assigning NIL to a
>      pointer can have implications beyond the immediate block of code being
>      optimised. This is especially true if code following the assignment
>      directly or indirectly triggers the garbage collector. ]

This "q:=NIL" is definitely dead code.  Even keeping it in the code
might not solve all problems (see my note to 3.).  Note that there are
no assignments in GSA: the "q:=NIL" in the above piece of code would
only appear in the exit instruction of f if q is global, and it won't
appear in GSA at all if q is local.