Herewith are some brief notes on garbage collection, current on 2012-07-16:

Right now cowjac has no garbage collection (which means garbage accrues indefinitely), but most of the hooks are in place for some. Actually adding a simple mark/sweep collector should be easy.

The basic setup is:

  • A manual chain of stackframes is maintained by the compiler, so whenever a method is called, a new stackframe object is allocated (on the stack) and added to the chain. Whenever a reference-like local variable is modified, a copy gets stored in this object.
  • A manual list of root objects is also maintained (via ContainsGlobalReferences). Each thread's root stackframe is one of these.
  • All objects that contain references implement a mark() which recursively marks all contained references (if not already marked). Stackframes count here: when a stackframe is marked it marks its reference-like locals and then calls mark() on the next frame on the stack.
  • A third list of all allocated objects is maintained by the root object constructor and destructor.
  • Objects may be marked, and may be immutable.

In order to do a collection, then, all we need to do is:

  • Stop all threads at a safe point. (How to be determined later.)
  • Traverse the list of all objects and clear the mark.
  • Traverse the list and mark all immutable objects.
  • Traverse the list of roots and mark all references recursively. (Including stackframes.)
  • Now, any object which is not marked is garbage, so traverse the list again and delete it.
  • Resume threads.

This is a stop-the-world collector, and is not necessarily that efficient. But it should be simple to implement, reasonably easy to debug, and may stand a chance of working.

Note that there a couple of places in cowjac where live references aren't anchored: exceptions in flight, for example. This imposes certain constraints on what we can do. These can probably all be fixed later, but for now this approach should be fine.

Previous page