We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Pros and Cons

To solve our cyclic reference issue (and to force you to implement another GC algorithm, HA!) we're going to implement a Mark and Sweep garbage collector.

Pros of MaS

  • Can detect cycles, and thus prevent memory leaks in certain cases
  • Less on-demand bookkeeping (Remember: all work done by the GC is "wasted" – it doesn't make your GPT-4 wrapper custom AI product run any faster)
  • Reduces potential performance degradation in highly multithreaded programs (refcounting requires atomic updates for thread safety)

Cons of MaS

  • More complex to implement (heh, you'll see)
  • Can cause "stop-the-world" pauses when lots of objects exist and must be freed (resulting in poor performance)
  • Higher memory overhead
  • Less predictable performance

Assignment

We'll be using a vm_t struct which stands for Virtual Machine Type. This vm_t simulates what would normally be tracked if Sneklang were a fully functional interpreted language (it's not). This virtual machine is much simpler than a real one because all we care about is demonstrating the garbage collection aspects.

You can spam Lane if you want a full "write your own programming language" course on boot.dev

Please don't. I have a wife and kids.

Open vm.h and take a look at the vm_t struct. The frames field holds a stack of frames, which are pushed and popped as we enter and exit new scopes. For example:

msg1 = "This is in scope 1"


def outer_func():
    msg2 = "This is in scope 2"

    def inner_func():
        msg3 = "This is in scope 3"
        return

    return

At each of the scope entrances (in this case function calls), a new stack frame is pushed onto the frames stack. When we exit a scope (a function returns), we pop the stack frame off the frames stack. Because we use void * to work with generics in C, you can't actually tell what the data type held by the stack_t is for each field. We'll write some wrapper functions later to help us make sure that we don't accidentally push the wrong kinds of data into our stacks (yay, C!).

The objects field is also a stack, but it holds snek_object_t pointers.