The Dark Side of JavaScript

Ali Arafati

What’s faster, C++ or JavaScript?

C++ developers

Franziska Hinkelmann

Marja Hölttä

Benedikt Meurer

const primes = [2, 3, 5, 7];
const nextPrime = calculateNextPrime(primes);

primes.push(nextPrime);
const a = [2, 3, 5, 7];
const b = c(a);

a.d(b);

https://medium.com/dailyjs/317d46c94775 by Franziska Hinkelmann

[
  {
    "type": "VariableDeclaration",
    "declarations": [
      {
        "type": "VariableDeclarator",
        "id": {
          "type": "Identifier",
          "loc": {
            "identifierName": "primes"
          },
          "name": "primes"
        },
        "init": {
          "type": "ArrayExpression",
          "elements": [
            {
              "type": "NumericLiteral",
              "value": 2
            },
            {
              "type": "NumericLiteral",
              "value": 3
            },
            {
              "type": "NumericLiteral",
              "value": 5
            },
            {
              "type": "NumericLiteral",
              "value": 7
            }
          ]
        }
      }
    ],
    "kind": "const"
  }
]
         0x2e3c1f51eb75 @    3 : 26 f7             Star r4
         0x2e3c1f51eb77 @    5 : 0c 25             LdaSmi [37]
         0x2e3c1f51eb79 @    7 : 26 f6             Star r5
         0x2e3c1f51eb7b @    9 : 61 c0 00 f7 02    CallRuntime [CreateArrayLiteralWithoutAllocationSite], r4-r5
         0x2e3c1f51eb80 @   14 : 26 fb             Star r0
   73 S> 0x2e3c1f51eb82 @   16 : 0d                LdaUndefined
         0x2e3c1f51eb83 @   17 : 26 f8             Star r3
         0x2e3c1f51eb85 @   19 : 13 01 00          LdaGlobal [1], [0]
         0x2e3c1f51eb88 @   22 : 26 f9             Star r2
         0x2e3c1f51eb8a @   24 : 27 fb f7          Mov r0, r4
   73 E> 0x2e3c1f51eb8d @   27 : 5f f9 f8 02       CallNoFeedback r2, r3-r4
         0x2e3c1f51eb91 @   31 : 26 fa             Star r1
  110 S> 0x2e3c1f51eb93 @   33 : 29 fb 02          LdaNamedPropertyNoFeedback r0, [2]
         0x2e3c1f51eb96 @   36 : 26 f9             Star r2
         0x2e3c1f51eb98 @   38 : 27 fb f8          Mov r0, r3
         0x2e3c1f51eb9b @   41 : 27 fa f7          Mov r1, r4
  110 E> 0x2e3c1f51eb9e @   44 : 5f f9 f8 02       CallNoFeedback r2, r3-r4
Instructions (size = 1108)
0x10e479600     0  488d1df9ffffff REX.W leaq rbx,[rip+0xfffffff9]
0x10e479607     7  483bd9         REX.W cmpq rbx,rcx
0x10e47960a     a  7410           jz 0x10e47961c  (LdaNamedPropertyNoFeedbackWideHandler)
0x10e47960c     c  48ba0000000037000000 REX.W movq rdx,0x3700000000
0x10e479616    16  e885c2b4ff     call 0x10dfc58a0  (Abort)
0x10e47961b    1b  cc             int3l
0x10e47961c    1c  55             push rbp
0x10e47961d    1d  4889e5         REX.W movq rbp,rsp
0x10e479620    20  6a18           push 0x18
0x10e479622    22  4883ec38       REX.W subq rsp,0x38
0x10e479626    26  4f0fbf440e01   REX.W movsxwq r8,[r14+r9*1+0x1]
0x10e47962c    2c  4c8b5d00       REX.W movq r11,[rbp+0x0]
0x10e479630    30  4f8b04c3       REX.W movq r8,[r11+r8*8]
0x10e479634    34  470fb7640e03   movzxwl r12,[r14+r9*1+0x3]
0x10e47963a    3a  49ba0000000001000000 REX.W movq r10,0x100000000
0x10e479644    44  4d39e2         REX.W cmpq r10,r12
0x10e479647    47  730d           jnc 0x10e479656  (LdaNamedPropertyNoFeedbackWideHandler)
0x10e479649    49  488b15ecffffff REX.W movq rdx,[rip+0xffffffec]
0x10e479650    50  e84bc2b4ff     call 0x10dfc58a0  (Abort)
0x10e479655    55  cc             int3l
0x10e479656    56  498bc6         REX.W movq rax,r14
0x10e479659    59  4883e003       REX.W andq rax,0x3
0x10e47965d    5d  4c894de0       REX.W movq [rbp-0x20],r9
0x10e479661    61  4c897de8       REX.W movq [rbp-0x18],r15
0x10e479665    65  4c895dd8       REX.W movq [rbp-0x28],r11
0x10e479669    69  4c8965c8       REX.W movq [rbp-0x38],r12
0x10e47966d    6d  4c8945f0       REX.W movq [rbp-0x10],r8
0x10e479671    71  4883f801       REX.W cmpq rax,0x1
const obj = {
  language: "JavaScript"
};
class Object {
  public:
    string language;
};

