Exploring Speculative JIT Compilation for Emacs Lisp with Java
26 points by kana
26 points by kana
Here for the homegrown Truffle interpreter, which is awesome. I really think Truffle could become to interpreters what tree-sitter is to parsers. How difficult was it to write? How much time did you spend staring at compilation graphs in Ideal Graph Visualizer? Did you get deep in the weeds with all the different JIT annotations or did only a few suffice? Did you make much use of the DSL for codegen?
I would be very hesitant as a hobbyist language author to bet on a very-engineered Java solution developed by Oracle, possibly the least appreciated company in the whole open-source ecosystem. Graal/Truffle may be technically impressive, but it almost seems like no one who isn't funded by Oracle is willing to touch it.
(Well, Pypy also looks promising, does not have any of the Oracle reputation sink, and yet does not seem to be spreading like wildfire among language-implementation enthusiasts. Maybe it's just that speculative JITs are way too complex and people stick to approaches that are conceptually simpler.)
I actually did not know Pypy is intended as a framework for general language implementation, that is interesting!
Technically RPython is the interpreter-generic JIT machinery below PyPy (which is a specific instance of usage of RPython to implement Python; it is also the only widely-used one, so RPython is mostly specialized to Pypy's needs). There has been some experiments using RPython for other languages, see for example Pycket.
You might find this Nix flake to be interesting; I've packaged quite a few RPython projects, mostly for my own personal purposes.
There are three high-quality JIT toolkits available for FLOSS folks: GNU Lightning, RPython, and Truffle. However, friends don't let friends expose themselves to legal risk from Oracle, so it's really a choice between GNU Lightning and RPython.
Thanks! It's been about a year and a few months since I started working on Juicemacs, though most of that time was actually spent implementing Emacs built-in functions rather than the interpreter itself, and the core interpreters took several months of intermittent work. I'd say it's not that hard to write, but the problem is that Truffle does not have that many tutorials or troubleshotting documentation, and you're on your own once something goes wrong. I used IGV occasionally rather than extensively - I remember jacoco coverage causing headaches (it adds Java bytecode that confuses Truffle, producing huge graphs) and debugging recursive calls (which gets easier once you realize you need to find the repeating parts, which usually just span the whole graph). I also have a PMD rule file tracking common pitfalls. But native images have been a life-saver with much clearer error messages, and I don't remember opening up IGV ever since I start building native images in CI. (And my advice for anyone starting out: use native images early.)
The JIT annotations I use are mostly just @CompilationFinal and @ExplodeLoop. There are other annotations but I think you will only use those in very few nodes. As for codegen annotations (DSL), I think my usage mostly follows their documentation (and error messages) and is not that different from some of tutorials online. The @GenerateNodeFactory annotation has been incredibly helpful though, automatically generating huge lists of implemented built-in functions/nodes.
On the tree-sitter comparison, I partially disagree mainly because Truffle/Graal's "sea of nodes" approach does bring some memory overhead that many people care about. (There's auxiliary engine caching, which is not available in the community edition, and I have no idea if that helps.)
Love the article but I have a complaint about the website: the background image keeps making me think there's dirt on my monitor. I had to open the FF dev tools and delete the background-image CSS rule.
Speculation is fun for jits, but wouldnt it be possible to employ a typechecker for elisp and compile fitting functions to machine code?
At least for Truffle, supposedly you get this for free without having to write a typechecker. The promise of Truffle is "write a treewalk interpreter and get bytecode interpreter speed". For dynamically-typed languages it largely handles all the tricky runtime type specialization stuff for you.