Asm.js, universal compatibility to applications
This subset of JavaScript defined by Mozilla gives apps and games nearly the speed of native code.
It was thought for a long time in the interest of a virtual machine in the browser to compile different languages and make them work on all operating systems. This idea took shape thanks to Mozilla developers, and Asm.js is implemented in SpiderMonkey in 2013.
It is not a real bytecode but a subset of JavaScript that is compiled and optimized for speed. It is operational in Firefox. The asm.js code is compiled AOT (Ahead Of Time), produces a reusable code unlile JavaScript which is compiled JIT (Just In Time).
We can compile various statically typed languages to LLVM bitcode, then use Emscriptem to convert it to Asm.js. The original code is already optimized, it produces faster JavaScript and Asm.js also brings speed to two times slower than binary but ten times faster than JavaScript.
An entire application can be converted into Asm.js or only a library from another language to be used in a JavaScript program .
With game developer Epic, Mozilla has implemented the 3D engine Unreal Engine 3 in Asm.js. This led to V8 developers to optimize the JavaScript compiler of Chrome and Node.js for Asm.js. Opera also has optimization for Asm.js code.
Microsoft, though, has announced the implementation of Asm.js in Windows 10 and for this, works with Mozilla.
Asm.js code since the last optimizations in December 2013 provides 1.5 times the execution time of native code to run the same program.
The new Edge browser from Microsoft, implements Asm.js, with the help of Mozilla. This has been commented by the firm in this post: Bringing Asm.js to Chackra in Microsoft Edge.
Features
From C to LLVM bitcode to Asm.js
Asm.js is compatible with JavaScript, and provides no additional function but to be validated and compiled the code must only contain the subset defined by the specification.
- Asm.js code is compiled to native code but the compiled code remains in place and is reused if the source is not changed.
- The code works on any browser but faster when Asm.js is implemented.
- This is a typed language without declaration. All the variables have a type that is assigned at compile time but not explicitly stated by the programmer.
- Annotations are statements that give a type and a default value to variables, especially when they are arguments of functions or return values. This has the form x = x | 0, the default value is 0 and the type is an integer.
- Strings are processed as memory areas.
- The only valid standard library are Math and stdlib.
- The specification does not mention objects.
- An array generic type ArrayBufferView, whose derive several numeric types.
- DOM access is not performed in Asm.js, but in common JavaScript. It is not accelerated.
- It has no garbage-collector. The code generator manages the memory allocation. It is expected to be included later.
- A module is defined like a function, whose the first line in the body is "use asm"; It contains other functions. It may be used in the standard JavaScript.
- Dynamic compilation such as eval does is possible. So the code can grow dynamically.
- It is intended to allow the storage of the generated code for a unique compilation on the first run.
One can benefit from the Asm.js language only by compiling a statically typed language because it is on this point that Asm.js get its speed. A dynamic language should rather be compiled to regular JavaScript to run in the browser.
Asm.js vs. Native Client vs. WebAssembly
Which solution should you prefer, Asm.js, or NaCl, ie programs compiled to LLVM bitcode running also in their browser?
A program under NaCl works in the browser but must be compiled for each operating system. So the author must provide multiple versions, that is not the case for Asm.js which works the same in any system.
Knowing that Mozilla does not want to implement NaCl, that excludes it from Firefox, and apparently from Internet Explorer as well.
Asm.js works automatically, since a JS compiler already exists in each browser. We know how to optimize it and it takes only a few minor changes to work on V8 or other JIT (Just-In-Time) and AOT (Ahead-Of-Time).
The announcement of WebAssembly in June 2015, obsoletes NaCl, as it will be supported by all browsers, while NaCl is only by Chrome. But this is not the case of Asm.js with which it will coexist. In fact, the wasm code will be similar to Asm.js initially before diverging. Wasm may be converted into Asm.js to run on older browsers. It may also be used in modules in JavaScript or Asm.js.
Example of code
The strlen function is defined and the letters of a string are displayed.
JavaScript:
function strlen(ptr)
{
var curr = ptr;
while(MEM8[curr] != 0)
curr++;
return (curr - ptr);
}
var ptr = "demo";
var len = strlen(ptr);
for(var i = 0; i < len; i++)
{
document.write(ptr[i]);
}
Asm.js:
function strlen(ptr)
{
ptr = ptr | 0;
var curr = 0;
curr = ptr;
while (MEM8[curr]|0 != 0)
{
curr = (curr + 1) | 0;
}
return (curr - ptr) | 0;
}
var ptr = "demo";
var len = strlen(ptr) | 0;
for(var i = 0; i < len; i++)
{
document.write(ptr[i]);
}
I can not guarantee that document.write is valid asm.js, it is there for the demonstration.
Emscriptem with the option ASM_JS=1 produces Asm.js code rather than JavaScript.
Documents
- Specification.
- Bananabench. Demo of 3D in the browser.
- Monster Madness (video). A commercial 3D game ported to Asm.js (within one week) with Emscriptem because it was writen in C++, fully functional, running in the browser!
- Asm.js AOT compilation. How is built the compiler, in depth. For compiler writers only.
- Slide show. From C++ to Asm.js via Emscriptem.
- A game made with asm.js. Video. Games are made with Unity or in C and converted to run in a browser, therefore on any OS!