asm.js in Firefox Nightly

I’m happy to announce that OdinMonkey, an asm.js optimization module for Firefox’s JavaScript engine, is now in Nightly builds and will ship with Firefox 22 in June.

What is asm.js? Why are we doing it, and how are we getting to within 2x of native performance? This post won’t be able to go into too much detail since we’re hard at work preparing for Mozilla’s upcoming GDC session, which you should definitely come see (Wednesday 11am, Room 3024, West Hall). After GDC, expect full coverage of these topics by Alon, Dave, myself and surely others. For now, allow me to point you at the asm.js FAQ, Alon’s mloc.js slides, a nice Badass JavaScript post and a more in-depth post by Axel Rauschmayer.

Want to see it in action? Download a new Firefox Nightly build and try out BananaBench. (Note: BananaBench runs with a fixed time step to make JS execution deterministic, so game speed will run fast/slow, depending on your hardware/browser.) Or, check out a demo of the Emscripten-compiled Bullet engine simulating a ton of falling boxes.

At the moment, we have x86/x64 support on desktop Windows/Mac/Linux and support for mobile Firefox on ARM is almost done. Since we intend to continue to iterate on the asm.js spec in cooperation with other JS engines, we’ve put OdinMonkey behind the flag javascript.options.asmjs in about:config. This flag is currently enabled by default on Nightly and Aurora, and if nothing changes over the next 12 weeks, will be automatically disabled in Beta and Release. By then, we hope to be happy with a stable “asm.js v.1″, we’ll enable it everywhere and ship with it enabled in our final builds. [Update: OdinMonkey has been enabled by default for all releases starting with Firefox 22.]

If you want to start experimenting with asm.js right now, you can:

  • Get Emscripten and start compiling C/C++ code. (Don’t forget the -O2 -s ASM_JS=1.)
  • Check out the draft spec and start writing asm.js by hand.

In the future, we’d like to see a rich third option of generating asm.js using a more ergonomic front-end language (e.g., a derivative of LLJS). [Update: LLJS work is already underway!]

How do you know if you are generating valid asm.js and taking full advantage of OdinMonkey? In the old days, this was a frustrating question for developers. Maybe you were doing something wrong, maybe the code, as written, was just slow. One cool thing about asm.js is that the "use asm" directive makes the programmer’s intention quite clear: they want to compile asm.js. Thus, if there is an asm.js validation error, OdinMonkey will print a warning on the JavaScript console. (OdinMonkey emits a warning, instead of throwing an error, since asm.js is just JavaScript and thus cannot change JavaScript semantics.) In fact, since silence is ambiguous, OdinMonkey also prints a message on successful compilation of asm.js. (There is currently a bug preventing asm.js optimization and warnings in Scratchpad and the Web Console, so for now experiment in regular content.)

For those who are itching to do some performance experiments: go for it, we’ve been pretty happy with the results so far when asm.js is applied to new codes, but we’ve also seen plenty of cases where the C++ compiler is doing important backend optimizations that we haven’t taught our IonMonkey backend yet. We expect continuous incremental improvement as we measure and implement new optimizations to close this gap. Second: one performance fault that we already know trips up people trying to benchmark asm.js is that calling from non-asm.js into asm.js and vice versa is much slower than normal calls due to general-purpose enter/exit routines. We plan to fix this in the next few months but, in the meantime, for benchmarking purposes, try to keep the whole computation happening inside a single asm.js module, not calling in and out.

In closing, I leave you with the musical inspiration for OdinMonkey:

Happy hacking!