if (hook)
if (hook) {
js_Interpret(JSContext *cx, jsval *result){    JSRuntime *rt;    JSStackFrame *fp;    JSScript *script;    uintN inlineCallCount;    JSObject *obj, *obj2, *proto, *parent;    JSVersion currentVersion, originalVersion;    JSBranchCallback onbranch;    JSBool ok, cond;    JSTrapHandler interruptHandler;    jsint depth, len;    jsval *sp, *newsp;    void *mark;    jsbytecode *pc, *pc2, *endpc;    JSOp op, op2;    JSCodeSpec *cs;    JSAtom *atom;    uintN argc, slot, attrs;    jsval *vp, lval, rval, ltmp, rtmp;    jsid id;    JSObject *withobj, *origobj, *propobj;    JSIdArray *ida;    jsval iter_state;    JSProperty *prop;    JSScopeProperty *sprop;    JSString *str, *str2;    jsint i, j;    jsdouble d, d2;    JSClass *clasp, *funclasp;    JSFunction *fun;    JSType type;#ifdef DEBUG    FILE *tracefp;#endif#if JS_HAS_SWITCH_STATEMENT    jsint low, high, off, npairs;    JSBool match;#endif#if JS_HAS_GETTER_SETTER    JSPropertyOp getter, setter;#endif    *result = JSVAL_VOID;    rt = cx->runtime;    /* Set registerized frame pointer and derived script pointer. */    fp = cx->fp;    script = fp->script;    /* Count of JS function calls that nest in this C js_Interpret frame. */    inlineCallCount = 0;    /*     * Optimized Get and SetVersion for proper script language versioning.     *     * If any native method or JSClass/JSObjectOps hook calls JS_SetVersion     * and changes cx->version, the effect will "stick" and we will stop     * maintaining currentVersion.  This is relied upon by testsuites, for     * the most part -- web browsers select version before compiling and not     * at run-time.     */    currentVersion = script->version;    originalVersion = cx->version;    if (currentVersion != originalVersion)        JS_SetVersion(cx, currentVersion);    /*     * Prepare to call a user-supplied branch handler, and abort the script     * if it returns false.     */    onbranch = cx->branchCallback;    ok = JS_TRUE;#define CHECK_BRANCH(len)                                                     \    JS_BEGIN_MACRO                                                            \        if (len <= 0 && onbranch) {                                           \            SAVE_SP(fp);                                                      \            if (!(ok = (*onbranch)(cx, script)))                              \                goto out;                                                     \        }                                                                     \    JS_END_MACRO    /*     * Load the debugger's interrupt hook here and after calling out to native     * functions (but not to getters, setters, or other native hooks), so we do     * not have to reload it each time through the interpreter loop -- we hope     * the compiler can keep it in a register.     * XXX if it spills, we still lose     */#define LOAD_INTERRUPT_HANDLER(rt)  (interruptHandler = (rt)->interruptHandler)    LOAD_INTERRUPT_HANDLER(rt);    pc = script->code;    endpc = pc + script->length;    len = -1;    /*     * Allocate operand and pc stack slots for the script's worst-case depth.     */    depth = (jsint) script->depth;    newsp = js_AllocRawStack(cx, (uintN)(2 * depth), &mark);    if (!newsp) {        ok = JS_FALSE;        goto out;    }    sp = newsp + depth;    fp->spbase = sp;    SAVE_SP(fp);    if (++cx->interpLevel == MAX_INTERP_LEVEL) {        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);        ok = JS_FALSE;        goto out;    }    while (pc < endpc) {        fp->pc = pc;        op = (JSOp) *pc;      do_op:        cs = &js_CodeSpec[op];        len = cs->length;#ifdef DEBUG        tracefp = (FILE *) cx->tracefp;        if (tracefp) {            intN nuses, n;            fprintf(tracefp, "%4u: ", js_PCToLineNumber(script, pc));            js_Disassemble1(cx, script, pc,                            PTRDIFF(pc, script->code, jsbytecode), JS_FALSE,                            tracefp);            nuses = cs->nuses;            if (nuses) {                SAVE_SP(fp);                for (n = -nuses; n < 0; n++) {                    str = js_DecompileValueGenerator(cx, n, sp[n], NULL);                    if (str != NULL) {                        fprintf(tracefp, "%s %s",                                (n == -nuses) ? "  inputs:" : ",",                                JS_GetStringBytes(str));                    }                }                fprintf(tracefp, " @ %d\n", sp - fp->spbase);            }        }#endif        if (interruptHandler) {            SAVE_SP(fp);            switch (interruptHandler(cx, script, pc, &rval,                                     rt->interruptHandlerData)) {              case JSTRAP_ERROR:                ok = JS_FALSE;                goto out;              case JSTRAP_CONTINUE:                break;              case JSTRAP_RETURN:                fp->rval = rval;                goto out;#if JS_HAS_EXCEPTIONS              case JSTRAP_THROW:                cx->throwing = JS_TRUE;                cx->exception = rval;                ok = JS_FALSE;                goto out;#endif /* JS_HAS_EXCEPTIONS */              default:;            }        }        switch (op) {          case JSOP_NOP:            break;          case JSOP_GROUP:            obj = NULL;            break;          case JSOP_PUSH:            PUSH_OPND(JSVAL_VOID);            break;          case JSOP_POP:            sp--;            break;          case JSOP_POP2:            sp -= 2;            break;          case JSOP_SWAP:            /*             * N.B. JSOP_SWAP doesn't swap the corresponding generating pcs             * for the operands it swaps.             */            ltmp = sp[-1];            sp[-1] = sp[-2];            sp[-2] = ltmp;            break;          case JSOP_POPV:            *result = POP_OPND();            break;          case JSOP_ENTERWITH:            rval = FETCH_OPND(-1);            VALUE_TO_OBJECT(cx, rval, obj);            withobj = js_NewObject(cx, &js_WithClass, obj, fp->scopeChain);            if (!withobj)                goto out;            fp->scopeChain = withobj;            STORE_OPND(-1, OBJECT_TO_JSVAL(withobj));            break;          case JSOP_LEAVEWITH:            rval = POP_OPND();            JS_ASSERT(JSVAL_IS_OBJECT(rval));            withobj = JSVAL_TO_OBJECT(rval);            JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass);            rval = OBJ_GET_SLOT(cx, withobj, JSSLOT_PARENT);            JS_ASSERT(JSVAL_IS_OBJECT(rval));            fp->scopeChain = JSVAL_TO_OBJECT(rval);            break;          case JSOP_SETRVAL:            fp->rval = POP_OPND();            break;          case JSOP_RETURN:            CHECK_BRANCH(-1);            fp->rval = POP_OPND();            /* FALL THROUGH */          case JSOP_RETRVAL:    /* fp->rval already set */            if (inlineCallCount)          inline_return:            {                JSInlineFrame *ifp = (JSInlineFrame *) fp;                void *hookData = ifp->hookData;                if (hookData) {                    JSInterpreterHook hook = cx->runtime->callHook;                    if (hook)                        hook(cx, fp, JS_FALSE, &ok, hookData);                }#if JS_HAS_ARGS_OBJECT                if (fp->argsobj)                    ok &= js_PutArgsObject(cx, fp);#endif                /* Restore context version only if callee hasn't set version. */                if (cx->version == currentVersion) {                    currentVersion = ifp->callerVersion;                    if (currentVersion != cx->version)                        JS_SetVersion(cx, currentVersion);                }                /* Store the return value in the caller's operand frame. */                vp = fp->argv - 2;                *vp = fp->rval;                /* Restore cx->fp and release the inline frame's space. */                cx->fp = fp = fp->down;                JS_ARENA_RELEASE(&cx->stackPool, ifp->mark);                /* Restore sp to point just above the return value. */                fp->sp = vp + 1;                RESTORE_SP(fp);                /* Restore the calling script's interpreter registers. */                script = fp->script;                depth = (jsint) script->depth;                pc = fp->pc;                endpc = script->code + script->length;                /* Store the generating pc for the return value. */                vp[-depth] = (jsval)pc;                /* Set remaining variables for 'goto advance_pc'. */                op = (JSOp) *pc;                cs = &js_CodeSpec[op];                len = cs->length;                /* Resume execution in the calling frame. */                inlineCallCount--;                if (ok)                    goto advance_pc;            }            goto out;#if JS_HAS_SWITCH_STATEMENT          case JSOP_DEFAULT:            (void) POP();            /* FALL THROUGH */#endif          case JSOP_GOTO:            len = GET_JUMP_OFFSET(pc);            CHECK_BRANCH(len);            break;          case JSOP_IFEQ:            POP_BOOLEAN(cx, rval, cond);            if (cond == JS_FALSE) {                len = GET_JUMP_OFFSET(pc);                CHECK_BRANCH(len);            }            break;          case JSOP_IFNE:            POP_BOOLEAN(cx, rval, cond);            if (cond != JS_FALSE) {                len = GET_JUMP_OFFSET(pc);                CHECK_BRANCH(len);            }            break;          case JSOP_OR:            POP_BOOLEAN(cx, rval, cond);            if (cond == JS_TRUE) {                len = GET_JUMP_OFFSET(pc);                PUSH_OPND(rval);            }            break;          case JSOP_AND:            POP_BOOLEAN(cx, rval, cond);            if (cond == JS_FALSE) {                len = GET_JUMP_OFFSET(pc);                PUSH_OPND(rval);            }            break;#if JS_HAS_SWITCH_STATEMENT          case JSOP_DEFAULTX:            (void) POP();            /* FALL THROUGH */#endif          case JSOP_GOTOX:            len = GET_JUMPX_OFFSET(pc);            CHECK_BRANCH(len);