@mraleph
Excelsior JET
V8
Dart VM
Excelsior JET
V8
Dart VM
Vector.prototype.length = function () {
  return Math.sqrt(this.x * this.x +
                   this.y * this.y);
};
          representation
resolution
redundancy
obj.prop
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
          
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
          
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
          
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
          
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
          
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
          
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
          
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
          
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
          
function Point(x, y) {
  this.x = x;
  this.y = y;
}
var p1 = new Point(1, 2);
var p2 = new Point(3, 4);
p2.z = 5;
          
var arr = [];
for (var i = 0; i < 101; i++)
  arr[i] = Math.sqrt(i);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
arr[3] = "xyz";
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
arr[3] = "xyz";
          
var arr = [];
arr[0] = Math.sqrt(0);
arr[1] = Math.sqrt(1);
arr[2] = Math.sqrt(2);
arr[3] = "xyz";
          
function Vec2(x, y) {
  this.x = x;
  this.y = y;
}
var v = new Vec2(0.1, 0.2);
v.x += 1;
v.y += 1;
          
function Vec2(x, y) {
  this.x = x;
  this.y = y;
}
var v = new Vec2(0.1, 0.2);
v.x += 1;
v.y += 1;
          
function Vec2(x, y) {
  this.x = x;
  this.y = y;
}
var v = new Vec2(0.1, 0.2);
v.x += 1;
v.y += 1;
          
function Vec2(x, y) {
  this.x = x;
  this.y = y;
}
var v = new Vec2(0.1, 0.2);
v.x += 1; v.y += 1;
while (true) v.x;
          
function Vec2(x, y) {
  this.x = x;
  this.y = y;
}
var v = new Vec2(0.1, 0.2);
v.x += 1; v.y += 1;
while (true) v.x;
          
function Vec2(x, y) {
  this.x = x;
  this.y = y;
}
var v = new Vec2(0.1, 0.2);
v.x += 1; v.y += 1;
while (true) v.x;
          
function Vec2(x, y) {
  this.x = x;
  this.y = y;
}
var v = new Vec2(0.1, 0.2);
v.x += 1; v.y += 1;
while (true) v.x;
          
function K() { }
K.prototype.f = function foo() { };
K.prototype.g = function bar() { };
          
function K() { }
K.prototype.f = function foo() { };
K.prototype.g = function bar() { };
// How hidden class of K.prototype looks like?
          
function K() { }
K.prototype.f = function foo() { };
K.prototype.g = function bar() { };
// How hidden class of K.prototype looks like?
          
function K() { }
K.prototype.f = function foo() { };
K.prototype.g = function bar() { };
// Want it to be more 'class'-like
          
function K() { }
K.prototype.f = function foo() { };
K.prototype.g = function bar() { };
          
function K() { }
K.prototype.f = function foo() { };
K.prototype.g = function bar() { };
// Now it's more like vtbl!
          
var o1 = {};
o1.f = function () { };
var o2 = {};
o2.f = function () { };
for (var i = 0; i < 1e7; i++) o1.f();
for (var i = 0; i < 1e7; i++) o2.f();
          
;; Compiled code
mov eax, obj
mov ecx, "foo"
call LoadIC_Initialize
          
// Runtime system.
function LoadIC_Initialize(obj, prop) {
  var lookupResult = obj.lookup(prop);
  patch(lookupResult.compile());
  return lookupResult.value;
}
          
// Runtime system.
function LoadIC_Initialize(obj, prop) {
  var lookupResult = obj.lookup(prop);
  patch(lookupResult.compile());
  return lookupResult.value;
}
          
;; Compiled LoadIC Stub
0xabcdef:
cmp [eax - 1], klass0
jnz LoadIC_Miss
mov eax, [eax + 11]
ret
;; Compiled code
mov eax, obj
mov ecx, "foo"
call 0xabcdef ;; patched!
          
;; Compiled LoadIC Stub
0xabcdef:
cmp [eax - 1], klass0
jnz LoadIC_Miss
mov eax, [eax + 11]
ret
;; Compiled code
mov eax, obj
mov ecx, "foo"
call 0xabcdef ;; patched!
          
;; Compiled LoadIC Stub
0xabcdef:
cmp [eax - 1], klass0
jnz LoadIC_Miss
mov eax, [eax + 11]
ret
;; Compiled code
mov eax, obj
mov ecx, "foo"
call 0xabcdef ;; patched!
          
;; Compiled LoadIC Stub
0xabcdef:
cmp [eax - 1], klass0
jnz LoadIC_Miss
mov eax, [eax + 11]
ret
;; Compiled code
mov eax, obj
mov ecx, "foo"
call 0xabcdef ;; patched!
          
;; Compiled LoadIC Stub
0xabcdef:
cmp [eax - 1], klass0
jnz LoadIC_Miss
mov eax, [eax + 11]
ret
;; Compiled code
mov eax, obj
mov ecx, "foo"
call 0xabcdef ;; patched!
          
function ICStub($data, receiver, ...) {
  var target = $data.get(receiver.klass)
  if (target === null) {
    target = HandleMiss($data, receiver, ...)
  }
  return target(receiver, ...)
}
          |  |  | 
|  |  | 
Vector.prototype.length = function () {
  return Math.sqrt(this.x * this.x +
                   this.y * this.y);
};
          
Vector.prototype.length = function () {
  return Math.sqrt(this.x * this.x +
                   this.y * this.y);
};
          fast ⊕ slow
"it's a trap"
getInferredTypeOf(element) {
  element = element.implementation;
  return typeInformations.putIfAbsent(element, () {
    return new ElementTypeInformation(element, this);
  });
}
getInferredTypeOf(element) {
  element = element.implementation;
  return typeInformations.putIfAbsent(element, () {
    return new ElementTypeInformation(element, this);
  });
}
class _HashMap {
  @jit.AlwaysInline
  putIfAbsent(key, @jit.AlwaysInline ifAbsent) {
    /* ... */
  }
}
@jit.NeverInline
getInferredTypeOf(element) {
  /* ... */
}
class ListMixin {  
  forEach(f) { /* ... */ }
}
class List with ListMixin { }
class Int32List with ListMixin { }
class Float64List with ListMixin { }
class ListMixin {
  @jit.ReceiverPolymorphic
  forEach(f) {
    /* ... */
  }
}small yet expressive core language
optimization hints
fast ⊕ slow decomposition (guards, assumptions, deopts)
ability to precook fast paths at build step