extern "C" void * js_InternalThrow(VMFrame &f) { JSContext *cx = f.cx; // It's possible that from within RunTracer(), Interpret() returned with // an error and finished the frame (i.e., called ScriptEpilogue), but has // not yet performed an inline return. // // In this case, RunTracer() has no choice but to propagate the error // up to the method JIT, and thus to this function. But ScriptEpilogue() // has already been called. Detect this, and avoid double-finishing the // frame. See HandleErrorInExcessFrame() and bug 624100. if (f.fp()->finishedInInterpreter()) { // If it's the last frame, just propagate the failure up again. if (f.fp() == f.entryfp) return NULL; InlineReturn(f); } // Make sure sp is up to date. JS_ASSERT(cx->regs == &f.regs); // Call the throw hook if necessary JSThrowHook handler = f.cx->debugHooks->throwHook; if (handler) { Value rval; switch (handler(cx, cx->fp()->script(), cx->regs->pc, Jsvalify(&rval), cx->debugHooks->throwHookData)) { case JSTRAP_ERROR: cx->clearPendingException(); return NULL; case JSTRAP_RETURN: cx->clearPendingException(); cx->fp()->setReturnValue(rval); return JS_FUNC_TO_DATA_PTR(void *, cx->jaegerCompartment()->forceReturnTrampoline()); case JSTRAP_THROW: cx->setPendingException(rval); break; default: break; } } jsbytecode *pc = NULL; for (;;) { pc = FindExceptionHandler(cx); if (pc) break; // The JIT guarantees that ScriptEpilogue() has always been run // upon exiting to its caller. This is important for consistency, // where execution modes make similar guarantees about prologues // and epilogues. RunTracer(), Interpret(), and Invoke() all // rely on this property. JS_ASSERT(!f.fp()->finishedInInterpreter()); js_UnwindScope(cx, 0, cx->isExceptionPending()); ScriptEpilogue(f.cx, f.fp(), false); // Don't remove the last frame, this is the responsibility of // JaegerShot()'s caller. We only guarantee that ScriptEpilogue() // has been run. if (f.entryfp == f.fp()) break; JS_ASSERT(f.regs.sp == cx->regs->sp); InlineReturn(f); } JS_ASSERT(f.regs.sp == cx->regs->sp); if (!pc) return NULL; JSStackFrame *fp = cx->fp(); JSScript *script = fp->script(); return script->nativeCodeForPC(fp->isConstructing(), pc); }