[comp.lang.scheme] Memory allocation mechanism

muenx@heike.informatik.uni-dortmund.de (Holger Muenx) (11/01/90)

Hi...

I just started to implement another functional programming language. It
contains lists which are done similar to Scheme's CONS - CAR - CDR.

Now let's have a tree T with left and right subtrees L and R. The final tree T
obviously can be contructed by something like T = (CONS L R). Let's assume the
evalution order is left-most-inner-most. So first the subtree L is
constructed, then subtree R and finally the CONS shown above is executed.

Here comes my question: What happens if the construction of L is finished and
the system realizes while dealing with R that there is no more space available?
Of course, garbage collection is started. But there is no reference to
the left subtree because it is ready constructed and hold only in some intern
register or stack of the underlying language. All contents of L will be
regarded as unused of the garbage collection algorithm.

It is simple to see that it is not enough to have a global register which
contains the CAR of a pair while constructing the CDR. My next idea was the
brute force approach: I had a additional stack on which I pushed explicitely
everything to which there were no other reference and which could be destroyed
by garbage collection although it is no garbage. While garbage collection I
used the references on the stack as roots of used cell trees too. It worked but
unfortunately this creates much expense and is susceptible for mistakes.

I am sure that there is a more elegant solution which I have not considered
yet. Any idea?

Thanks in advance,

                                                       -Holger

===========================================================================
|| Holger Muenx, IRB, Universitaet Dortmund, 4600 Dortmund, West-Germany ||
||          Internet: muenx@heike.informatik.uni-dortmund.de             ||
===========================================================================

gyro@CYMBAL.REASONING.COM (Scott Layson Burson) (11/03/90)

   Date: 1 Nov 90 14:34:06 GMT
   From: Holger Muenx <mcsun!unido!laura!heike.informatik.uni-dortmund.de!muenx@uunet.uu.net>

   I just started to implement another functional programming language. It
   contains lists which are done similar to Scheme's CONS - CAR - CDR.

   Now let's have a tree T with left and right subtrees L and R. The
   final tree T obviously can be contructed by something like T = (CONS
   L R). Let's assume the evalution order is left-most-inner-most. So
   first the subtree L is constructed, then subtree R and finally the
   CONS shown above is executed.

   Here comes my question: What happens if the construction of L is
   finished and the system realizes while dealing with R that there is
   no more space available?  Of course, garbage collection is started.
   But there is no reference to the left subtree because it is ready
   constructed and hold only in some intern register or stack of the
   underlying language. All contents of L will be regarded as unused of
   the garbage collection algorithm.

   It is simple to see that it is not enough to have a global register
   which contains the CAR of a pair while constructing the CDR. My next
   idea was the brute force approach: I had a additional stack on which
   I pushed explicitely everything to which there were no other
   reference and which could be destroyed by garbage collection although
   it is no garbage. While garbage collection I used the references on
   the stack as roots of used cell trees too. It worked but
   unfortunately this creates much expense and is susceptible for
   mistakes.

   I am sure that there is a more elegant solution which I have not
   considered yet. Any idea?

You are basically on the right track.  The only improvement that I know
of to the approach you are taking is to arrange to be able to scan the
CPU control stack and registers to find roots, so they do not have to be
kept on a separate stack.  I don't know of anyone who has successfully
done this without writing their own native-code compiler (and even then
it can be quite tricky to get right, as you might imagine).

Oh, as I reread your message I see that I may have misunderstood.  When
you say you "pushed explicitly" the objects onto the root stack, do you
mean "explicitly" in the sense of doing this in user code, or in the
sense of having the interpreter do it?  In Scheme and other Lisps this
job is handled automatically by the interpreter, so the user doesn't
have to think about it.  Maybe that's what you meant.

This problem of needing to be able to find roots just might be the most
subtle aspect of Lisp implementation design, and the one with the most
pervasive effects, in the sense that you have to set up certain
conventions you will follow and then make sure they are adhered to
throughout the system.  Do not despair.  The problem really is as hard
as it looks, but it has also been solved numerous times and in numerous
ways.

-- Scott