A short history of frames

Eric W. Biederman ebiederm@cse.unl.edu
Sat, 27 Apr 1996 12:19:54 -0500


Long ago in programming land there was a language called Fortran.  Now
Fortran had this marvelous new concept, you could have functions!  In
those days when Fortran on punch cards was high level programming
nothing was spared for efficiency, not even recursion.  That is
loading a variable off of a stack was more inefficient then a
statically allocated variable, so all vairables were statically
allocated.  To allow variables that were specific to a function
certain areas (frames) were set aside to allow for the local variables
of a function.  In these frames also were set aside places for the
arguments to the function, and it's return address.  Exactly where
return values were stored I don't know but they were highly restricted
anyway.  In all functions the location of frames was statically know.  

In later languages when machines got better at indirect addressing and
people were more concerned with functionality, frames were allocated
upon a stack, to allow for recursion.  Recently since frames upon
stacks has become such a defacto part of life many optimizations have
been introduced to attempt to keep frames, especially their arguments
in registers.

So while C and other languages allocate their frames upon a stack, it
is just a convinience.  They just as well could dynamically allocate
them from a heap, and use malloc and free.  In fact some variants of
lisp actually do use the heap to allow for expressions that can return
multiple times, only the garbage collector knows when it won't happen
again.  

For a garbage collector having a structure with all the variables of a
function is very attractive.  It can then tag that structure as it
would any other object, with garbage collected information.  But this
needs to only be way out at the structure level, instead of having to
tag every cell of memory as to weather or not it's a pointer.  There
is at least one specialized collector for a stack/heap for lisp like
languages that simply collects the stack/heap and not the general
heap, is quite fast, and allows multiple `threads' upon the same it.

The difficulty with integrating all of this into forth is that long
ago forth took a different approach to memory management.  It
implemented a global data stack & a global return stack, and words
that implement them.  In forth there is no telling how much of the
data stack a given word will consume.  It might just consume the whole
data stack, and then return to the caller.  Or perhaps it might
consume upon a rare occasion consume a word from the return stack it
didn't push and then return to lala land.  Now much of this is good in
that you can address completely manipulate the system.  The bad is
that you can easily manipulate things wrong.

One last argument to dispell having a function like printf in C is not
a very good argument in C because only the programmer can properly
construct calls to printf!  In the few languages where you can
actually construct function calls for printf at least it is quite
difficult.  So my question is in a language where the heap is as fast
as the stack, what kind of routines would benefit from variable
arguments and variable return values?

Eric