memory allocation

kaffe@rufus.w3.org kaffe@rufus.w3.org
Thu, 18 May 2000 16:04:08 +0100 (BST)


Johan Andersson wrote:
> I am trying to figure how Kaffe allocates memory using Linux on an i386.
> 
> I found this in gc.h :
> 
> 
> struct GarbageCollectorInterface_Ops {
> ...
>      void* (*malloc)(Collector *, size_t size, int type);
>      void* (*realloc)(Collector *, void* addr, size_t size, int type);
> ...
> }


The allocation code is complicated (to me, at least).  Still, it has
there a certain involuted charm.  The following isn't anything like a
complete description but, if nothing else, it should indicate which
bits of code to look at.


Userland calls
==============

The main allocation calls are jmalloc() and gc_malloc().  They're used
for different things, but in fact they're thin wrappers around the
(*malloc) you mention above.  jmalloc is a function defined in gc.c;
gc_malloc is a macro defined in gc.h.

jmalloc() is for C-style allocation.  Its semantics are exactly those
of the normal C malloc() [right?].  Objects allocated with jmalloc()
are not subject to garbage collection, and are never moved or
interfered with.  They must be deallocated with jfree().  
[Note: KMALLOC() is a synonym for jmalloc().]

gc_malloc is used to allocate Java objects.  These are then subject to
the operations of the garbage collector, which will deallocate them
when they're no longer in use.  [Some collectors may also alter or
move objects.  The current collector does not, but please don't assume
that.]


Exporting the interface
=======================

The GC mechanism is designed (I think) to allow multiple collectors,
but at the moment only one collector is supported.

As you've seen, all the collector's operations go through a single
struct GarbageCollectorInterface_Ops.  The actual GC structure is set
up -statically- in mem/gc-incremental.c, and all its members are
static functions in the same file.  (The main Collector structure is
tucked inside `gc_obj' at the top of the file; its component
`Interface_Ops' struct (the interesting bit) is down at the bottom.
And, of course, neither of them are directly accessible from outside
the file.)

The outside world accesses the collector through main_collector, a
pointer in gc.c.  Somehow, main_collector has to be made to point to
the GC structure.  This is done during initialiseKaffe() via the
following call stack.  Note that createGC() is within the (static)
scope of the GC structure:

 1.  createGC()         (gc-incremental.c)
 2.  initCollector()    (gcFuncs.c)
 3.  initialiseKaffe()  (baseClasses.c).


An example allocation
=====================

Say you want to allocate a 32-byte Java instance object.  You do the
following:

    gc_malloc(32, GC_ALLOC_NORMALOBJECT)

With a couple of macro substitutions (see gc.h), that becomes:

    main_collector->ops->malloc(main_collector, 32, GC_ALLOC_NORMALOBJECT)

main_collector points to `gc_obj.collector' (mem/gc-incremental.c),
whose member `ops' points to `GC_Ops' (gc-incremental.c), whose member
`malloc' points to the static function gcMalloc() in gc-incremental.c.
And gcMalloc() does the work.

One of these days I'll understand it.


			     *    *    *


If you're puzzled by the meaning of GC_ALLOC_*, have a look at the
following:

   GC_ALLOC_*             (gc.h)
   initCollector()        (gcFuncs.c)
   registerTypeByIndex()  (mem/gc-incremental.c)
   gcFunctions            (mem/gc-incremental.c)

... but I won't explain further because the GC_ALLOC_* types are
mostly to do with garbage collection, which is outside the literal
scope of your question.



-- D.

David Hughes
Department of Computer Science, University of Exeter, UK

         We burn so hard, but we shed so little light;
         it makes us crazy and sad.
                                      -- Clive Barker, 'Galilee'