Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News lua.vm.js – Running Lua VM in a JavaScript VM

lua.vm.js – Running Lua VM in a JavaScript VM

Leia em Português

This item in japanese

Lire ce contenu en français

Mozilla is showing off the strength of asm.js by running the entire Lua VM in a JavaScript VM, with the ability to call JS code.

lua.vm.js is a project started by Alon Zakai, a researcher for Mozilla working on Emscripten and asm.js, meant to show the possibility to run an entire virtual machine including garbage collection, in this case Lua VM, in a JavaScript VM. The Lua VM is written in pure ANSI C, so it became a good candidate for compilation “out of the box” into asm.js with Emscripten, “with only a few minor Makefile tweaks,” according to Zakai.

There is even a REPL for testing Lua code in the browser. Besides running pure Lua code, the REPL shows that one can call JavaScript code, interacting with the DOM, or setting up callbacks, by getting hold of the object, as show in the following example:

print('hello' .. ' ' .. 'world!') -- This is Lua!

print('[0,1,2,3,4,5][3]')) -- Run JS from Lua

-- Interact with the page using Lua

local screen =
print("you haz " .. (screen.width*screen.height) .. " pixels")

local window = -- global object in JS is the window
window.alert("hello from lua!")
window.setTimeout(function() print('hello from lua callback') end, 2500)

local document =
print("this window has title '" .. document.title .. "'")

One of the important aspects of running a VM in another VM is performance, and in this case benchmark tests indicate 50% of the native code, which is on par with other C code compiled to asm.js, and good enough for certain scenarios according to Zakai:

That is too much [performance too low] for some uses cases, but certainly acceptable for others. In particular, remember that the Lua VM is often significantly faster than other dynamic languages like Python and Ruby. These languages are useful in many cases even if they are not super-fast.

Another issue is the size of the library, which in this case is surprisingly small at 200KB g-zipped.

There are some other difficult problems to deal with when running a VM in another VM, as mentioned by Zakai:

There are however some tricky issues, for example we can't do cross-VM cycle collection - if a Lua object and a JavaScript object are both not referred to by anything, but do refer to each other, then to be able to free them we would need to be able to traverse the entire heap on both sides, and basically do our own garbage collection in place of the browser's - for normal JavaScript objects, not just a new type of objects like Lua ones. JavaScript engines don't let us do that, for a combination of security and performance reasons. What we can do is allow Lua to hold strong references into the JavaScript world, and automatically free those when Lua GCs such a reference. That limits things, but it's important to remember that cross-VM cycle collection is a hard problem in CS in general - the only easy case is when one VM's objects can be implemented entirely in the other, but that isn't possible in most cases (and not in this one: for example, some Lua objects can have finalizers - __gc - that can't be implemented in JavaScript) and even when it is, performance is a concern. But note that this type of problem would also be present if we shipped two separate VMs in web browsers.

This project does not seem to be an indication of Mozilla’s desire to be able to run other VMs in the browser, but rather to show the power of Emscripten and asm.js, which currently are in a race head-to-head with Google PNaCl, another attempt to run native code in the browser. (Mode details can be found in this InfoQ post: Debate: Do We Need a Universal Web Bytecode?)

The problem with both asm.js and PNaCl is that none is supported by other browsers. Theoretically, Chrome can run asm.js code, but the performance is rather poor. For example, Lua VM benchmarks run on Chrome at less than 30% the performance on Firefox Nightly, which is 50% of the native. As it is, nobody will run asm.js in Chrome unless Google optimizes their browser for Firefox’s solution for native code. It may all come down to browser market share and the ability to improve the performance of their respective solutions.

Rate this Article