This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Precise GC



There was some talk a while back about why precise GC was too hard in a C
environment.
I thought I might show people how I did it in a little scheme I wrote a
while back. It's pretty simple
and pretty easy to use, but I'll let people more expert comment on it. You
_don't_ have to use a
special macro  to assign objects around.

In a header file I put these definitions...
#define s_beginGcArea() int s_gcStackPos = s_gcContext.cStack.pos
#define s_prepGc(v) pushStackAutoResize(&s_gcContext.cStack, &(v))
#define s_defGc(type, name, init) type name = (type)(s_prepGc(name), init)
#define s_endGcArea() popStackTo(&s_gcContext.cStack, s_gcStackPos)


Now when I want to write a C function called from Scheme I do something
like...

s_String * s_newString(int len)
    {
    s_beginGcArea();
    s_defGc(s_String *, rtn, s_unspec_obj);

    rtn = s_allocType(String);
    rtn->str = (char *)malloc(len + 1);
    rtn->str[len] = EOS;
    rtn->length = s_newExactNum(len);
    s_endGcArea();
    return rtn;
    }

The basic idea is that s_beginGcArea() marks a point in the stack where we
entered
the function. s_defGc defines a C pointer which is subject to GC tracing.
Arg1 is C type,
arg 2 is the name of the variable, and arg3 is a value to initialise it to.

s_endGcArea() tells the system to unmark all the stack variables between
the
beginGcArea() and here.

rtn->length is also a scheme object, but we don't have to do anything
special because
the GC can trace it via rtn, which the GC knows about.

Is something like this so hard to use that it is not worth implementing
precise GC? Is there
something about it not portable?

This is the definition of s_gcContext in case it helps understanding...

typedef struct
    {
    Stack progress;
    Stack cStack;
    int state;
    /* markHeap */
    int hashIndex;
    /* markStack */
    int stackIndex;
    /* markCStack */
    int cstackIndex;
    /* sweep */
    Vector items;
    int nextpos;
    } s_GcContext;