Closed
Bug 900849
Opened 11 years ago
Closed 10 years ago
Polymorphic inlining shouldn't ignore own properties and type objects known to be interpreted functions
Categories
(Core :: JavaScript Engine: JIT, defect)
Core
JavaScript Engine: JIT
Tracking
()
RESOLVED
FIXED
mozilla38
People
(Reporter: mbx, Assigned: jandem)
References
Details
(Whiteboard: [Shumway])
Attachments
(2 files, 1 obsolete file)
(deleted),
application/x-javascript
|
Details | |
(deleted),
patch
|
djvj
:
review+
|
Details | Diff | Splinter Review |
Setting named properties on array objects de-optimize all future array accesses. I suspect the JS engine panics whenever a named property is set on an array and invalidates code. See attached example. If "Test 2" is commented out performance is fine, otherwise array accesses slow down by a factor of ~30X. V8 has similar behavior, but it appears to be worse. In SM, this appears to happen when you override a property defined on Array.prototype, in V8 this happens for any named properties set on array objects.
Reporter | ||
Comment 1•11 years ago
|
||
Calling a cloned version of "accessIndirect" in Test 3 avoids the problem, so I'm guessing the issue here is that "accessIndirect" gets invalidated once the array shape changes and never gets recompiled.
Comment 2•11 years ago
|
||
There're 2 main things here:
(1) Inlining non-singleton-typed functions (i.e., functions that aren't defined in the global scope).
(2) ICs installed because of context insensitivity.
(1) needs some TI background. Object, functions included, types are either singleton or non-singleton, singleton here meaning we can get to the single function having the type. Global functions are singleton typed, functions created inside other functions are not. Because of bug 883973, inlining of non-singleton type functions is turned off. This means the |indexGet| that lives on the arrays themselves (not on the prototype), since they're being created inside functions, can't be inlined.
(2) There's only one copy of |indirectAccess| but 3 different array objects with different allocation site-keyed types are passed to it, so getting the |indexGet| property requires an IC. This is a slowdown that can't really be avoided at the moment without manual cloning. It also plays into (1). I *think* that if |indexGet| *could* be inlined, we would be able to compile a poly function dispatch inline despite there being 2 different targets.
Comment 3•11 years ago
|
||
Comment 4•11 years ago
|
||
(In reply to Boris Zbarsky (:bz) from comment #3)
> Hmm. Comment 2 is pretty specific to this testcase's use of polymorphic
> indexGet, but comment 0 and the testcase claim this is a general named prop
> problem. Which is correct?
Comment 2 is my attempt at explaining what I saw in the engine causing the slowdown. I think mbx's comment is how it looks from the outside, without knowing more about what Ion is doing exactly.
Comment 5•11 years ago
|
||
So bug 893038 turned inlining of non-singleton typed functions back on. This test case is still slow though, because to be able to inline polymorphic targets, some very specific criteria must be met: all targets must be singleton typed and live on the prototypes of the set of receiver objects.
That is, in this example, all versions of |indexGet| must be singleton typed and must live on the [[Prototype]] of all 3 arrays. This is clearly not true, so Ion doesn't do a polymorphic inline.
Short term workaround is to ensure that each callsite to |indexGet| is monomorphic, preferably both in the receiver and the property. Medium term fix would be to support polymorphic inlining for non-singleton typed objects. Long term fix is to deal with context sensitivity somehow.
Comment 6•11 years ago
|
||
CC'ing djvj since he wrote the poly inline stuff afaik.
Updated•11 years ago
|
Summary: Named properties on arrays de-optimize future accesses. → Polymorphic inlining shouldn't ignore own properties and type objects known to be interpreted functions
Updated•10 years ago
|
Blocks: shumway-m4
Comment 7•10 years ago
|
||
Just re-tested this:
SM:
Access Indirect: 36
Access Indirect Override: 845
Access Indirect: 882
V8:
Access Indirect: 53
Access Indirect Override: 117
Access Indirect: 102
JSC:
Access Indirect: 42
Access Indirect Override: 522
Access Indirect: 3897
I.e., we're fastest by a substantial margin until we deoptimize. After that, we're terribly slow, though not as terribly as JSC is. Note that V8 also takes a hit, but only to about 2x, not close to 25x like us.
Updated•10 years ago
|
Assignee: general → nobody
Comment 8•10 years ago
|
||
Jandem, is there anything we can do about this?
Component: JavaScript Engine → JavaScript Engine: JIT
Flags: needinfo?(jdemooij)
OS: Mac OS X → All
Hardware: x86 → All
Assignee | ||
Comment 9•10 years ago
|
||
(In reply to Till Schneidereit [:till] from comment #8)
> Jandem, is there anything we can do about this?
Sorry for the late response. Shu is right and the polymorphic inlining needs to handle the lambda case. Will see how hard this is.
Assignee | ||
Updated•10 years ago
|
Assignee: nobody → jdemooij
Status: NEW → ASSIGNED
Assignee | ||
Comment 10•10 years ago
|
||
This patch makes polymorphic inlining work with lambdas, it turned out to be pretty straight-forward.
For the attached micro-benchmark:
Before / After / V8
Access Indirect: 21 / 21 / 31
Access Indirect Override: 603 / 79 / 85
Access Indirect: 639 / 107 / 111
So it's a lot faster than before and a bit faster than V8 in all cases.
Flags: needinfo?(jdemooij)
Attachment #8549914 -
Flags: review?(kvijayan)
Comment 11•10 years ago
|
||
\o/
Assignee | ||
Comment 12•10 years ago
|
||
Just realized the previous patch had a change that isn't necessary.
Attachment #8549914 -
Attachment is obsolete: true
Attachment #8549914 -
Flags: review?(kvijayan)
Attachment #8550228 -
Flags: review?(kvijayan)
Comment 13•10 years ago
|
||
Comment on attachment 8550228 [details] [diff] [review]
Patch
Review of attachment 8550228 [details] [diff] [review]:
-----------------------------------------------------------------
Awesome perf improvement there :)
::: js/src/jit/MIR.h
@@ +9373,5 @@
> // Map from JSFunction* -> MBasicBlock.
> struct Entry {
> JSFunction *func;
> + // func's TypeObject or nullptr if func is a singleton. If non-null,
> + // FunctionDispatch should guard on this, instead of func.
The comment here is unclear. The first 'if' refers to the func field, the second 'if' to the funcType field.
Something like the following might be clearer:
// if |func| has a singleton type, |funcType| is null. Otherwise, |funcType| holds the TypeObject for |func|, and dispatch guards on the type instead of directly on the function.
Attachment #8550228 -
Flags: review?(kvijayan) → review+
Assignee | ||
Comment 14•10 years ago
|
||
Comment 15•10 years ago
|
||
Backed out in https://hg.mozilla.org/integration/mozilla-inbound/rev/99ee26ed26e5
I'm suspicious that devtools tests weren't happy, since there was a sudden increase in their constant level of failure and a couple of new unfiled failures, but they're always a bit iffy and that was nothing but suspicion.
b2g desktop linux64 gaia unit test (that's Gu), calendar/test/unit/interval_tree_test.js timed out 100% on ten tries on your push, timed out 0% on the push before. The fact that it was green on the push above you, and then went back to timing out on every push above that... I can't explain.
Assignee | ||
Comment 16•10 years ago
|
||
(In reply to Phil Ringnalda (:philor) from comment #15)
> b2g desktop linux64 gaia unit test (that's Gu),
> calendar/test/unit/interval_tree_test.js timed out 100% on ten tries on your
> push, timed out 0% on the push before. The fact that it was green on the
> push above you, and then went back to timing out on every push above that...
> I can't explain.
This one was actually a crash; maybe the crash reporter confused the test harness. Just pushed a fix for that to Try:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=1223e97761ad
(Full Try run to make sure I don't miss something this time.)
Assignee | ||
Comment 17•10 years ago
|
||
Comment 18•10 years ago
|
||
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla38
You need to log in
before you can comment on or make changes to this bug.
Description
•