I have a confession to make. It’s not the easiest one and it took me more than a month to get myself together for it.
I am madly in love with an oyster!
No wait, that’s not it.
I am madly in love with nonsense.
Yeah, that’s what I wanted to say. If you ever met me in person then you probably know that I have an unhealthy tendency to say random things that pop into my head. Interestingly enough I like to do the same when I talk to the Machine: I like to wildly crank out random nonsensical code as if I were a quantum superposition of infinitely many monkeys equipped with keyboards and tasked with producing Shakespeare’s sonnets hidden in C++ metaprograms.
Why am I saying all this? Well… “What was your talk about?” This probably is the most common question I am getting about my JSConf EU 2012 talk. And the truth is…
I ain’t got no freaking idea!
‹slides›
No, seriously. What was this all about?
There were actually two themes that I shook but did not stir in this talk. The first one is observability of JavaScript VM innards from inside the JavaScript itself. The second one is implementation of JavaScript VM in JavaScript. Both unified by the same grand idea: when developing a virtual machine for the language XYZ do as much as possible in XYZ itself.
I really do believe that self hosting big portions of the VM improves its maintainability, extensibility, portability and even performance characteristics.
Observability
It is not a secret that modern JavaScript VM while very sophisticated and quite performant lack user friendly tools to look deep into VMs and appropriately tune application code when performance becomes a priority. Browsers’ best offering at the moment seems to consist of a sampling profiler and a collection of undocumented debug flags (some requiring you to rebuild a browser from source).
In the lack of tooling performance tuning often is reduced to cargo cult of just writing JavaScript like C.
During my time on the V8 team I had to investigate quite a number of performance issues in the real world code and my inability to interactively observe what V8 is doing under the hood was always causing certain pain and frustration. And this is given my knowledge of V8’s implementation and all kinds of tracing flags that cause V8 to dump a lot of information about its decisions.
Those flags, while very helpful, exist in separation. There is no unifying “dashboard”. Debugging output requires manual cross-referencing, which is kinda 1699-ish. This output is all about the past (it states what happened) but it does not tell you what is the state of things here and now. It is not interactive.
In attempts to relieve this pain I (randomly) played with many different approaches, some presented in my talk. Unfortunately my prototypes never became complete enough to be useful for someone except me. Nevertheless I decided to show some of those to make people interested, to make both JavaScript developers and browser engineers think of what they are lacking.
I wanted everybody to feel that vacuum and antiquity of existing tools and that’s about it for the first part of my talk.
Hackability
I have this crazy idea that if you need to understand something you need to do it yourself.
Want understand how JIT compiler works? Don’t just read stuff on the net. Not even sources are enough! Take your laptop, cup of chamomile tea and implement one. Or at least take some and hack its socks off.
Surely not everybody has time to hack on VMs in C++ so don’t limit yourself. Like JavaScript? Do it in JavaScript then!
The idea here is to have some fun and learn at the same time. Playing is the only way of learning when we are kids. I don’t see why we should abandon it when we are becoming older… Just replace colorful alphabet cubes with assembly instructions. Those are equally fun.
All these ideas combined lead to a couple of small projects that I’ve decided to open source.
mö.js — source code
In its core this project is not groundbreaking. It’s just about taking well known concepts from other VMs and reimplementing them in pure JavaScript.
There are other more complete VMs implemented in JavaScript (e.g. Tachyon). However the idea of mö.js is different: it does not try to be a full VM (at least not yet), it’s a toy that exists solely for educational purposes. I want to take interesting VM concepts and decompose them into digestible pieces. I also want to learn something new myself.
That is why I choose to implement largely LuaJIT2 inspired tracing compiler instead of a classical method based JIT like V8. Because I have never done a tracing compiler before I just wanted to have some fun implementing one.
On the other side you can also see that mö.js also contains IC code that I have written for an older blog post of mine. I hope that mö.js will continue to grow as I am traveling in through the world of VMs and play with different approaches.
[Though I am even less sure now that I really want to do it in JavaScript. Oh well...]
Finally, answering some questions: mö.js is named after Möbius Strip — a surface with only one side. It refers to the idea that VM should have only a single side, to avoid C++ on the inside vs. JavaScript on the outside dichotomy.
node-llvm — source code
Quite some time ago I played a bit with an idea of hosting a statically typed language with a LLVM based compiler inside node.js.
I never actually finished implementing the language but I produced somewhat working LLVM bindings for node.js. These bindings came in handy when I decided to generate a bit of native code by mö.js’s tracing compiler.
The idea here was that LLVM backend would produce the code that would access V8’s heap directly just like code emitted by JavaScript backend does.
All gory details I decided to hide in a small module called Meldo that actually does the evil job of messing with V8 heap directly and not through the standard V8 API. My hope was that it can eventually become a well documented module that other people can employ when they are either curious or just trying to win some milliseconds through the use of the Dark Side of the Force. This hope did not materialize yet, because I never got enough time to clean things up and thoroughly document it. So I am releasing it as is like a proof of concept.
Another issue here is that I can’t publish node-llvm
in the npm
yet because it depends on a custom binding generator kharon which in turn depends on libclang bindings that are API incompatible with libclang
package available on npm
. Basically it is Issue 1 that I discovered during open sourcing today :-)
Thus unfortunately for now the only way to try node-llvm
is to clone git repository and install it piece by piece manually.
git clone https://code.google.com/p/node-llvm/
npm install $node-llvm-dir/kharon/node-libclang
npm install $node-llvm-dir/
npm install $node-llvm-dir/examples/meldo
[Obviously one also needs to checkout and build LLVM and Clang as described in their wiki]