Hacker News new | ask | show | jobs
by rurban 3390 days ago
> In Evan’s keynote, he proposed a really interesting and ambitious solution to the problem he called “lifting the core.” It involved shipping Ruby with LLVM intermediate representation of the CRuby functions to allow the LLVM JIT technology to look inside the CRuby functions and dramatically increase the optimization horizon. As far as I know, this hasn’t been attempted yet — although, if it has, I really want to see it!

Actually unladen_swallow and cperl are doing this. Compile the whole runtime to a lib<rt>.bc (trivial make rule), load this bitcode file (a single call), and add the expensive optimizations, esp. the inliner and IPO in llvm. Just the type-checks need to be done in the jit. This inliner does a lot of good magic esp. for the small RT functions. >10x faster.

The compiler is expensive though (i.e. very slow), and LLVM changed it's jit API 3 times already. <=3.4 jit, then mcjit and >= 3.6 ocrjit, all 3 of them still having major quirks.

With mcjit you cannot selectively add jit code to a module. So every single body needs to be a new module. So module != package/class/namespace. So the jitcache is a bit complicated. With the latest ocrjit you got problems in finding the symbols in the bc. The C API doesn't support the name resolver at all, and it's a major quirks with C++. LLVM's C API is really behind, but at least they don't change it that often as the C++ API.

unladen_swallow has a huge JIT overhead library, which nobody really needs.

For the cperl jit I just used 4 days so far and doesn't even link yet. I used the C API, not the better C++ API. No C++ for cperl. But it's very simple. https://github.com/perl11/cperl/blob/feature/gh220-llvmjit/j...

3 comments

On the GNU side there is https://www.gnu.org/software/libjit/ that could presumably be used, but that's GPLv3 and would have consequences
Na, all those abstract jit libraries suck. They are too abstract and thereby failed to support the needed architectures.

Practically usable are only LLVM and dynasm.

Now the orm guys did something special I appreciate a lot. Basically they re-invented parrot, with a proper, fast object system with compile-time class extensions in C++, plus still supporting run-time inheritance via vtables. And on top of their existing stable jit engine for java, they started targeting ruby and python (unofficially).

Much better than parrot (which I'm maintaining on life-support), and probably also better than rpython. We will see how this will turn out, as they already have truffle, which don't like that much. orm looks much better to me.

Yes, libraries like libjit help you to emit a low level program, but that was never the problem anyone had.

The problem is turning Ruby into a low level program in the first place.

Wow I had no idea anyone was shipping bitcode of their runtime for dynamic compilation. Are there any blog posts, papers, etc about it? Does it work well?
Nope, just one page of code. unladen swallow should have some papers, but I found out after studying their code.

Both are not working well. unladen swallow, because of incredible bloat and overhead. cperl, because it's not done yet. Just 4 days so far :) And supporting the 3 LLVM jits is awkward. I'll better decide on only one and add the llvm version as fixed requirement. MCJIT sounds best so far, when storing the jit'ed bodies for all subs in a module in extra files does not kill all the performance. v8 went without that cache, java with. With a jit cache you can easily pre-compile/warmup your stdlib and do more expensive optimizations beforehand. LLVM is really slow.

impala does.
The impala bitcode reader/resolver is here: https://github.com/cloudera/Impala/blob/cdh5-trunk/be/src/co...

It also needs a special mcjit resolver: https://github.com/cloudera/Impala/blob/cdh5-trunk/be/src/co...

Thanks so much for posting this! That was exactly what I was curious about!