A Trace-based Just-in-time Compiler for Haskell
Did you ever wonder why GHC didn’t optimise away that one dictionary lookup inside your critical loop? Couldn’t get GHC to inline just the right amount without blowing up compilation time or code size? Got confused why fusion didn’t happen? Got annoyed that you had to recompile all your libraries just to turn on profiling?
All these are problems because GHC is a static compiler. To explore whether these problems can be fixed by performing optimisations at runtime I implemented Lambdachine, a prototype trace-based just-in-time (JIT) compiler for Haskell. A JIT compiler knows where a program spends most of its time and optimises those parts aggressively. A trace-based JIT compiler (as used by Dalvik and LuaJIT 2) is naturally interprocedural, has a short warm-up period, and short compilation pauses. It also fits well with Haskell’s execution model. Lambdachine uses GHC as a front-end, thus we could potentially take advantage of both static and dynamic optimisations.
I will give a short demo and discuss what works well and what doesn’t work so well in a trace-based JIT compiler.