Closed Bug 618577 Opened 10 years ago Closed 10 years ago

TM: "Assertion failure: 0,"

Categories

(Core :: JavaScript Engine, defect)

x86
Linux
defect
Not set
critical

Tracking

()

RESOLVED FIXED
Tracking Status
blocking2.0 --- -
status2.0 --- wanted

People

(Reporter: gkw, Assigned: njn)

References

Details

(Keywords: assertion, regression, testcase, Whiteboard: fixed-in-tracemonkey)

Attachments

(2 files)

eval("\
  x=(Uint32Array(eval(\"(/x/)\")));\
  for(a=0;a<8;a++){\
    (x)[7]++\
  }\
")

asserts js debug shell on TM changeset 1002cba2f2d6 with -j at Assertion failure: 0,
blocking2.0: --- → ?
autoBisect shows this is probably related to the following changeset:

The first bad revision is:
changeset:   55722:438afef93fd5
user:        Andreas Gal
date:        Wed Oct 20 22:41:35 2010 -0700
summary:     Remove obsolete wrappedObject extended class hook (604523, r=mrbkap/vlad/dvander).
Blocks: 604523
blocking2.0: ? → -
status2.0: --- → wanted
Assignee: general → brendan
Assignee: brendan → nnethercote
Attached file stack trace
Looks like a constantly-false guard of some sort.
Yep, and there's a great big comment right above that assertion that I wrote to remind myself what to do when it trips :)
Here's a simpler reproducer:

    var x = Uint32Array();
    for (var i = 0; i < 100; i++)
        x[77] = x[77];

The problem is as follows.  We generate this code for the GETELEM:

    typedArrayLength = ldi.tarray/c private[16]
    gtui1 = gtui typedArrayLength, immi1/*7*/
    xt1: xt gtui1 -> exit=0x9d7e56c pc=0x9d79dfb imacpc=(nil) sp+32 rp+0 BRANCH
    sti.sp sp[16] = strict/*0*/

Note: we exit if the index is *within* bounds.  That sounds odd, but it's
because the record-time access was not within bounds, so we assume that later
ones won't be either.  And we return undefined (represented by 0) as the result.

Then later on we have a SETELEM, and it wants to generate this code

    gtui2 = gtui typedArrayLength, immi1/*7*/
    xf1: xf gtui2 -> exit=0x9d7e56c pc=0x9d79dfb imacpc=(nil) sp+32 rp+0 BRANCH

ie. "exit if we're not within bounds".  However, Nanojit is smart enough to
know that if 'xt1' didn't exit, then 'xf1' must exit.  And so the assertion
triggers.

It's an easy fix -- pass in |abortIfAlwaysExits = true| to guard(), which
basically says "yeah, I know this might always exit, and that's ok, just abort
recording and I'll handle it".

Other tweaks:
- Use JS_NOT_REACHED in guard() so that the message is more informative when
  it's hit.

- Give names to some of the inRange tests for type arrays, so that LIR dumps
  are easier to read.
Attachment #497438 - Flags: review?(vladimir)
http://hg.mozilla.org/tracemonkey/rev/91092f078223
Status: NEW → ASSIGNED
Whiteboard: fixed-in-tracemonkey
http://hg.mozilla.org/mozilla-central/rev/91092f078223
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
A testcase for this bug was automatically identified at js/src/jit-test/tests/basic/bug618577.js.
Flags: in-testsuite+
You need to log in before you can comment on or make changes to this bug.