Web App Development

Compiling V8 and viewing the assembly code it generates from JavaScript

I was recently looking into some code optimization behavior by V8, the JavaScript engine used by Chrome and Node. (The JavaScript engine in Firefox is called SpiderMonkey, the one in Internet Explorer Chakra).

Modern JavaScript engines don’t interpret the JavaScript code directly, but instead translate it to machine code that can run much faster.

This post explains how to compile V8 and and use the JavaScript shell it provides (called D8).

Compiling V8

Update: Consider using JSVU to install D8 instead.

Before compiling V8 you need to install the Chromium depot_tools - when I tried it without V8 complained that it couldn’t find a program called gclient:

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"

Then check out the V8 repo and build the JavaScript engine:

svn co http://v8.googlecode.com/svn/trunk v8-trunk
cd v8-trunk
make dependencies
make ia32.release objectprint=on disassembler=on
export PATH=${PATH}:`pwd`/out/ia32.release

I’m not sure what exactly objectprint does and if it’s necessary, but you need the disassembler options to be able to view the assembly code generated by V8.

Now the D8 program should be available in your console.

Running a JavaScript program with D8

The D8 command line tool is very similar to the node command. You can ither use the interactive shell or use it to execute a specific file.

For example if we have this code in add.js:

function add(a, b){
  return a + b;

print(add(15, 19));

Then you can run it by calling

d8 add.js

And the output will be


Not how we use print rather than console.log. The console API isn’t available natively in the V8 engine.

Using D8 to view the Hydrogen code representation

Update: I don’t think V8 uses Hydrogen anymore, but you can view the interpreter bytecode with --print-bytecode .

There are four main stages that code inside V8 passes through:

  1. JavaScript Code - this is what you wrote
  2. Hydrogen - intermediate code representation where optimizations are applied
  3. Lithium - machine specific code used to generate native code
  4. Machine Code - this is what the computer understands

The --trace-hydrogen option allows you to see the Hydrogen code that’s generated when running V8. To ensure the Hydrogen code is created for the addfunction, add this to the code:

for (var i=0;i<1000;i++){
  add(i, 1);

Now d8 --trace-hydrogen add.js will create a hydrogen.cfg file in the current directory.

The file is 80KB large and contains code like this:

  name "add"
  method "add:0"
  date 1440029178000
  name "H_Assign dominators"
    name "B0"
    from_bci -1
    to_bci -1
    successors "B1"
    loop_depth 0
        size 0
        method "None"
      0 0 v0 BlockEntry  type:Tagged <|@
      0 0 t12 Constant 0x333080a1 <the hole> [map 0x29e08211]  <|@

You can have a look at the entire file on Github.

Using D8 to view the generated assembly code

Update: I’m not sure if --print-code still works with the instructions above, but it should still work if built in Debug mode.

Finally, you can use the --print-code option to see the native code generated by V8:

d8 --print-code add.js

Which will output something like this:

--- Raw source ---
function add(a, b){
  return a + b;

--- Code ---
source_position = 0
Instructions (size = 456)
0x36953100     0  8b4c2404       mov ecx,[esp+0x4]
0x36953104     4  81f991806049   cmp ecx,0x49608091          ;; object: 0x49608091 <undefined>
0x3695310a    10  750a           jnz 22  (0x36953116)
0x3695310c    12  8b4e13         mov ecx,[esi+0x13]
0x3695310f    15  8b4917         mov ecx,[ecx+0x17]
0x36953112    18  894c2404       mov [esp+0x4],ecx
0x36953116    22  55             push ebp

You can have a look at the full assembly code for add.js on Github.

Follow me on Twitter
I'm building monitoring tool for site speed and Core Web Vitals.
➔ Start monitoring your website or run a free site speed test