#include "SchemeObject.h" #include "defs.h" //#include "debug.h" SchemeObject maybe_garbage, not_garbage, not_garbage_end, wait_list, roots, queue_pos; BOOL markstate; typedef enum { GC_IDLE = 0, GC_MARK = 1, GC_SWEEP = 2 } gc_state_e; gc_state_e gc_state; integer checkpoint; #define GC_AMOUNT 200 @implementation SchemeObject + (void) initialize { maybe_garbage = not_garbage = not_garbage_end = wait_list = roots = NIL; markstate = true; gc_state = GC_IDLE; checkpoint = 0; } + (id) dummyObject { return [[SchemeObject alloc] initDummy]; } - (id) initDummy { self = [super init]; prev = next = NIL; marked = markstate; root = false; return self; } + (void) collectCheckPoint { if (checkpoint >= GC_AMOUNT) { [self collect]; checkpoint = 0; } } + (void) collect { local SchemeObject cur; local integer amount; switch (gc_state) { case GC_IDLE: dprintf("GC: Starting collection...\n"); gc_state = GC_MARK; not_garbage = not_garbage_end = [SchemeObject dummyObject]; for (cur = roots; cur; cur = cur.next) { [cur markReachable]; } queue_pos = not_garbage_end; return; case GC_MARK: dprintf("GC: Marking...\n"); amount = 0; while (queue_pos) { dprintf("GC: marking queue: %s[%s]@%i\n", [queue_pos description], [queue_pos printForm], (integer) queue_pos); [queue_pos markReachable]; queue_pos = queue_pos.prev; if (++amount >= GC_AMOUNT/2) return; } dprintf("MARKED: %i reachable objects\n", amount); gc_state = GC_SWEEP; queue_pos = maybe_garbage; return; case GC_SWEEP: dprintf("GC: Sweeping...\n"); amount = 0; while (queue_pos) { dprintf("GC: freeing %s[%s]@%i...\n", [queue_pos description], [queue_pos printForm], (integer) queue_pos); [queue_pos release]; queue_pos = queue_pos.next; //if (++amount == GC_AMOUNT) return; } maybe_garbage = not_garbage; not_garbage_end.next = wait_list; if (wait_list) { wait_list.prev = not_garbage_end; } wait_list = NIL; not_garbage_end = NIL; not_garbage = NIL; markstate = !markstate; gc_state = GC_IDLE; } } + (void) finishCollecting { while (gc_state) { [self collect]; } } - (id) init { self = [super init]; if (gc_state) { if (wait_list) { wait_list.prev = self; } next = wait_list; wait_list = self; marked = markstate; dprintf("GC: During collect: %i\n", (integer) self); } else { if (maybe_garbage) { maybe_garbage.prev = self; } next = maybe_garbage; maybe_garbage = self; marked = !markstate; dprintf("GC: Not during collect: %i\n", (integer) self); } prev = NIL; root = false; checkpoint++; return self; } - (void) mark { if (!root && marked != markstate) { dprintf("GC: Marking %s[%s]@%i\n", [self description], [self printForm], (integer) self); marked = markstate; if (prev) { prev.next = next; } else { maybe_garbage = next; } if (next) { next.prev = prev; } if (not_garbage) { not_garbage.prev = self; } next = not_garbage; prev = NIL; not_garbage = self; } } - (void) makeRootCell { if (root) return; if (gc_state) { dprintf("Root cell made during collection!\n"); [SchemeObject finishCollecting]; } if (prev) { prev.next = next; } else { maybe_garbage = next; } if (next) { next.prev = prev; } if (roots) { roots.prev = self; } next = roots; prev = NIL; roots = self; root = true; } - (void) markReachable { return; } - (string) printForm { return ""; } - (void) dealloc { dprintf("Deallocing %s @ %i!\n", [self description], (integer) self); [super dealloc]; } - (BOOL) isError { return false; } - (string) source { return source; } - (void) source: (string) s { source = s; } - (integer) line { return line; } - (void) line: (integer) l { line = l; } @end