Object obj = new Object
obj.language = "C++"
case class Object(language: String)

val obj = new Object("Scala")
const obj = {
  language: "JavaScript"
}

obj.compiler = "V8"
obj.history = ["dark", "good parts", "bad parts"]
obj.history = 1337;

delete obj.history
const dictionary = {
  "hej": "yo",
  "hej då": "so long",
  "lagom": NaN,
  "gift": ["married", "poison"],
  "fart-hinder": "speed bump"
}

dictionary["hej"] // yo

THIS IS SLOW!

Very fast objects

Fast objects

Slow objects

JavaScript Object/Array

Memory

Hidden Class

Properties

Elements

pointer

pointer

pointer

in-object properties

Fixed Array

Fixed Array

or

Dictionary

Hidden Class

bit fields

Descriptor

Fixed Array

length

key 1

details 1

item 1

item 2

function getPlayerPosition(player) {
  return player.position;
}
const arya = { name: 'Arya Stark', hair: 'dark' }
const girl = { name: 'A girl has no name' }

Object.setPrototypeOf(girl, arya);

girl.hair; // dark

name

hair

function getPlayerPosition(player) {
  return player.position;
}
function getPlayerPosition(player) {
  if (%ShapeEqual(player, @123414))
    return player@2432
  }
  return player.position;
}
function getPlayerPosition(player) {
  if (%ShapeEqual(player, @986909))
    return player@3446
  }
  if (%ShapeEqual(player, @123414))
    return player@2432
  }
  return player.position;
}
const playerA = { position: [0, 0] };
const playerB = { position: [1, 2] };

playerB.isDead = true;
const playerA = { position: [0, 0] };
const playerB = { position: [1, 2] };

const IS_DEAD = 0;
playerB[IS_DEAD] = true;
function getPlayerPosition(player) {
  if (%ShapeEqual(player, @123414))
    return player@2432
  }
  return player.position;
}

Demo

         0x3f0c8a9e9d1 @   23 : 61 c2 00 f8 02    CallRuntime [CreateObjectLiteralWithoutAllocationSite], r3-r4
         0x3f0c8a9e9d6 @   28 : 26 f9             Star r2
  519 E> 0x3f0c8a9e9d8 @   30 : 13 02 00          LdaGlobal [2], [0]
         0x3f0c8a9e9db @   33 : 2f f9 03 02       StaNamedOwnProperty r2, [3], [2]
         0x3f0c8a9e9df @   37 : 25 f9             Ldar r2
  472 E> 0x3f0c8a9e9e1 @   39 : 1d 04             StaCurrentContextSlot [4]
  558 S> 0x3f0c8a9e9e3 @   41 : 1b 04             LdaImmutableCurrentContextSlot [4]
         0x3f0c8a9e9e5 @   43 : 26 f9             Star r2
  568 E> 0x3f0c8a9e9e7 @   45 : 29 f9 04          LdaNamedPropertyNoFeedback r2, [4]

