Node Under The Hood : V8

Matt Sprague - LoDo Labs

Javascript Engines

  • JScript (IE)
  • SpiderMonkey  (Mozilla)
  • JavascriptCore (Safari) 
  • Chakra (MS Edge)
  • V8 (Chromium)

V8 and NodeJS

# Search for packages related to V8

# Arch Linux
$ pacman -Ss v8
    community/nodejs 6.3.1-1
        Evented I/O for V8 javascript

V8: Design and Architecture

  • Fast Property Access
  • Dynamic Machine Code Generation
  • Efficient Garbage Collection

Fast Property Access

V8: Design and Architecture

Fast Property Access

Shadow Classes

Property Dictionary or Map

VS

Fast Property Access

Each subsequent invocation of the Triple constructor references the shadow class 

This approach allows inline caching ala Smalltalk-80

Fast Property Access

class Triple {

    constructor(a,b,c) {
        this._first = a;
        this._second = b;
        this._third = c;
    }

    get first() {
        return this._first;
    }

    get second() {
        return this._second;
    }


    get third() {
        return this._third;
    }

}

Fast Property Access

Triple (JS)

Native Shadow Class

NativeTriple0

Initial Shadow Class

Fast Property Access

Triple (JS)

Offset 0 : first

Native Shadow Class

NativeTriple1

Native Shadow Class

NativeTriple0

As each property is initialized a new shadow class is created.

Fast Property Access

Triple (JS)

Offset 0 : first

Offset 1: second

Native Shadow Class

NativeTriple2

Native Shadow Class

NativeTriple0

Native Shadow Class

NativeTriple1

V8: Design and Architecture

Dynamic Machine Code Generation

const v8 = require('v8');

v8.setFlagsFromString('--print_code');

class Triple {

    constructor(a,b,c) {
        this._first = a;
        this._second = b;
        this._third = c;
    }

    get first() {
        return this._first;
    }

    get second() {
        return this._second;
    }


    get third() {
        return this._third;
    }

}

const myTriple = new Triple(2,-1,0);
const myOtherTriple = new Triple(-3.4,22,1.3);

console.log(myTriple);
kind = FUNCTION
name = Triple
compiler = full-codegen
Instructions (size = 180)
0x314ae6b404e0     0  55             push rbp                ;; debug: position 171
0x314ae6b404e1     1  4889e5         REX.W movq rbp,rsp
0x314ae6b404e4     4  56             push rsi
0x314ae6b404e5     5  57             push rdi
0x314ae6b404e6     6  493ba5880a0000 REX.W cmpq rsp,[r13+0xa88]
0x314ae6b404ed    13  7305           jnc 20  (0x314ae6b404f4)
0x314ae6b404ef    15  e8cc91efff     call StackCheck  (0x314ae6a396c0)    ;; code: BUILTIN
0x314ae6b404f4    20  ff7528         push [rbp+0x28]         ;; debug: statement 189
                                                             ;; debug: position 189
0x314ae6b404f7    23  488b4520       REX.W movq rax,[rbp+0x20]    ;; debug: position 203
0x314ae6b404fb    27  48b9e1ae05a34a320000 REX.W movq rcx,0x324aa305aee1    ;; debug: position 201
                                                             ;; object: 0x324aa305aee1 <String[6]: _first>
0x314ae6b40505    37  5a             pop rdx
0x314ae6b40506    38  48bf0000000001000000 REX.W movq rdi,0x100000000
0x314ae6b40510    48  e86b3ceeff     call 0x314ae6a24180     ;; code: STORE_IC, GENERIC
0x314ae6b40515    53  ff7528         push [rbp+0x28]         ;; debug: statement 214
                                                             ;; debug: position 214
0x314ae6b40518    56  488b4518       REX.W movq rax,[rbp+0x18]    ;; debug: position 229
0x314ae6b4051c    60  48b901af05a34a320000 REX.W movq rcx,0x324aa305af01    ;; debug: position 227
                                                             ;; object: 0x324aa305af01 <String[7]: _second>
