Arrow of time
Arrow of time

We should replace asm.js with Rust

Share Tweet Share

I can't be the only one to think there is something horrible about today's JavaScript. It is like a Lovecraftian …

I can't be the only one to think there is something horrible about today's JavaScript. It is like a Lovecraftian programming language from outer space - it is here to stay, and if you follow certain forums it looks like it's spread absolutely everywhere and absorbed every other language, but at the same time it just seems so damned indescribably icky.

It was a toy language that went nuclear. With just the bare minimum of features to be practical: several basic data types (Boolean, Number, String, Undefined, Null, Object), basic flow control structures (if, case, for, do, while), but with fancy new features (at the time of its making) already built-in in the first standard: exceptions and prototype-based inheritance, it was twisted, hacked and bolted upon enough in the almost two decades since its introduction to become actually usable, and finally, necessary.

Because of its very dynamic nature it has become one of the top reasons for the development of modern optimizing compilers and JITs. In a curious twist of fate, and out of dire need, web browsers have become the drivers for large innovations and huge software engineering efforts to make this clumsy little language as good as its more serious cousins. It has become routine to see developer teams boasting about new JavaScript benchmarks which break each other records fairly regularly - and this is perfectly fine.

What I think crosses the line into monstrosity is efforts which basically annotate the language with special syntax or objects which ordinarily would not normally be used in practical programming to signal certain things to the interpreter or JIT. Consider asm.js. Have you every really looked at it?

For example, JavaScript on its own has a single numeric data type, called Number. This "Number" has probably started as some kind of abstraction intended for novice programmers (especially at the time in mid 1990-ies) so they don't have to trouble their precious minds about what really goes on under the hood, but it should be obvious that this approach to language design is bogus and that it is one of the basic marks of a "toy language." Nowadays, every JavaScript programmer worth its salt needs to keep in mind that the practical implementation of the Number type in all current engines is that of a double-precision floating point number, with all the devious problems it may bring.

On the other hand, JavaScript obviously has Boolean logic operators and bit operators which more naturally operate on integers. What JavaScript interpreters do with these is that they convert the double-precision numbers into integers, perform the required operation and convert them back into the floating point representation. All this can be done without loss of precision if the numbers fit into a 32-bit integer (because all the values of a 32-bit integer can be unambiguously presented with a 64-bit double precision floating point type), but is reasonably slow.

Enter asm.js

The point of asm.js is to JIT-compile as much of the code in as low-level way possible, and this means the compiler needs to be sure that the programmer meant that certain variables and certain operations be strictly integer-only. If this is done properly, certain variables will only ever exist in the resulting compiled code as integer variables. In practice, it means the compiler recognizes special syntax which would otherwise be unnecessary or unused, like this:

(x+y)|0

Basically, the result of this operation, by definition, cannot be anything other than an integer value, even if every part of it - x, y and 0 - are actually floating point numbers. This knowledge is used to simply compile this into low-level integer CPU instructions.

Asm.js actually goes further than that, and is intended to be a parallel compiler for such specially annotated JavaScript which the "normal" engines will call into when the code indicates it is compliant. Asm.js promises it will provide compatible entry points into such compiled code to whatever the wider external JavaScript environment may be (e.g. a web browser), but that internally, everything will be compiled ahead of time as soon as the code is provided (e.g. loaded from the Internet).

It makes me wonder -- why???. Any code that requires asm.js to achieve decent performance will be horrifically slow when interpreted or even JIT-compiled with generic compilers. Why not have a separate language which is sufficiently high-performance to allow serious compilation to machine code, with just the same type of interfaces to the "regular" JavaScript environment, but which would be actually decent to program into.

How Rust would help

#1: Rust is a "safe by default" language. It allows C-style low-level shenanigans but such code must be specially marked. Obviously, for the web, this language feature would be completely disabled.

#2: Rust in integrated with the web. Unlike the vast majority of languages, Rust actually provides for directly referencing required libraries for a project directly from on-line repositories. This means we can have fairly large projects with tons of dependencies which don't have to be distributed with the main code. There is still space for improvement, especially with regards to depending on specific version of an external library.

#3: Rust compiles to C-level efficient machine code. It was never meant to be interpreted. It has low-level CPU-friendly data types. It can call into OpenGL (if needed...) directly without the large machinery of thunking and data type adaptations which JavaScript needs. Luckily, WebGL did the right thing and allowed shaders to be written in a more natural language for them.

#4: The licensing is friendly. Rust is MIT-licensed. It can be included wherever, even in proprietary-code projects.

Of course, memory safety in itself is not enough - some sandboxing of the standard library will also be needed.

Replacing JavaScript itself?

While at it, what is stopping us to ditch JavaScript altogether? Nothing I can see. IMHO, it has way surpassed its sell-by date.

Asm.js is not the only elephant in the room. Things like SIMD.js try to shoe-horn advanced features into a language which simply wasn't designed to handle them. Compare this to Rust where such constructs could be handled with templates and macros.

Using Rust instead of JavaScript simply makes sense, you know it does.


comments powered by Disqus