@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