Closed
Bug 606892
Opened 14 years ago
Closed 13 years ago
TM: most Function guards are unnecessary
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
RESOLVED
WONTFIX
People
(Reporter: n.nethercote, Assigned: n.nethercote)
References
Details
When we unbox an object, if it's a non-function object at trace time, we emit a guard that exits if the object is a function, like this:
ldi24 = ldi.objclasp ldi23[4]
guard(class is Function)4 = eqi ldi24, clasp2/*......*/
xt11: xt guard(class is Function)4 -> pc=...... imacpc=(nil) sp+48 rp+0 (......)
However, we almost always test the non-function object is another guard
shortly afterwards. For example, if we access an array-of-arrays we have
code like this:
ldi24 = ldi.objclasp ldi23[4]
guard(class is Function)4 = eqi ldi24, clasp2/*......*/
xt11: xt guard(class is Function)4 -> pc=...... imacpc=(nil) sp+48 rp+0 (......)
sti.sp sp[32] = ldi23
sti.sp sp[40] = ldi1
guard(class is Array)7 = eqi ldi24, clasp/*......*/
xf19: xf guard(class is Array)7 -> pc=...... imacpc=(nil) sp+48 rp+0 (......)
The (weak) 'is Function' guard is subsumed by the (strong) 'is Array' guard.
Similarly, if we access a property of an object we see code like this:
ldi6 = ldi.objclasp ldi5[4]
clasp2 = immi 0x83b1500
guard(class is Function) = eqi ldi6, clasp2/*0x83b1500*/
xt1: xt guard(class is Function) -> pc=0x8cbc383 imacpc=(nil) sp+16 rp+0 (GuardID=005)
sti.sp sp[0] = ldi5
objShape = ldi.objshape ldi5[12]
immi2 = immi 456
guard_kshape = eqi objShape, immi2/*456*/
xf5: xf guard_kshape -> pc=0x8cbc384 imacpc=(nil) sp+8 rp+0 (GuardID=006)
I think the shape guard again subsumes the 'is Function' guard (though I'm less
certain; the array-of-array case above is clear, whereas this case requires
knowledge of how shapes work).
I tried just removing all the 'is Function' guards; only two jit-tests
failed. So they're rarely necessary. Can we find a way to remove the
unnecessary ones?
As a single data point, ai-astar (run under -j) executes 15% fewer
instructions with the 'is Function' guards removed -- it has three
unnecessary ones in its hottest loop.
Comment 1•14 years ago
|
||
An object's shape depends on its prototype object's identity, so a function object whose proto is Function.prototype is enough to determine that its shape cannot match any non-function object's shape. Setting __proto__ assigns a unique, "own" shape, so that's not an issue either.
Thus if at record time we emit a shape guard for a non-function object, we know no function object can match it, and vice versa.
Aside: most functions have the same shape.
/be
Comment 2•14 years ago
|
||
Good discovery! It seems difficult to kill in the forward pass, since, at least from the uses of unbox_value I skimmed, its not clear when we are about to emit the stronger guard.
I wonder if we could add a backwards pass which keeps a table of live (LIns*, guard condition) pairs and uses this table to kill guards on LIns*'s which are implied by a live condition. Guard instructions would add entries to the table and uses of LIns*'s would kill entries in the table. To just solve the problem at hand, the "guard condition" could simply be the two-element ordered set "guard on specific non-function class" > "guard not a function".
Assignee | ||
Comment 3•14 years ago
|
||
A pass in the LIR reader pipeline (which reads the code backwards) is the obvious thing. NJ compile time is less of an issue than it used to be because with '-j -m -p' fewer things in SunSpider trace these days.
Assignee | ||
Comment 4•13 years ago
|
||
TM's days are numbered: WONTFIX.
Status: ASSIGNED → RESOLVED
Closed: 13 years ago
Resolution: --- → WONTFIX
You need to log in
before you can comment on or make changes to this bug.
Description
•