3 ms·
V8 can inline at bimorphic (trimorphic and quadmorphic :)) site. That's explicitly stated in the post: see the part about decision tree building. When you inlin
by mraleph 12y ago
V8 can inline at bimorphic (trimorphic and quadmorphic :)) site. That's explicitly stated in the post: see the part about decision tree building. When you inline at polymorphic site in the worst case you have branching flow graph that decides which particular operation to pick. Rewriting example from the post into Java terminology yields:
if (o.getClass() == A.class) {
// inlined variant that matches A
} else if (o.getClass() == B.class) {
// inlined variant that matches B
} else if (o.getClass() == C.class) {
// inlined varint that matches C
} else {
$Deoptimize(); // -> exit, this never returns.
}
[Note: `$GetShape(o)` became `o.getClass()`]
V8 can do this. If inlined variants for A, B and C are all the same V8 can also do
// Check that we are either A, B, C
if (o.getClass() != A.class &&
o.getClass() != B.class &&
o.getClass() != C.class) {
$Deoptimize(); // -> exit, this never returns
}
/* inlined variant for A, B, C */
However in both cases you pay penalty for the conditional control flow and in the first case V8 is unable to merge subsequent decision trees in any way to eliminate redundancy between them so `o.x + o.y` might end up compiled into something like (assuming polymorphic code that uses objects of shapes {x, y} and {y, x}):
int o_x;
if (o.getClass() == A.class) {
o_x = $LoadByOffset(o, 12);
} else if (o.getClass() == B.class) {
o_x = $LoadByOffset(o, 16);
} else {
$Deoptimize(); // -> exit, this never returns.
}
int o_y;
if (o.getClass() == A.class) {
o_y = $LoadByOffset(o, 16);
} else if (o.getClass() == B.class) {
o_y = $LoadByOffset(o, 12);
} else {
$Deoptimize(); // -> exit, this never returns.
}
o_x + o_y
That's a lot of repetitive branching right here. Arguably the code quality can be substantially improved by merging ifs like this:
int o_x, o_y;
if (o.getClass() == A.class) {
o_x = $LoadByOffset(o, 12);
o_y = $LoadByOffset(o, 16);
} else if (o.getClass() == B.class) {
o_x = $LoadByOffset(o, 16);
o_y = $LoadByOffset(o, 12);
} else {
$Deoptimize(); // -> exit, this never returns.
}
o_x + o_y
but at the moment V8 does not do this hence the penalty is higher.