Developer: 1; Garbage Collector: 0
However, I've beaten this one, and the M2VM garbage collector is working again. Found a number of oversights in my implementation; I knew the initial mark-compact collector was a stopgap measure, and boy, did I write it like a stopgap measure. :-)
I've also gained a real appreciation for gdb. At some point in the last few years, it's learned to reload single functions from a modified binary on the fly, as well as dynamically reloading and relinking shared libraries. I can switch windows, recompile my GC, rebind the entry point, and resume execution. Pretty sweet. (These might be Apple-specific enhancements, not sure.)
So, the GC is creeping right along — emphasis on the creeping. Like any naïve mark-compact collector, it causes nasty pauses — as much as 1s on a 40MB heap. Hand it a heavily fragmented 1GB heap, and not even my 2.5GHz G5 can make the experience pleasant.
I've found some creative ways to optimize it, but it raises the question of how much to tune throwaway code.
Update: corrected "mark-sweep" to say "mark-compact." I had actually forgotten that non-moving tracing collectors existed.
Update 2: in answer to my final question, I modified the mark-compact collector to use a simple generational strategy. Work required: 2 lines of code. Speedup: 100x.