Closed Bug 1100337 Opened 8 years ago Closed 8 years ago

Assertion failure: buffer_ < end_, at js/src/jit/CompactBuffer.h:55 or Crash [@ CollectJitStackScripts]


(Core :: JavaScript Engine, defect)

Not set



Tracking Status
firefox36 --- affected


(Reporter: decoder, Assigned: shu)



(4 keywords, Whiteboard: [jsbugmon:update][fuzzblocker])

Crash Data


(2 files, 1 obsolete file)

The following testcase crashes on mozilla-central revision a52bf59965a0 (build with --enable-debug --enable-optimize --enable-posix-nspr-emulation --enable-valgrind, run with --thread-count=2 --ion-eager --ion-offthread-compile=off):

function $ERROR(msg) {
    throw new Error("Test262 error: " + msg);
try {
    $ERROR('#1.1: x >>>= 1 throw ReferenceError. Actual: ' + (2 << 4));
} catch (e) {}
var g = newGlobal();
g.parent = this;
g.eval("function f(frame, exc) { f2 = function () { return exc; }; exc = 123; }");
g.eval("new Debugger(parent).onExceptionUnwind = f;");
x = "1";
$ERROR('#1: x = "1"; x <<= 1; x === 2. Actual: ' + (x));


Program terminated with signal 11, Segmentation fault.
#0  0x000000000069db74 in js::jit::CompactBufferReader::readByte (
    this=<optimized out>)
    at js/src/jit/CompactBuffer.h:55
55	        MOZ_ASSERT(buffer_ < end_);
Loading JavaScript value pretty-printers; see js/src/gdb/README.
If they cause trouble, type: disable pretty-printer .* SpiderMonkey
#0  0x000000000069db74 in js::jit::CompactBufferReader::readByte (this=<optimized out>) at js/src/jit/CompactBuffer.h:55
#1  0x000000000061fc35 in readByte (this=<optimized out>) at js/src/jit/CompactBuffer.h:55
#2  readVariableLength (this=<optimized out>) at js/src/jit/CompactBuffer.h:40
#3  readUnsigned (this=<optimized out>) at js/src/jit/CompactBuffer.h:76
#4  js::jit::BaselineScript::nativeCodeForPC (this=0x32afd40, script=<optimized out>, pc=0x32d801c "\231\220\220\210\002ψ\006\214#", slotInfo=0x7fffefad249f) at js/src/jit/BaselineJIT.cpp:682
#5  0x000000000067251b in InitFromBailout (poppedLastSPSFrameOut=0x7fffefad296f, excInfo=<optimized out>, callPC=<synthetic pointer>, nextCallee=0x0, startFrameFormals=..., builder=..., invalidate=true, iter=..., ionScript=<optimized out>, script=0x7feba598cca0, fun=(JSFunction * const) 0x7feba5980840 [object Function "$ERROR"], callerPC=0x12 <Address 0x12 out of bounds>, caller=0x0, cx=0x31545a0) at js/src/jit/BaselineBailouts.cpp:1023
#6  js::jit::BailoutIonToBaseline (cx=0x31545a0, activation=<optimized out>, iter=..., invalidate=true, bailoutInfo=0x7fffefad2960, excInfo=0x7fffefad2b50, poppedLastSPSFrameOut=0x7fffefad296f) at js/src/jit/BaselineBailouts.cpp:1482
#7  0x00000000005b41b3 in js::jit::ExceptionHandlerBailout (cx=0x31545a0, frame=..., rfe=0x7fffefad32e0, excInfo=..., overrecursed=0x7fffefad2bde) at js/src/jit/Bailouts.cpp:201
rax	0x0	0
rbx	0x32d801c	53313564
rcx	0xa70b139d	140650096563101
rdx	0x0	0
rsi	0xa7385aa0	140650099530400
rdi	0xa7384180	140650099523968
rbp	0xefad1f40	140737214488384
rsp	0xefad1f40	140737214488384
r8	0xa83df740	140650116675392
r9	0x632d616c	8247338199356891500
r10	0x6a2f6c61	8246987515394747489
r11	0x0	0
r12	0x32afd40	53148992
r13	0x12e	302
r14	0x32afe50	53149264
r15	0x32d801c	53313564
rip	0x69db74 <js::jit::CompactBufferReader::readByte()+28>
=> 0x69db74 <js::jit::CompactBufferReader::readByte()+28>:	movl   $0x7b,0x0
   0x69db7f <js::jit::CompactBufferReader::readByte()+39>:	callq  0x4048b0 <abort@plt>
