diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index a2b5d2bef50..6323ac7a995 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -133,29 +133,8 @@ JSStackFrame::pc(JSContext *cx, JSStackFrame *next) return next->prevpc_; #if defined(JS_METHODJIT) && defined(JS_MONOIC) - JSScript *script = this->script(); - js::mjit::JITScript *jit = script->getJIT(isConstructing()); - size_t low = 0; - size_t high = jit->nCallICs; - while (high > low + 1) { - /* Could overflow here on a script with 2 billion calls. Oh well. */ - size_t mid = (high + low) / 2; - void *entry = jit->callICs[mid].funGuard.executableAddress(); - - /* - * Use >= here as the return address of the call is likely to be - * the start address of the next (possibly IC'ed) operation. - */ - if (entry >= next->ncode_) - high = mid; - else - low = mid; - } - - js::mjit::ic::CallICInfo &callIC = jit->callICs[low]; - - JS_ASSERT((uint8*)callIC.funGuard.executableAddress() + callIC.joinPointOffset == next->ncode_); - return callIC.pc; + js::mjit::JITScript *jit = script()->getJIT(isConstructing()); + return jit->nativeToPC(next->ncode_); #else JS_NOT_REACHED("Unknown PC for frame"); return NULL; diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index b384eee252f..273ee76edbe 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -272,8 +272,14 @@ stubs::FixupArity(VMFrame &f, uint32 nactual) JSStackFrame *newfp = cx->stack().getInlineFrameWithinLimit(cx, (Value*) oldfp, nactual, fun, fun->script(), &flags, f.entryfp, &f.stackLimit); - if (!newfp) + if (!newfp) { + /* + * The PC is not coherent with the current frame, so fix it up for + * exception handling. + */ + f.regs.pc = f.jit()->nativeToPC(ncode); THROWV(NULL); + } /* Reset the part of the stack frame set by the caller. */ newfp->initCallFrameCallerHalf(cx, flags, ncode); diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp index baf4a75d26e..6124a8ff3e6 100644 --- a/js/src/methodjit/MethodJIT.cpp +++ b/js/src/methodjit/MethodJIT.cpp @@ -948,3 +948,30 @@ mjit::GetCallTargetCount(JSScript *script, jsbytecode *pc) return 1; } #endif + +jsbytecode * +JITScript::nativeToPC(void *returnAddress) const +{ + size_t low = 0; + size_t high = nCallICs; + while (high > low + 1) { + /* Could overflow here on a script with 2 billion calls. Oh well. */ + size_t mid = (high + low) / 2; + void *entry = callICs[mid].funGuard.executableAddress(); + + /* + * Use >= here as the return address of the call is likely to be + * the start address of the next (possibly IC'ed) operation. + */ + if (entry >= returnAddress) + high = mid; + else + low = mid; + } + + js::mjit::ic::CallICInfo &ic = callICs[low]; + + JS_ASSERT((uint8*)ic.funGuard.executableAddress() + ic.joinPointOffset == returnAddress); + return ic.pc; +} + diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 4d5822f6674..1c41699d7da 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -361,6 +361,8 @@ struct JITScript { size_t scriptDataSize(); size_t mainCodeSize() { return code.m_size; } /* doesn't account for fragmentation */ + + jsbytecode *nativeToPC(void *returnAddress) const; }; /*