Year in review: Spidermonkey in 2014 part 3

In the first two parts I listed the major changes in the Javascript engine of Mozilla Firefox in 2014 and enumerated the major changes that happened starting from Firefox 29 till Firefox 34. In part 3 I will iterate the major changes in the JavaScript engine in the last two releases that were developed in 2014.

If you haven’t read the first parts yet, I would encourage you to do that first.
<- Year in review: Spidermonkey in 2014 part 1
<- Year in review: Spidermonkey in 2014 part 2

Firefox 35

JIT RegExp.prototype.exec and RegExp.prototype.test

When Firefox 32 was released the regular expression engine was replaced with Irregexp. The new engine had just like its predecessor a small jit where regular expressions get compiled to native code. And just like its predecessor the easiest way to embed the regular expression engine is to use C code. Consequently a normal execution of a regular expression looked as following. The js code goes into C code preparing the regular expression engine jit, whereafter the regular expression engine gets called. In this release we eliminated the middle step (the c code) and now jump directly from JS jit to regular expression jit, removing the overhead the c code provided when calling RegExp.prototype.exec or RegExp.prototype.test.

Read more about this in the bug report

GVN + UCE combined

Just like most compilers Ionmonkey has an optimization called Global Value Numbering (GVN). It tries to remove or replace redundant instructions. In our implementation it is also the place where most replaces based on inputs happen, like constant folding, identity removal … After this pass we run Unreachable Code Elimination (UCE), which eliminates branches which are never taken. Optimizations taking place during GVN can improve the efficiency of UCE. More folded instructions can increase how many code that can be found to be dead. On the other hand removed code can again make it possible for GVN to optimize some extra instructions. Before Firefox 35 we only ran both passes once. As a result we sometimes didn’t find the most optimal code. With this release GVN and UCE are now combined, making it possible to have the same optimizations as running GVN and UCE multiple times after each other, but doing so in only one pass.

Learn more about this in an explanatory video

Lazy linking when recompiling code

The compilation of Ion code happens in three phases. First we have the graph creation phase (happens in IonBuilder), afterwards we do all sort of optimizations on that graph, ending with a linking phase, which finishes the compilation. In this sequence only the optimizing part can be done off the main thread. The other two phases block execution of JavaScript code. Lazy linking is about improving the last phase. Currently linking happens eagerly. As soon as a graph is ready we will try to link it. Even if we won’t ever execute that code (again) or if it gets invalidated due to better types. With lazy linking we wait until we want to execute that code before linking.

Read more about this in the bug report.

Compile non-CNG functions

Compile and Go (CNG) functions give extra performance since the caller cannot modify objects on the scope chain between compilation and execution [1]. With this warranty compilers can optimize access to these objects better. Now IonMonkey can only compile such functions. Non-CNG were stuck in the baseline compiler. In Firefox 34 and 35 these limitations were mostly removed. Given our most important class of non-CNG functions are in addons and chrome content. This will give again a nice boost to performance of these.

Read more about this in the bug reports: bug 1064777, bug 1045529 and bug 911570

Firefox 36

Baseline compile generators

Like mentioned in part 1, Firefox 30 saw the introduction of ES6 generators. In that release only supported for the interpreter (our first tier) was added. This was because the initial implementation tried to support this feature touching as little code as possible. But this method also disabled support for higher tiers. Six releases later we are now proud to also have support for generators in our second tier, the baseline compiler and that even before ES6 is released.

Wingo did the beginning of this huge task and has written a blogpost about it.
Read the blogpost about support of compiling generators in Baseline

ES6 Symbols

For the first time in a very long time a new primitive type was added to the engine. This all has to do with the upcoming spec. of ES6 Symbols. Nexto null, undefined, boolean, number and string, symbol is now present on that list. A Symbol is a unique and immutable primitive value. Without going too deep it can enable hiding of properties or fix name clashes between properties. It also can helps with not breaking existing codebases when new property names to the language are introduced. Not immediately something people need to use, but it can open new and maybe better ways to do some things.

Read more about this in the developer reference
Stackoverflow: why bring symbols to JS

Selfhosting String.prototype.substr, String.prototype.substring and String.prototype.slice

In Firefox 20 the selfhosting infrastructure landed. Since that release we can implement JavaScript features in JavaScript itself, instead of writing it in C. During runtime this selfhosted function will just get executed like somebody would have scripted in JavaScript. The major improvement here is that we remove the overhead from calling from JavaScript out to C and back. This gave improvements for e.g. “ { /* … */})” since the C step was fully eliminated between calling the function and the function given in the argument. In this release substr, substring and slice are now also selfhosted. For these functions the speedup is mostly because the edge case checks (start is positive and length is smaller than string length) are now done in JavaScript and IonMonkey can reason about them and potentially remove those checks!

Read more about this in the bug report