The only thing that really bugs me is that the GC has imposed a serious performance hit on the raytracer - to the tune of halving its old performance. I still need to do a full release build of the runtime to make sure I can't improve on that any, but I suspect the GC root spilling in LLVM is taking a toll on optimization passes. I might need to work on improving the front-end of the compiler to generate more optimal code in the first place so that I don't have to spill so many registers onto the stack all the time.
It'll take some analysis and study of the emitted machine code, but I'm optimistic about being able to reclaim at least some of the performance.
If nothing else, this is a good motivation for introducing a "manually reclaimed" semantic to object allocations in Epoch, so programs that don't want to incur GC overhead can bypass it entirely.
[As I wrote this, I kept alt-tabbing over to Visual Studio and mucking around. I managed to suppress garbage collection invocation for a large percentage of functions, which got me back to 21FPS - compared to 24FPS previously. I'm happy.]