0x314ae6b40526    70  5a             pop rdx
0x314ae6b40527    71  48bf0000000003000000 REX.W movq rdi,0x300000000
0x314ae6b40531    81  e84a3ceeff     call 0x314ae6a24180     ;; code: STORE_IC, GENERIC
0x314ae6b40536    86  ff7528         push [rbp+0x28]         ;; debug: statement 240
                                                             ;; debug: position 240
0x314ae6b40539    89  488b4510       REX.W movq rax,[rbp+0x10]    ;; debug: position 254
0x314ae6b4053d    93  48b921af05a34a320000 REX.W movq rcx,0x324aa305af21    ;; debug: position 252
                                                             ;; object: 0x324aa305af21 <String[6]: _third>
0x314ae6b40547   103  5a             pop rdx
0x314ae6b40548   104  48bf0000000005000000 REX.W movq rdi,0x500000000
0x314ae6b40552   114  e8293ceeff     call 0x314ae6a24180     ;; code: STORE_IC, GENERIC
0x314ae6b40557   119  498b45a8       REX.W movq rax,[r13-0x58]
0x314ae6b4055b   123  48bb01e705a34a320000 REX.W movq rbx,0x324aa305e701    ;; object: 0x324aa305e701 Cell for 6144
0x314ae6b40565   133  83430bd1       addl [rbx+0xb],0xd1
0x314ae6b40569   137  791f           jns 170  (0x314ae6b4058a)
0x314ae6b4056b   139  50             push rax
0x314ae6b4056c   140  e80f90efff     call InterruptCheck  (0x314ae6a39580)    ;; code: BUILTIN
0x314ae6b40571   145  58             pop rax
0x314ae6b40572   146  48bb01e705a34a320000 REX.W movq rbx,0x324aa305e701    ;; object: 0x324aa305e701 Cell for 6144
0x314ae6b4057c   156  49ba0000000000180000 REX.W movq r10,0x180000000000
0x314ae6b40586   166  4c895307       REX.W movq [rbx+0x7],r10
0x314ae6b4058a   170  c9             leave                   ;; debug: statement 261
0x314ae6b4058b   171  c22000         ret 0x20
0x314ae6b4058e   174  6690           nop

Three Compilers

Full - Codegen

Crankshaft

Turbofan

Parser

AST

Full Codegen

Crankshaft

Turbofan

Optimized

Code

Unoptimized

Code

Optimized

Code mk2

Full Codegen

Native Code

AST

Crankshaft

Native Code

AST

Hydrogen IR

Lithium

IR

V8: Design and Architecture

Efficient Garbage Collection

Efficient Garbage Collection

  • Execution Halting

  • Generational

  • Heap Segmenting

Efficient Garbage Collection

[
  {
    "space_name": "new_space",
    "space_size": 2063872,
    "space_used_size": 951112,
    "space_available_size": 80824,
    "physical_space_size": 2063872
  },
  {
    "space_name": "old_space",
    "space_size": 3090560,
    "space_used_size": 2493792,
    "space_available_size": 0,
    "physical_space_size": 3090560
  },
  {
    "space_name": "code_space",
    "space_size": 1260160,
    "space_used_size": 644256,
    "space_available_size": 960,
    "physical_space_size": 1260160
  },
  {
    "space_name": "map_space",
    "space_size": 1094160,
    "space_used_size": 201608,
    "space_available_size": 0,
    "physical_space_size": 1094160
  },
  {
    "space_name": "large_object_space",
    "space_size": 0,
    "space_used_size": 0,
    "space_available_size": 1490980608,
    "physical_space_size": 0
  }
]

Efficient Garbage Collection

Current Experiments:

Strong Mode

&

SoundScript

Strong Mode: Extends Strict Mode

  • No more var (only let & const)
  • Objects are inherently immutable
  • No sparse arrays
  • Safe functions (strict arity)
  • No implicity type conversions

SoundScript

  • Based on Typescript
  • Provides a type system IN the VM
  • Efficient runtime type checking
  • Aimed at improving predictability

Further Reading

lodolabs [at] gmail [.] com

Node Internals

By Matt Sprague

Node Internals

  • 1,529