Fascinating stuff. As far as the efficiency issues of tracing JIT go, I've been pondering the idea, and I wonder if it might be useful to have a combination of "method JIT" and tracing?
To wit, the system starts by creating compiled (but not necessarily highly optimized) versions of the functions, and then traces their execution and creates "trace-optimized" versions for common paths. This way, when the traced condition fails, you don't have to drop down to interpretation: you still have compiled code. It's just not as fast as the traced path.