Install d8 & some useful commands

d8 --allow-natives-syntax
const array = [1, 2, 3, 4, 5];
%DebugPrint(array)

const obj = { name: 'JavaScript' };
%DebugPrint(obj)

const car = { name: 'BMW' };
%HaveSameMap(obj, car)
const language = {};

language.name = "JavaScript";
language.type = "Dynamic";
language.jit = true;

delete language.type;
const language = {};

language.name = "JavaScript";
language.type = "Dynamic";
language.jit = true;

delete language.type;

language ref

Memory

Hidden Class

[]

const language = {};

language.name = "JavaScript";
language.type = "Dynamic";
language.jit = true;

delete language.type;

language ref

Memory

Hidden Class

JavaScript

[name]

[]

const language = {};

language.name = "JavaScript";
language.type = "Dynamic";
language.jit = true;

delete language.type;

language ref

Memory

Hidden Class

JavaScript

[name, type]

[name]

Dynamic

[]

const language = {};

language.name = "JavaScript";
language.type = "Dynamic";
language.jit = true;

delete language.type;

language ref

Memory

Hidden Class

JavaScript

[name, type, jit]

[name, type]

Dynamic

[name]

[]

true

const language = {};

language.name = "JavaScript";
language.type = "Dynamic";
language.jit = true;

delete language.type;

language ref

Memory

Hidden Class

JavaScript

[name, jit]

[name, type, jit]

Dynamic

[name, type]

[name]

true

[]

const language = {};

language.name = "JavaScript";
language.type = "Dynamic";

[name, hobies]

[name, type]

[name]

[]

const person = {};

person.name = "Ali";
person.hobies = ["dark side"];
const languages = [
  {
    name: "JavaScript",
    type: "Dynamic"
  },
  {
    type: "Static",
    name: "C++"
  }
];
const primes = [2, 3, 5, 7];

2

3

5

7

Memory

@1234000

Hidden Class

length: 4

SMI-Packed

const primes = [2, 3, 5, 7];

primes.push(13);

2

3

5

7

Memory

@1234000

Hidden Class

length: 4

SMI-Packed

const primes = [2, 3, 5, 7];

primes.push(13);

2

3

5

7

Memory

@93422313

13

Hidden Class

length: 5

SMI-Packed

const primes = [2, 3, 5, 7];

primes.push(13);
primes.push(17.0);

2

3

5

7

Memory

@93422313

13

Hidden Class

length: 5

SMI-Packed

const primes = [2, 3, 5, 7];

primes.push(13);
primes.push(17.0);

2.0

3.0

5.0

7.0

Memory

@54223411

13.0

17.0

Hidden Class

length: 6

Double-Packed

const primes = [2, 3, 5, 7];

primes.push(13);
primes.push(17.0);
primes.push(false);

2.0

3.0

5.0

7.0

Memory

@54223411

13.0

17.0

Hidden Class

length: 6

Double-Packed

const primes = [2, 3, 5, 7];

primes.push(13);
primes.push(17.0);
primes.push(false);

2

3

5

7

Memory

@72419991

13

false

17.0

Hidden Class

length: 7

Object-Packed

const primes = [2, 3, 5, 7];

primes[5] = 13;

2

3

5

7

Memory

@10031234

Hidden Class

length: 4

SMI-Packed

const primes = [2, 3, 5, 7];

primes[5] = 13;

2

3

5

7

Memory

@561222101

13

Hidden Class

length: 6

Holey-SMI

const primes = [2, 3, 5, 7];

primes[10000] = 104729;

Memory

Hidden Class

length: 4

SMI-Packed

2

3

5

7

@10031234

const primes = [2, 3, 5, 7];

primes[10000] = 104729;

Memory

Hidden Class

length: 10001

Holey-SMI

2

3

5

7

@10031234

Recap

https://github.com/thlorenz/v8-perf/blob/master/data-types.md

http://jayconrod.com/posts/52/a-tour-of-v8-object-representation

The Dark Side of JavaScript

By Ali Arafati

The Dark Side of JavaScript

  • 628