HTML and CSS Reference
In-Depth Information
In Listing 18-5, you can see that char* pointer dereferences are converted to HEAP8 array access. The next section
shows how memory access works in general.
Memory Representation
To understand JavaScript strlen , you must know how Emscripten represents memory. The Typed Array specification,
used in WebGL, HTML5 Canvas, and XMLHttpRequest Level 2, introduces a mechanism by which JavaScript can
read from and write to contiguous blocks of binary data. An ArrayBuffer stores a sequence of contiguous bytes which
can be accessed and interpreted through ArrayBufferView objects. For example, the Int8Array object exposes the
ArrayBuffer as if it were signed 8-bit integers and Float32Array exposes the same memory as if it were IEEE 32-bit
Emscripten's memory space is a single JavaScript ArrayBuffer accessed through one of each of ArrayBufferView
type. For example, HEAP8, used in _strlen above, is an Int8Array through which signed 8-bit integer values are
read from and written to the program's memory. Pointers, such as the variables str and s above, are simply numeric
indices into the heap. Emscripten has ArrayBufferViews for 32-bit and 64-bit floats, as well as the full range of 8-, 16-,
and 32-bit integers, both signed and unsigned.
In JavaScript, all numbers are 64-bit IEEE floats. Using floating point numbers to represent pointers into the heap
would be silly and slow, so to inform JavaScript optimizers that these variables can be made into integers, Emscripten
sprinkles | 0 throughout the function. The x | 0 expression coerces the number x into a signed integer, allowing
JavaScript engines to optimize, say, c = c + 1 | 0 , into a fast, native increment instruction.
Through clever type analysis, JavaScript engines can even notice when it's possible to reduce 64-bit precision
floating point operations to 32-bit precision floating point operations without changing the semantics of the code.
You are beginning to discover why Emscripten-generated JavaScript is fast. It uses a compact ArrayBuffer for
memory, so the garbage collector doesn't have to do anything. Variables are always numbers, not objects, which
means there are no dynamic method calls or hash table lookups. Clever use of JavaScript's | , >> , and >>> operators
indicate the code has integer semantics. All of this means that just-in-time optimizers can translate JavaScript directly
into fast machine code.
These high-performance JavaScript conventions have been codified in a standard called asm.js.
What is asm.js?
asm.js is a subset of JavaScript: that is, it adds no new semantics to the existing JavaScript language. All asm.js code
has identical behavior in browsers that do not specifically support it, though it runs much faster in browsers that
recognize and optimize asm.js constructs.
The asm.js subset of JavaScript is restricted enough that it can be treated as a low-level compile target. It only
exposes operations that can be directly translated into native machine instructions. Traditional JavaScript engines
optimize code dynamically during execution with so-called just-in-time (JIT) compilation. asm.js, on the other
hand, can be recognized, compiled, and optimized ahead-of-time (AOT), resulting in consistent, predictable, high
performance, which is especially important for games.
asm.js sparked controversy in the web and game development communities. Is JavaScript the right way to specify
what is effectively a virtual machine bytecode? Does asm.js break the “View Source” nature of the open web? Can
native code performance really be achieved with this approach?
However, to us game developers, those discussions are somewhat academic. asm.js is real and it works well in
practice, so if you want your game on the secure, cross-browser, open platform of the Web, targeting asm.js is a great
option. You can read more about asm.js at .
Search WWH ::

Custom Search