Closed
Bug 1138693
Opened 10 years ago
Closed 10 years ago
Assertion failure: index < length_, at jit/FixedList.h:82 or Crash [@ ??]
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
VERIFIED
FIXED
mozilla39
| Tracking | Status | |
|---|---|---|
| firefox37 | --- | unaffected |
| firefox38 | --- | unaffected |
| firefox39 | --- | verified |
| firefox-esr31 | --- | unaffected |
| b2g-v1.4 | --- | unaffected |
| b2g-v2.0 | --- | unaffected |
| b2g-v2.0M | --- | unaffected |
| b2g-v2.1 | --- | unaffected |
| b2g-v2.1S | --- | unaffected |
| b2g-v2.2 | --- | unaffected |
| b2g-master | --- | fixed |
People
(Reporter: decoder, Assigned: nbp)
Details
(5 keywords, Whiteboard: [jsbugmon:update,ignore])
Attachments
(2 files)
|
5.00 KB,
patch
|
jandem
:
review+
nbp
:
checkin+
|
Details | Diff | Splinter Review |
|
3.80 KB,
patch
|
jandem
:
review+
|
Details | Diff | Splinter Review |
The following testcase crashes on mozilla-central revision eea6188b9b05 (build with --enable-optimize --enable-posix-nspr-emulation --enable-valgrind --enable-gczeal --disable-debug, run with --no-threads --ion-eager):
var T = TypedObject;
var ST = new T.StructType({x:T.int32});
function check(v) {
return v.toSource();
}
function test() {
var fake = { toSource: ST.toSource };
try {
check(fake);
} catch (e) {}
}
test();
var uint8 = TypedObject.uint8;
function runTests() {
uint8.toSource();
}
runTests();
test();
Backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x00000000017b7ea0 in ?? ()
#0 0x00000000017b7ea0 in ?? ()
#1 0x00000000007230a8 in is<js::jit::MPhi> (this=0x17b8bd0) at js/src/jit/MIR.h:747
#2 isPhi (this=0x17b8bd0) at js/src/jit/MIR.h:767
#3 js::jit::EliminatePhis (mir=0x17b38c8, graph=..., observe=js::jit::ConservativeObservability) at js/src/jit/IonAnalysis.cpp:739
#4 0x00000000007aadaf in js::jit::ScalarReplacement (mir=0x17b38c8, graph=...) at js/src/jit/ScalarReplacement.cpp:1073
#5 0x000000000073d3e3 in js::jit::OptimizeMIR (mir=mir@entry=0x17b38c8) at js/src/jit/Ion.cpp:1231
#6 0x000000000073dad9 in js::jit::CompileBackEnd (mir=mir@entry=0x17b38c8) at js/src/jit/Ion.cpp:1580
#7 0x000000000073eade in IonCompile (optimizationLevel=<optimized out>, recompile=false, constructing=<optimized out>, osrPc=<optimized out>, baselineFrame=<optimized out>, script=0x0, cx=0x16b7ce0) at js/src/jit/Ion.cpp:1952
#8 js::jit::Compile (cx=cx@entry=0x16b7ce0, script=script@entry=0x7ffff7e5e1f0, osrFrame=osrFrame@entry=0x0, osrPc=osrPc@entry=0x0, constructing=<optimized out>, forceRecompile=forceRecompile@entry=false) at js/src/jit/Ion.cpp:2106
#9 0x000000000073ee03 in js::jit::CanEnter (cx=0x16b7ce0, state=...) at js/src/jit/Ion.cpp:2245
#10 0x0000000000547f88 in js::RunScript (cx=cx@entry=0x16b7ce0, state=...) at js/src/vm/Interpreter.cpp:424
#11 0x00000000005483aa in js::Invoke (cx=cx@entry=0x16b7ce0, args=..., construct=construct@entry=js::NO_CONSTRUCT) at js/src/vm/Interpreter.cpp:517
#12 0x0000000000548f9b in js::Invoke (cx=0x16b7ce0, thisv=..., fval=..., argc=0, argv=<optimized out>, rval=...) at js/src/vm/Interpreter.cpp:554
#13 0x00000000006bb5fd in js::jit::DoCallFallback (cx=0x16b7ce0, frame=0x7fffffffd308, stub_=<optimized out>, argc=0, vp=0x7fffffffd2c8, res=JSVAL_VOID) at js/src/jit/BaselineIC.cpp:9578
[...]
#24 0x0000000000000000 in ?? ()
rax 0x17ba818 24881176
rbx 0x17ba4e8 24880360
rcx 0x1 1
rdx 0x17ba598 24880536
rsi 0x17b8bd0 24873936
rdi 0x17b8bd0 24873936
rbp 0x17b8bd0 24873936
rsp 0x7fffffffbca8 140737488338088
r8 0x2 2
r9 0x20 32
r10 0x17ba7d8 24881112
r11 0x17ba4a8 24880296
r12 0x1 1
r13 0x2 2
r14 0x17b56a8 24860328
r15 0x17ba7f8 24881144
rip 0x17b7ea0 24870560
=> 0x17b7ea0: pushq $0x17ba8
0x17b7ea5: add %al,(%rax)
Marking this s-s because the assertion indicates some out-of-bounds access.
Comment 1•10 years ago
|
||
JSBugMon is down so NI from nbp because ScalarReplacement is on the stack.
Flags: needinfo?(nicolas.b.pierron)
| Assignee | ||
Comment 2•10 years ago
|
||
I am unable to reproduce this issue with either a debug/optimized build while compiling with clang/gcc4.8.
Running multiple times does not show intermittent behaviour.
Flags: needinfo?(nicolas.b.pierron)
| Assignee | ||
Comment 4•10 years ago
|
||
clang version 3.3 (tags/RELEASE_33/final)
gcc (GCC) 4.8.2
Decoder mention that he was no longer able to reproduce it on tip, so I will try to see if I can reproduce it on top of the revision mentionned in comment 0.
Flags: needinfo?(nicolas.b.pierron)
| Reporter | ||
Updated•10 years ago
|
Flags: needinfo?(choller)
| Assignee | ||
Comment 5•10 years ago
|
||
I can reproduce this issue on top of revision eea6188b9b05.
I will investigate.
| Assignee | ||
Comment 6•10 years ago
|
||
So far the problem seems to be that DescrToSource does
UnsafeGetStringFromReservedSlot(this, 1);
which is inlined as a MLoadFixedSlot, where |this| is a MNewObject which has the following template object:
object 0x7ffff7e6d1f0
class 0x150a890 Object
flags:
proto <Object at 0x7ffff7e5b020>
parent <global object at 0x7ffff7e5a060>
properties:
((js::Shape *) 0x7ffff7e7de20) enumerate JSString* (0x7ffff7e1c970) = Latin1Char * (0x7ffff7e1c978) = "toSource"
: slot 0 = undefined
Apparently, MCallOptimize does not guard on the object type before doing the MLoadFixedSlot(slot = 1).
| Assignee | ||
Comment 7•10 years ago
|
||
Ok, the problem is simple, Scalar Replacement is eager to replace the MLoadFixedSlot from the MNewObject, even if the path which is being optimized can never happen. This problem is likely to exists since the introduction of Scalar Replacement.
| Assignee | ||
Comment 8•10 years ago
|
||
This patch add inevitable bailouts on the paths where we saw Load/Store
instructions which are making references to slots which are not defined as
part of the shape of the NewObject.
This is not a big deal, as these branches are likely to be removed by UCE
(within GVN).
The problem seen here is that the self-hosted code has guards to check that
the object is correct, before doing any operations. These guards are
replaced by constants when the function calls are inlined. Unfortunately,
Scalar replacement has to run before the Apply Types phase, which runs
before UCE (within GVN), and thus see both branches, including the dead-one.
Attachment #8572730 -
Flags: review?(jdemooij)
| Assignee | ||
Comment 9•10 years ago
|
||
Attachment #8572731 -
Flags: review?(jdemooij)
| Reporter | ||
Updated•10 years ago
|
Whiteboard: [jsbugmon:update,bisect] → [jsbugmon:update,ignore]
| Reporter | ||
Comment 10•10 years ago
|
||
JSBugMon: The testcase found in this bug no longer reproduces (tried revision 993eb76a8bd6).
JSBugMon: Bisection requested, result:
autoBisect shows this is probably related to the following changeset:
The first bad revision is:
changeset: https://hg.mozilla.org/mozilla-central/rev/2a0481539f38
user: Nicolas B. Pierron
date: Thu Feb 26 16:18:41 2015 +0100
summary: Bug 1129313 - Scalar Replacement: Remove PostWriteBarrier at the same time as the stores. r=h4writer
This iteration took 145.106 seconds to run.
| Assignee | ||
Comment 11•10 years ago
|
||
(In reply to Christian Holler (:decoder) from comment #10)
> The first bad revision is:
> summary: Bug 1129313 - Scalar Replacement: Remove PostWriteBarrier at
> the same time as the stores. r=h4writer
I think the problem existed before this, as this patch only re-enabled scalar replacement after it got accidently disabled by the addition of new MIR nodes.
Flags: needinfo?(nicolas.b.pierron)
Comment 12•10 years ago
|
||
Comment on attachment 8572730 [details] [diff] [review]
Check if Loads can be optimized by Scalar Replcement.
Review of attachment 8572730 [details] [diff] [review]:
-----------------------------------------------------------------
Looks good. Some comments below that we can maybe fix in a separate patch.
::: js/src/jit/MIR.h
@@ +3180,5 @@
> replaceOperand(slot + 1, def);
> }
>
> + bool hasFixedSlot(uint32_t slot) const {
> + return slot < numSlots() && slot < numFixedSlots();
I think it'd be nice to have the invariant numFixedSlots() <= numSlots(), to make it easier to reason about the code and so that we only need to check numFixedSlots().
@@ +3192,5 @@
> setSlot(slot, def);
> }
>
> + bool hasDynamicSlot(uint32_t slot) const {
> + return numFixedSlots() < numSlots() && slot < numSlots() - numFixedSlots();
Then we could get rid of the && LHS here too.
Attachment #8572730 -
Flags: review?(jdemooij) → review+
Comment 13•10 years ago
|
||
Comment on attachment 8572731 [details] [diff] [review]
Add comments and test.
Review of attachment 8572731 [details] [diff] [review]:
-----------------------------------------------------------------
::: js/src/jit/ScalarReplacement.cpp
@@ +437,5 @@
> state_ = BlockState::Copy(alloc_, state_);
> state_->setFixedSlot(ins->slot(), ins->value());
> ins->block()->insertBefore(ins->toInstruction(), state_);
> } else {
> + // UnsafeSetReserveSlot can inject baked-in slots which are guarded by
Nit: maybe s/inject/access/ ?
Attachment #8572731 -
Flags: review?(jdemooij) → review+
Updated•10 years ago
|
status-firefox38:
--- → unaffected
status-firefox-esr31:
--- → unaffected
| Assignee | ||
Updated•10 years ago
|
Assignee: nobody → nicolas.b.pierron
Status: NEW → ASSIGNED
| Assignee | ||
Comment 14•10 years ago
|
||
| Assignee | ||
Updated•10 years ago
|
Attachment #8572730 -
Flags: checkin+
Comment 15•10 years ago
|
||
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla39
Updated•10 years ago
|
status-b2g-v1.4:
--- → unaffected
status-b2g-v2.0:
--- → unaffected
status-b2g-v2.0M:
--- → unaffected
status-b2g-v2.1:
--- → unaffected
status-b2g-v2.1S:
--- → unaffected
status-b2g-v2.2:
--- → unaffected
status-b2g-master:
--- → fixed
status-firefox37:
--- → unaffected
| Reporter | ||
Updated•10 years ago
|
Status: RESOLVED → VERIFIED
| Reporter | ||
Comment 16•10 years ago
|
||
JSBugMon: This bug has been automatically verified fixed.
Updated•10 years ago
|
Group: core-security
Comment 17•10 years ago
|
||
Comment 19•10 years ago
|
||
You need to log in
before you can comment on or make changes to this bug.
Description
•