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
•