MozillaはJavaScript VMで完全なLua VMを動かすことで、asm.jsのパワーを見せつけた。Lua VMからJavaScriptコードを呼び出すこともできる。
lua.vm.jsは、Emscriptenとasm.jsに取り組んでいるMozillaのリサーチャー、Alon Zakai氏がはじめたプロジェクトだ。このプロジェクトの目的は、JavaScript VMでガベージコレクションを含んだ完全な仮想マシン(この場合Lua VM)を動かせることを見せることにある。Lua VMは純粋なANSI Cで書かれているため、Emscriptenを使って「そのまま」asm.jsにコンパイルするのに適していた。Zakai氏によると「Makefileをわずかに変更するだけ」だったそうだ。
ブラウザでLuaコードをテストするREPLもある。純粋なLuaコードの実行だけでなく、js.globalオブジェクトを介して、JavaScriptコードを呼び出し、DOMとやりとりしたり、コールバックをセットすることもできる。
print('hello' .. ' ' .. 'world!') -- This is Lua!
print(js.run('[0,1,2,3,4,5][3]')) -- Run JS from Lua
-- Interact with the page using Lua
local screen = js.global.screen
print("you haz " .. (screen.width*screen.height) .. " pixels")local window = js.global -- global object in JS is the window
window.alert("hello from lua!")
window.setTimeout(function() print('hello from lua callback') end, 2500)local document = js.global.document
print("this window has title '" .. document.title .. "'")
VMでVMを動かす上で重要なのは、パフォーマンスだ。ベンチマークテストによると、ネイティブコードの50%ほどであり、asm.jsにコンパイルしたほかのCコードに匹敵する。Zakai氏によると、これで十分なシナリオもあると言う。
これだと遅すぎるユースケースもありますが、許容できるユースケースもあります。たいていの場合、Lua VMはPythonやRubyなどの動的言語と比べて、かなり高速です。たとえ超高速とは言えなくても、これらの言語は多くのケースで役に立ちます。
もうひとつ問題になるのは、ライブラリのサイズだ。この場合、gzipして200KBとかなり小さい。
Zakai氏が話しているように、他にも難しい問題がある。
やっかいな問題があります。たとえば、VM横断での循環参照のコレクション (cycle collection) はできません。LuaオブジェクトとJavaScriptオブジェクトが他から参照されずに相互参照している場合、解放するためにはLuaとJavaScriptの両方のヒープを完全にトラバースできなくてはなりません。ブラウザの通常のJavaScriptオブジェクトのためのGCに代わって、Luaのような新しいオブジェクトの世話もしてくれる独自のGCが必要になるでしょう。JavaScriptエンジンは、セキュリティとパフォーマンスのため、それをさせてくれません。できることと言えば、LuaにJavaScriptの世界への強い参照を持たせて、Luaがそうした参照をGCするときに自動で解放することぐらいです。これには制限がありますが、VM横断の循環参照のコレクションというのは一般的に難しい問題であることを忘れないでください。唯一簡単なケースは、あるVMのオブジェクトが完全に別のVMで実装できる場合ですが、それはまず不可能ですし(たとえば、Luaオブジェクトは__gcというファイナライザを持つことができます。これはJavaScriptでは実装できません)、できてもパフォーマンスが懸念されます。でも、こうした問題は、Webブラウザに2つのVMを搭載した場合にも起こることです。
Mozillaはこのプロジェクトによって、ブラウザで別のVMを動かせるようにしたいわけではなく、Emscriptenとasm.jsのパワーを見せつけたいようだ。彼らは現在、ブラウザでネイティブコードを実行するもう1つの試み、Google PNaClと競っているためだ。(状況について、詳しくはこの記事を参照。ウェブためのユニバーサルなバイトコードは必要か)
asm.jsとPNaClのどちらにもある問題は、他のブラウザでサポートされていないことだ。理論的には、Chromeはasm.jsコードを実行できるが、そのパフォーマンスはかなりひどい。たとえば、Chromeで実行したLua VMベンチマークは、(ネイティブの50%である)Firefox Nightlyの30%以下しかない。GoogleがFirefoxのネイティブコードソリューションに合わせてChromeを最適化しない限り、Chromeでasm.jsを実行する人はいないだろう。結局、ブラウザのマーケットシェアと各ソリューションのパフォーマンス改善次第なのかもしれない。