diff --git a/js/src/ion/IonFrames.cpp b/js/src/ion/IonFrames.cpp index ed2b8a453487..c639bdc8db6d 100644 --- a/js/src/ion/IonFrames.cpp +++ b/js/src/ion/IonFrames.cpp @@ -698,10 +698,10 @@ MarkBaselineStubFrame(JSTracer *trc, const IonFrameIterator &frame) JS_ASSERT(frame.type() == IonFrame_BaselineStub); IonBaselineStubFrameLayout *layout = (IonBaselineStubFrameLayout *)frame.fp(); - ICStub *stub = layout->stubPtr(); - JS_ASSERT(ICStub::CanMakeCalls(stub->kind())); - - stub->trace(trc); + if (ICStub *stub = layout->maybeStubPtr()) { + JS_ASSERT(ICStub::CanMakeCalls(stub->kind())); + stub->trace(trc); + } } void diff --git a/js/src/ion/arm/IonFrames-arm.h b/js/src/ion/arm/IonFrames-arm.h index 5545f9267262..66f9e624a422 100644 --- a/js/src/ion/arm/IonFrames-arm.h +++ b/js/src/ion/arm/IonFrames-arm.h @@ -183,7 +183,7 @@ class IonBaselineStubFrameLayout : public IonCommonFrameLayout return -int(2 * sizeof(void *)); } - inline ICStub *stubPtr() { + inline ICStub *maybeStubPtr() { uint8_t *fp = reinterpret_cast(this); return *reinterpret_cast(fp + reverseOffsetOfStubPtr()); } diff --git a/js/src/ion/arm/Trampoline-arm.cpp b/js/src/ion/arm/Trampoline-arm.cpp index 13284219e723..7c2b555abe99 100644 --- a/js/src/ion/arm/Trampoline-arm.cpp +++ b/js/src/ion/arm/Trampoline-arm.cpp @@ -779,7 +779,10 @@ IonRuntime::generateDebugTrapHandler(JSContext *cx) masm.mov(r11, scratch1); masm.subPtr(Imm32(BaselineFrame::Size()), scratch1); - // Call the HandleDebugTrap VM function. + // Enter a stub frame and call the HandleDebugTrap VM function. Ensure + // the stub frame has a NULL ICStub pointer, since this pointer is marked + // during GC. + masm.movePtr(ImmWord((void *)NULL), BaselineStubReg); EmitEnterStubFrame(masm, scratch2); IonCompartment *ion = cx->compartment->ionCompartment(); diff --git a/js/src/ion/shared/IonFrames-x86-shared.h b/js/src/ion/shared/IonFrames-x86-shared.h index 3ec653555cb7..04f055884d71 100644 --- a/js/src/ion/shared/IonFrames-x86-shared.h +++ b/js/src/ion/shared/IonFrames-x86-shared.h @@ -428,7 +428,7 @@ class IonBaselineStubFrameLayout : public IonCommonFrameLayout return -int(2 * sizeof(void *)); } - inline ICStub *stubPtr() { + inline ICStub *maybeStubPtr() { uint8_t *fp = reinterpret_cast(this); return *reinterpret_cast(fp + reverseOffsetOfStubPtr()); } diff --git a/js/src/ion/x64/Trampoline-x64.cpp b/js/src/ion/x64/Trampoline-x64.cpp index 6891c029ef7d..d417018c4a71 100644 --- a/js/src/ion/x64/Trampoline-x64.cpp +++ b/js/src/ion/x64/Trampoline-x64.cpp @@ -683,7 +683,10 @@ IonRuntime::generateDebugTrapHandler(JSContext *cx) masm.mov(rbp, scratch2); masm.subPtr(Imm32(BaselineFrame::Size()), scratch2); - // Call the HandleDebugTrap VM function. + // Enter a stub frame and call the HandleDebugTrap VM function. Ensure + // the stub frame has a NULL ICStub pointer, since this pointer is marked + // during GC. + masm.movePtr(ImmWord((void *)NULL), BaselineStubReg); EmitEnterStubFrame(masm, scratch3); IonCompartment *ion = cx->compartment->ionCompartment(); diff --git a/js/src/ion/x86/Trampoline-x86.cpp b/js/src/ion/x86/Trampoline-x86.cpp index 4a08fcca7c9b..b813fa4162ad 100644 --- a/js/src/ion/x86/Trampoline-x86.cpp +++ b/js/src/ion/x86/Trampoline-x86.cpp @@ -709,7 +709,10 @@ IonRuntime::generateDebugTrapHandler(JSContext *cx) masm.mov(ebp, scratch2); masm.subPtr(Imm32(BaselineFrame::Size()), scratch2); - // Call the HandleDebugTrap VM function. + // Enter a stub frame and call the HandleDebugTrap VM function. Ensure + // the stub frame has a NULL ICStub pointer, since this pointer is marked + // during GC. + masm.movePtr(ImmWord((void *)NULL), BaselineStubReg); EmitEnterStubFrame(masm, scratch3); IonCompartment *ion = cx->compartment->ionCompartment(); diff --git a/js/src/jit-test/tests/baseline/bug857580.js b/js/src/jit-test/tests/baseline/bug857580.js new file mode 100644 index 000000000000..79c9519700ac --- /dev/null +++ b/js/src/jit-test/tests/baseline/bug857580.js @@ -0,0 +1,13 @@ +gczeal(2); +var g = newGlobal('new-compartment'); +var dbg = new Debugger(g); +dbg.onNewScript = function(script) { + fscript = script.getChildScripts()[0]; +} +g.eval("function f(x) { arguments[0] = 3; return x }"); +fscript.setBreakpoint(0, {hit:function(frame) { + assertEq(frame.eval('x').return, 1); + gc(); + return {return:42}; +}}); +assertEq(g.f(1), 42);