A Mozilla está mostrando a força do asm.js ao rodar a Lua VM completa em uma VM JavaScript, inclusive com capacidade de invocar código JS. O lua.vm.js é um projeto criado por Alon Zakai, um pesquisador da Mozilla que trabalha nos projetos Emscripten e asm.js. Tem como objetivo tornar possível a execução total da máquina virtual Lua (inclusive com garbage collection) em uma VM JavaScript. A Lua VM é escrita em ANSI C puro, o que a torna boa candidata para compilação no asm.js com Emscripten, "bastando apenas pequenos ajustes no arquivo Makefile", de acordo com Zakai.
A biblioteca é surpreendentemente pequena: 200KB compactada com gzip. Existe também um REPL (read-eval-print loop) para testar o código escrito em Lua diretamente no navegador. Além de rodar o código Lua puro, o REPL mostra que é possível invocar código JavaScript, interagir com o DOM ou configurar callbacks por meio do objeto js.global, como mostrado no exemplo a seguir:
print('hello' .. ' ' .. 'world!') -- Isso é Lua! print(js.run('[0,1,2,3,4,5][3]')) -- Executa JS a partir do código Lua -- Interage com a página usando Lua local screen = js.global.screen print("you haz " .. (screen.width*screen.height) .. " pixels") local window = js.global -- window é o objeto global no JS 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 .. "'")
O desempenho, como de esperar, é um dos aspectos mais importantes ao rodar uma VM dentro de outra. Testes de benchmark indicam um desempenho de 50% em relação ao código nativo, o que deixa a linguagem Lua no mesmo nível de outros códigos C compilados para o asm.js, suficiente para alguns cenários:
A performance é muito baixa para certos casos de uso, mas é certamente aceitável para outros. Em particular, a Lua VM muitas vezes é mais rápida que outras linguagens dinâmicas como Python e Ruby. E embora essas linguagens não sejam super-rápidas, ainda assim são úteis em muitas situações.
Mas, conforme explica Zakai, existem outras dificuldades para lidar ao executar uma VM dentro de outra:
Há questões complexas, como por exemplo a impossibilidade de realizar a coleta de lixo entre diferentes VMs (cross-VM collection). Se não existir uma referência apontando para um objeto Lua ou JavaScript mas houver apenas referência de um para outro, será necessário percorrer todo o heap em ambos os lados e realizar nossa própria coleta (em substituição ao garbage collection do navegador) para liberá-los da memória.
A VM do JS não permite fazer isso, por motivos relacionados a segurança e desempenho. O que se pode fazer é permitir que a Lua VM mantenha referências fortes dentro do mundo JavaScript e libere-as automaticamente quando seu GC coletar tais referências. Isso gera limitações, mas é importante lembrar que o garbage collection entre VMs é um problema complexo na ciência da computação em geral.
O único caso simples ocorre quando um objeto de uma VM pode ser implementado inteiramente em outra; mas isso não é possível na maioria dos casos, tampouco nesse. Por exemplo, alguns objetos Lua podem ter métodos finalizer ("__gc") que não podem ser implementados em JavaScript. E mesmo quando é possível fazer o GC cruzando as VMs, o desempenho é uma preocupação. E note que esse tipo de problema também estaria presente se tivéssemos duas VMs separadas nos navegadores web.
O projeto parece ter como objetivo mostrar a força do Emscripten e do asm.js. Atualmente ambos disputam uma batalha de igual para igual com o Google PNaCl, outra tentativa de rodar código nativo no navegador (mais detalhes podem ser encontrados neste post do InfoQ.com: Debate: Do We Need a Universal Web Bytecode?).
O problema é que tanto o asm.js quanto o PNaCl não são suportados por outros navegadores. Teoricamente, o Chrome pode rodar código asm.js, mas o desempenho é baixo. Por exemplo, benchmarks da Lua VM rodando no Chrome apontam cerca de 30% do desempenho obtido no Firefox Nightly (no momento de escrita), que por sua vez é de 50% em relação ao desempenho da execução nativa. Sendo assim, ninguém vai querer rodar o asm.js no Chrome a menos que o Google otimize seu navegador para a solução de código nativo do Firefox. Tudo vai depender da parcela do mercado de navegadores e da habilidade de cada um em melhorar o desempenho de suas respectivas soluções.