Flags: needinfo?(kvijayan)
Whiteboard: [jsbugmon:update,bisect] → [jsbugmon:update]
JSBugMon: Bisection requested, result:
Due to skipped revisions, the first bad revision could be any of:
user:        Shu-yu Guo
date:        Thu Nov 13 14:39:39 2014 -0800
summary:     Bug 1032869 - Part 2: Move debuggee-ness to frames and selectively deoptimize when Debugger needs to observe execution. (r=jimb)

user:        Shu-yu Guo
date:        Thu Nov 13 14:39:40 2014 -0800
summary:     Bug 1062629 - Off-thread compartment debug mode should match main thread compartment debug mode. (r=jimb)

user:        Shu-yu Guo
date:        Thu Nov 13 14:39:40 2014 -0800
summary:     Bug 1063328 - Fix on-stack live iterator handling when bailing out in-place due to debug mode OSR. (r=jandem)

user:        Shu-yu Guo
date:        Thu Nov 13 14:39:40 2014 -0800
summary:     Bug 1063330 - Remove the JS shell's evalInFrame. (r=jimb)

user:        Shu-yu Guo
date:        Thu Nov 13 14:39:40 2014 -0800
summary:     Bug 1032869 - Part 3: Don't consider onExceptionUnwind an all-execution-observing hook. (r=jandem)

This iteration took 363.220 seconds to run.
Needinfo from jimb also because this is jsdbg2. I still see this reproducing.
Flags: needinfo?(jimb)
This triggers quite often, can someone look into this fuzzblocker?
Whiteboard: [jsbugmon:update] → [jsbugmon:update][fuzzblocker]
Shu-yu might have been looking at some related bugs recently... maybe he may also have an idea?
Flags: needinfo?(shu)
Keywords: regression
The bug is that in order to support onExceptionUnwind without deopting all code, whenever there's a live onExceptionUnwind hook, handling exceptions in Ion causes a bail out in place (instead of jumping to a catch/finally block) to Baseline, so that Baseline can do debug mode OSR and call the Debugger hook.

There's been a lot of corner cases in this in-place bailout I didn't think carefully enough through, sorry. :(

This bug is because the test case generate bytecode like so:

00018:   2  throw
00019:   2  retrval

retrval is unreachable, so there is no Baseline code for it. So when trying to bail out in place from the throw, which is a resumeAfter resume point, we assert when searching for the native code for retrval.

I'm not sure on the fix yet. It doesn't matter what we set the return address as, really, because this in-place bailout bails goes to the Baseline exception handler, and will not resume execution in the frame.
Flags: needinfo?(shu)
Flags: needinfo?(kvijayan)
Flags: needinfo?(jimb)
Assignee: nobody → shu
Comment on attachment 8527371 [details] [diff] [review]
Cheat when computing resume address for propagating exception for debug mode in Ion exception handler

Review of attachment 8527371 [details] [diff] [review]:

I am not happy with this super-hacky approach. I don't have any better ones though. :(
Attachment #8527371 - Flags: review?(jdemooij)
Consider a simple function like

  function f() { throw 42; }

The bytecode for this is

  00000:  int8 42
  00002:  throw
  00003:  retrval

JSOP_INT8 generates no native code, and JSOP_RETRVAL is unreachable, and so
generates no code either. So if we bail out in place after JSOP_THROW for
propagating an exception for the Debugger, we try to set the resume PC to be
JSOP_THROW per the first patch. However, since this has the same native code
offset as JSOP_INT8, the frame ends up thinking it's settled on JSOP_INT8.

This patch fixes 2 bugs:

1. When searching for a PC given a native offset, consider the last matching
   entry instead of the first, since PCs that generate no code can't re-enter the
   VM anyways.

2. Pad a nop after the prologue code to distinguish the return address of the
   last NonOp ICEntry inserted in the prologue from the start address of the first
   op, so that in the example above, baselineScriptAndPc won't think the frame is
   settled on JSOP_INT8 because there's a NonOp IC from the prologue with the same
   return address.
Attachment #8528054 - Flags: review?(kvijayan)
Added test.
Attachment #8527371 - Attachment is obsolete: true
Attachment #8527371 - Flags: review?(jdemooij)
Attachment #8528062 - Flags: review?(jdemooij)
Attachment #8528062 - Flags: review?(jdemooij) → review+
Attachment #8528054 - Flags: review?(kvijayan) → review+
Closed: 8 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla37
Target Milestone: mozilla37 → mozilla36
You need to log in before you can comment on or make changes to this bug.