📜 ⬆️ ⬇️

Asm.js came to Chakra and Microsoft Edge

Asm.js in Microsoft Edge

A few months ago we announced the start of work on the introduction of Asm.js. Asm.js support was one of the 10 most requested requests for UserVoice for Microsoft Edge , starting from the very launch in December 2014. Since then, we have made good progress: in Windows 10 Insider Preview, starting with build 10074, you can try Asm .js in Chakra and Microsoft Edge.

What is Asm.js?


Asm.js is a strict subset of JavaScript that can be used as a low-level and effective language for the compiler. As a subset, asm.js describes a restricted virtual machine for languages ​​with unsafe memory access like C and C ++. The combination of static and dynamic checks allows JavaScript engines to use techniques like specialized compilation without insurance or AOT compilation (Ahead-of-Time) for correct asm.js code.

')
Such techniques help javascript run with “predictable” and “close to native” performance, both of which are nontrivial to achieve within the framework of conventional compiler optimizations for dynamic languages ​​like javascript.

Given the difficulty of writing asm.js code manually, today asm.js is mainly done through the transcompilation of C / C ++ code using tools such as Emscripten . The result is used in the framework of the web platform together with technologies such as WebGL and Web Audio. Game engines, for example, Unity and Unreal , are beginning to implement early or experimental support for games on the web without the use of plug-ins, using a combination of asm.js and other related technologies.

How can I try with Asm.js in Microsoft Edge?


To enable Asm.js support in Microsoft Edge, go to the about: flags page in Microsoft Edge and enable the “Enable asm.js” flag, as shown below:



Embedding Asm.js in the Chakra code execution flow


To add Asm.js to Chakra, the components highlighted in green below have been added or changed compared to the basic code execution model described in the article about improving JavaScript performance in Windows 10 .



Key changes:



JIT compiler optimizations for Asm.js


In addition to the changes to the code execution process described above, the Chakra JIT compiler also takes advantage of the limitations imposed by the asm.js specification. These improvements help the Chakra JIT compiler to generate code that will be executed with near-native performance — a cherished goal for all dynamic language JIT compilers. Let's take a closer look at two such optimizations.

Elimination of helpers and insurance calls


The code of assistants and insurance acts as a powerful lifeline for compiled code of dynamic languages. If any of the assumptions made by the JIT compiler during compilation of the code becomes incorrect, there must be a safe mechanism for correctly continuing the execution of the code.

Helpers can be used to handle unexpected situations during an operation, after which the control can be returned to the JIT code. The insurances handle situations in which the JIT code cannot recover after the occurrence of unpredicted conditions and control needs to be transferred back to the interpreter to perform the rest of the current function.

For example, if a variable appears to be an integer, and the compiler has generated code with this assumption, the appearance of a real number should not affect the correctness. In such cases, the helper or insurance code is used to continue execution even with reduced performance. For asm.js code, Chakra does not generate any additional helpers or insurance code.

To understand why this is not necessary, let's look at an example of a squaring function inside an asm.js module, which has been simplified to explain the concept:

function PhysicsEngine(global, foreign, heap) { "use asm"; … // Function Declaration function square(x) { x = +x; return +(x*x); } … } 


The square function in the example code above translates the two x64-machine instructions into asm.js code, excluding the prologue and epilogue generated for this function.

 xmm1 = MOVAPS xmm0 //  double    xmm0 = MULSD xmm0, xmm1 // 


For comparison, the compiled code generated for the square function, with asm.js disabled, includes about 10 machine instructions. Including:


The Chakra JIT compiler is capable of generating efficient code for asm.js, taking advantage of type information for variables that does not change over the lifetime of the program. The validator and linker Asm.js also take this into account. Since all internal variables in asm.js are of native type (int, double, float, or SIMD values), internal functions calmly use native types without packaging them into JavaScript variables for transfer between functions. In the terminology of the compiler, this is often called direct calls and the exclusion of packaging or transformations when working with data in code in asm.js. In this case, for external calls to or from JavaScript, all incoming variables are converted to native types, and outgoing native types are converted to variables during packaging.

Exclusion of border checking when accessing typed arrays


In the previous post, we talked about how the Chakra JIT compiler implements the optimization of automatically typed arrays , while simultaneously putting the border checks out of the arrays, thus improving the performance of array operations within the loop by up to 40%. Given the type constraints in asm.js, the Chakra JIT compiler completely eliminates checking the boundaries for accessing typed arrays for all compiled asm.js code, regardless of where it is in the code (inside or outside the loop or function) or the type of the typed array. It also excludes bounds checking for persistent and non-persistent indexed queries on typed arrays. Together, these optimizations make it possible to achieve near-native performance when working with typed arrays in asm.js code.

Below is a simplified example of saving in a typed array with a constant shift and one x64-machine instruction generated by the Chakra compiler for the corresponding code in asm.js:

 int8ArrayView[4] = 25; //JavaScript- [Address] = MOV 25 //      


When compiling asm.js code, the Chakra JIT compiler can precompute the final address corresponding to int8ArrayView [4] directly during linking of the asm.js code (the first call to the asm.js module) and therefore generate one instruction corresponding to saving in a typed array. For comparison, compiled code generated for the same operation from non-asm.js JavaScript code results in approximately 10-15 machine instructions, which is quite significant. The operation includes the following steps:


The checks above are removed from the code in asm.js due to strict restrictions on what can be changed inside the asm.js module. For example, a variable indicating a typed array in the asm.js module does not change. If it changes, then this is no longer a valid code on asm.js, which is caught during the code validation stage. In such cases, the code is processed in the same way as any other JavaScript function.

Improved scripts and performance improvements from Asm.js


Already from the first results that you can try in the fresh build of the preview of Windows 10, we have seen some cool scripts that benefit from the asm.js support in Chakra and Microsoft Edge. If you want to play yourself, run games like Angry Bots , Survival Shooter , Tappy Chicken or try some fun demos asm.js shown here .



If we talk about improvements in performance, there are several asm.js speed meters that are constantly evolving. Already with preliminary support for asm.js, Chakra and Microsoft Edge work more than 300% faster in Unity Benchmark and about 200% faster in individual tests like zlib used in Google Octane and Apple Jet Stream test suites.


Unity Benchmark scores for 64-bit browsers (Click to enlarge)
(System info: Intel Core (TM) i7 CPU 860 @ 2.80GHz (4 cores), 12GB RAM running 64 bit Windows 10 Preview)
(Scores have been scaled so that IE11 = 1.0, to fit a single chart)

What next?


This is the first step towards integrating asm.js into the web platform behind Microsoft Edge. We are pleased with the results, but not all have done. We are working on fine-tuning the chain of code execution in Chakra to support Asm.js — collect data to make sure that the current approach to the architecture works well on real-life usage scenarios for asm.js, analyze and try to improve performance, functionality, support for tools, etc. P. before enabling this option by default.

As soon as it is enabled, asm.js will work not only in Microsoft Edge, but will also be available in Windows applications written in HTML / CSS / JS, as well as in WebView, as it uses the EdgeHTML rendering engine supplied with MicrosoftEdge in Windows 10.

We also want to thank the colleagues from Mozilla, with whom we have worked closely since the beginning of the implementation of asm.js support, and Unity for their support and cooperation in implementing asm.js in Chakra and Microsoft Edge. And a special thank you to all the developers and users of Windows 10 and Microsoft Edge, who left us valuable feedback. Continue in the same spirit! You can email us on Twitter at @MSEdgeDev or via Connect .

Source: https://habr.com/ru/post/258019/


All Articles