Closed
Bug 1059426
Opened 10 years ago
Closed 10 years ago
IonMonkey: ArrayIndexOf repeatedly bails out without invalidating if second argument is non-primitive
Categories
(Core :: JavaScript Engine: JIT, defect)
Core
JavaScript Engine: JIT
Tracking
()
RESOLVED
FIXED
mozilla35
People
(Reporter: djvj, Assigned: jschulte)
References
Details
Attachments
(1 file, 1 obsolete file)
(deleted),
patch
|
djvj
:
review+
|
Details | Diff | Splinter Review |
The following test case shows the issue:
function makeArray() {
var arr = new Array(5000);
for (var i = 0; i < 5000; i++)
arr[i] = (i % 27);
return arr;
}
function main() {
var arr = makeArray();
for (var j = 0; j < 5; j++) {
for (var i = 0; i < 5000; i++)
arr.indexOf(5, new Number(i));
}
}
main();
Run this, and we see roughly 20,000 bailouts. A sample of the bailout:
[BaselineBailouts] Bailing to baseline self-hosted:122 (IonScript=0x2f4d310) (FrameType=2)
[BaselineBailouts] Reading from snapshot offset 93 size 264
[BaselineBailouts] Incoming frame ptr = 0x7fff04015130
[BaselineBailouts] Callee function (self-hosted:122)
[BaselineBailouts] Not constructing!
[BaselineBailouts] Restoring frames:
[BaselineBailouts] FrameNo 0
[BaselineBailouts] Unpacking self-hosted:122
[BaselineBailouts] [BASELINE-JS FRAME]
[BaselineBailouts] WRITE_PTR 0x2f46d48/0x7fff04015128 PrevFramePtr 0x7fff04015168
[BaselineBailouts] SUB_064 0x2f46d08/0x7fff040150e8 BaselineFrame
[BaselineBailouts] FrameSize=112
[BaselineBailouts] ScopeChain=0x7f3db0846040
[BaselineBailouts] ReturnValue=fff9000000000000
[BaselineBailouts] Is function!
[BaselineBailouts] thisv=fffc7f3db0a00090
[BaselineBailouts] frame slots 10, nargs 1, nfixed 5
[BaselineBailouts] arg 0 = fff8800000000005
[BaselineBailouts] WRITE_VAL 0x2f46d00/0x7fff040150e0 FixedValue fffc7f3db0a00090
[BaselineBailouts] WRITE_VAL 0x2f46cf8/0x7fff040150d8 FixedValue fff8800000001388
[BaselineBailouts] WRITE_VAL 0x2f46cf0/0x7fff040150d0 FixedValue fff9000000000000
[BaselineBailouts] WRITE_VAL 0x2f46ce8/0x7fff040150c8 FixedValue fff9000000000000
[BaselineBailouts] WRITE_VAL 0x2f46ce0/0x7fff040150c0 FixedValue fffa000000000009
[BaselineBailouts] pushing 0 expression stack slots
[BaselineBailouts] Resuming at pc offset 67 (op getintrinsic) (line 127) of self-hosted:122
[BaselineBailouts] Bailout kind: Bailout_NonPrimitiveInput
[BaselineBailouts] Adjusted framesize -= 0: 112
[BaselineBailouts] Set resumeAddr=0x7f3db3b60af6
[BaselineBailouts] Done restoring frames
[BaselineBailouts] Done restoring frames
[BaselineBailouts] Got pc=0x2e4ccfc
[BaselineBailouts] Restored outerScript=(self-hosted:122,43) innerScript=(self-hosted:122,43) (bailoutKind=7)
The source code being bailed out to is:
function ArrayIndexOf(searchElement ) {
var O = ToObject(this);
var len = ((O.length) >>> 0);
if (len === 0)
return -1;
var n = arguments.length > 1 ? ToInteger(arguments[1]) : 0;
....
The Bailout_NonPrimitiveInput and the line of the bailout (containing ToInteger(arguments[1])) suggests that we are bailing while converting arguments[1] to an integer.
This SHOULD be triggering an invalidation and an ion-recompile with looser type information.
Assignee | ||
Comment 1•10 years ago
|
||
Improves test case by ~10x.
Attachment #8489148 -
Flags: feedback?(kvijayan)
Reporter | ||
Comment 2•10 years ago
|
||
Comment on attachment 8489148 [details] [diff] [review]
v1.patch
Review of attachment 8489148 [details] [diff] [review]:
-----------------------------------------------------------------
Nice. Some minor style nits, but nice job finding the issue!
::: js/src/jit/MCallOptimize.cpp
@@ +2047,5 @@
> + MIRType type = callInfo.getArg(0)->type();
> + // Only fast-path if we know the input is in the int32 range and we're not
> + // likely to bailout.
> + if (getInlineReturnType() != MIRType_Int32 ||
> + (!IsNumberType(type) && type != MIRType_Null && type != MIRType_Boolean))
Split this up into two conditionals, with appropriate comments on each. The first is checking the return typeset, the second is checking an operand type. Lumping the two together implies confuses them, so:
// Only optimize cases where input is number, null, or boolean
if (!IsNumberType(type) && ...)
return InliningStatus_NotInlined;
// Only optimize cases where output is int32
if (getInlineReturnType() != MIRType_Int32)
return InliningStatus_NotInlined;
Attachment #8489148 -
Flags: feedback?(kvijayan) → feedback+
Assignee | ||
Comment 3•10 years ago
|
||
Should I state in the comment, that MToInt32 will bail on other input, or is it fine like that?
Attachment #8489148 -
Attachment is obsolete: true
Attachment #8490260 -
Flags: review?(kvijayan)
Reporter | ||
Comment 4•10 years ago
|
||
Comment on attachment 8490260 [details] [diff] [review]
v2.patch
Review of attachment 8490260 [details] [diff] [review]:
-----------------------------------------------------------------
No, I think the comments are good as is. Thanks for working on this! I'll run this through try.
Attachment #8490260 -
Flags: review?(kvijayan) → review+
Reporter | ||
Comment 5•10 years ago
|
||
Assignee | ||
Updated•10 years ago
|
Assignee: nobody → j_schulte
Status: NEW → ASSIGNED
Keywords: checkin-needed
OS: Windows 8.1 → All
Hardware: x86_64 → All
Comment 6•10 years ago
|
||
Keywords: checkin-needed
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla35
Comment 8•10 years ago
|
||
Just a drive-by comment. This will also deoptimize when we encounter a typeset having multiple types (that don't bail) e.g. if the inputType is "null int32", we won't do the special case.
What about using "callInfo.getArg(0)->mightBe(X)" with X checking all cases that can bail (String|Symbol|Object|Undefined) to decide to not inline ToInteger?
You need to log in
before you can comment on or make changes to this bug.
Description
•