JS_END_MACRO  #define POP_ELEMENT_ID(id)                                                    \ JS_BEGIN_MACRO                                                            \ FETCH_ELEMENT_ID(-1, id);                                             \ sp--;                                                                 \ JS_END_MACRO
id = (jsid)atom;                                                      \ }                                                                         \ }  #define POP_ELEMENT_ID(id)      { FETCH_ELEMENT_ID(-1, id); sp--; }
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;    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, *str3;    size_t length, length2, length3;    jschar *chars;    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    if (cx->interpLevel == MAX_INTERP_LEVEL) {        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);        return JS_FALSE;    }    cx->interpLevel++;    *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. */    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    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);    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 == 0) ? "  inputs:" : ",",                                JS_GetStringBytes(str));                    }                }                putc('\n', tracefp);            }        }#endif        {            JSTrapHandler handler = rt->interruptHandler;            if (handler) {                switch (handler(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 pc stack             * generating pcs, as they're not needed for the current use of             * preserving the top-of-stack return value when popping scopes             * while returning from catch blocks.             */            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_RETURN:            CHECK_BRANCH(-1);            fp->rval = POP_OPND();            if (inlineCallCount)          inline_return:            {                JSInlineFrame *ifp = (JSInlineFrame *) fp;                void *hookData = ifp->hookData;                if (hookData)                    cx->runtime->callHook(cx, fp, JS_FALSE, &ok, hookData);#if JS_HAS_ARGS_OBJECT                if (fp->argsobj)                    ok &= js_PutArgsObject(cx, fp);#endif                /* 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;                /* Restore version and version control variable. */                if (script->version != currentVersion) {                    currentVersion = script->version;                    JS_SetVersion(cx, currentVersion);                }                /* 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;#if !JS_BUG_SHORT_CIRCUIT          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;#endif          case JSOP_TOOBJECT:            SAVE_SP(fp);            ok = js_ValueToObject(cx, FETCH_OPND(-1), &obj);            if (!ok)                goto out;            STORE_OPND(-1, OBJECT_TO_JSVAL(obj));            break;#define FETCH_ELEMENT_ID(n, id)                                               \    JS_BEGIN_MACRO                                                            \        /* If the index is not a jsint, atomize it. */                        \        id = (jsid) FETCH_OPND(n);                                            \        if (JSVAL_IS_INT(id)) {                                               \            atom = NULL;                                                      \        } else {                                                              \            SAVE_SP(fp);                                                      \            atom = js_ValueToStringAtom(cx, (jsval)id);                       \            if (!atom) {                                                      \                ok = JS_FALSE;                                                \                goto out;                                                     \            }                                                                 \            id = (jsid)atom;                                                  \        }                                                                     \    JS_END_MACRO#define POP_ELEMENT_ID(id)                                                    \    JS_BEGIN_MACRO                                                            \        FETCH_ELEMENT_ID(-1, id);                                             \        sp--;                                                                 \    JS_END_MACRO#if JS_HAS_IN_OPERATOR          case JSOP_IN:            rval = POP_OPND();            if (JSVAL_IS_PRIMITIVE(rval)) {                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                                     JSMSG_IN_NOT_OBJECT);                ok = JS_FALSE;                goto out;            }            obj = JSVAL_TO_OBJECT(rval);            FETCH_ELEMENT_ID(-1, id);            ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);            if (!ok)                goto out;            STORE_OPND(-1, BOOLEAN_TO_JSVAL(prop != NULL));            if (prop)                OBJ_DROP_PROPERTY(cx, obj2, prop);            break;#endif /* JS_HAS_IN_OPERATOR */          case JSOP_FORPROP:            /*             * Handle JSOP_FORPROP first, so the cost of the goto do_forinloop             * is not paid for the more common cases.             */            lval = FETCH_OPND(-1);            atom = GET_ATOM(cx, script, pc);            id   = (jsid)atom;            i = -2;            goto do_forinloop;          case JSOP_FORNAME:            atom = GET_ATOM(cx, script, pc);            id   = (jsid)atom;            /*             * ECMA 12.6.3 says to eval the LHS after looking for properties             * to enumerate, and bail without LHS eval if there are no props.             * We do Find here to share the most code at label do_forinloop.             * If looking for enumerable properties could have side effects,             * then we'd have to move this into the common code and condition             * it on op == JSOP_FORNAME.             */            SAVE_SP(fp);            ok = js_FindProperty(cx, id, &obj, &obj2, &prop);            if (!ok)                goto out;            if (prop)                OBJ_DROP_PROPERTY(cx, obj2, prop);            lval = OBJECT_TO_JSVAL(obj);            /* FALL THROUGH */          case JSOP_FORARG:          case JSOP_FORVAR:            /*             * JSOP_FORARG and JSOP_FORVAR don't require any lval computation             * here, because they address slots on the stack (in fp->args and             * fp->vars, respectively).             */            /* FALL THROUGH */          case JSOP_FORELEM:            /*             * JSOP_FORELEM simply initializes or updates the iteration state             * and leaves the index expression evaluation and assignment to the             * enumerator until after the next property has been acquired, via             * a JSOP_ENUMELEM bytecode.             */            i = -1;          do_forinloop:            /*             * ECMA-compatible for/in evals the object just once, before loop.             * Bad old bytecodes (since removed) did it on every iteration.             */            obj = JSVAL_TO_OBJECT(sp[i]);            /* If the thing to the right of 'in' has no properties, break. */            if (!obj) {                rval = JSVAL_FALSE;                goto end_forinloop;            }            /*             * Save the thing to the right of 'in' as origobj.  Later on, we             * use this variable to suppress enumeration of shadowed prototype             * properties.             */            origobj = obj;            /*             * Reach under the top of stack to find our property iterator, a             * JSObject that contains the iteration state.  (An object is used             * rather than a native struct so that the iteration state is             * cleaned up via GC if the for-in loop terminates abruptly.)             */            vp = &sp[i - 1];            rval = *vp;            /* Is this the first iteration ? */            if (JSVAL_IS_VOID(rval)) {                /* Yes, create a new JSObject to hold the iterator state */                propobj = js_NewObject(cx, &prop_iterator_class, NULL, obj);                if (!propobj) {                    ok = JS_FALSE;                    goto out;                }                /*                 * Root the parent slot so we can get it even in our finalizer                 * (otherwise, it would live as long as we do, but it might be                 * finalized first).                 */                ok = js_AddRoot(cx, &propobj->slots[JSSLOT_PARENT], NULL);                if (!ok)                    goto out;                /*                 * Rewrite the iterator so we know to do the next case.                 * Do this before calling the enumerator, which could                 * displace cx->newborn and cause GC.                 */                *vp = OBJECT_TO_JSVAL(propobj);                ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, 0);                if (!ok)                    goto out;                /*                 * Stash private iteration state into property iterator object.                 * NB: This code knows that the first slots are pre-allocated.                 */#if JS_INITIAL_NSLOTS < 5#error JS_INITIAL_NSLOTS must be greater than or equal to 5.#endif                propobj->slots[JSSLOT_ITER_STATE] = iter_state;            } else {                /* This is not the first iteration. Recover iterator state. */                propobj = JSVAL_TO_OBJECT(rval);                obj = JSVAL_TO_OBJECT(propobj->slots[JSSLOT_PARENT]);                iter_state = propobj->slots[JSSLOT_ITER_STATE];            }          enum_next_property:            /* Get the next jsid to be enumerated and store it in rval. */            OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &rval);            propobj->slots[JSSLOT_ITER_STATE] = iter_state;            /* No more jsids to iterate in obj? */            if (iter_state == JSVAL_NULL) {                /* Enumerate the properties on obj's prototype chain. */                obj = OBJ_GET_PROTO(cx, obj);                if (!obj) {                    /* End of property list -- terminate loop. */                    rval = JSVAL_FALSE;                    goto end_forinloop;                }                ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, 0);                propobj->slots[JSSLOT_ITER_STATE] = iter_state;                if (!ok)                    goto out;                /* Stash private iteration state into iterator JSObject. */                propobj->slots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(obj);                goto enum_next_property;            }            /* Skip properties not owned by obj, and leave next id in rval. */            ok = OBJ_LOOKUP_PROPERTY(cx, origobj, rval, &obj2, &prop);            if (!ok)                goto out;            if (prop) {                OBJ_DROP_PROPERTY(cx, obj2, prop);                /* Yes, don't enumerate again.  Go to the next property. */                if (obj2 != obj)                    goto enum_next_property;            }            /* Make sure rval is a string for uniformity and compatibility. */            if (!JSVAL_IS_INT(rval)) {                rval = ATOM_KEY((JSAtom *)rval);            } else if (cx->version != JSVERSION_1_2) {                str = js_NumberToString(cx, (jsdouble) JSVAL_TO_INT(rval));                if (!str) {                    ok = JS_FALSE;                    goto out;                }                rval = STRING_TO_JSVAL(str);            }            switch (op) {              case JSOP_FORARG:                slot = GET_ARGNO(pc);                JS_ASSERT(slot < fp->fun->nargs);                fp->argv[slot] = rval;                break;              case JSOP_FORVAR:                slot = GET_VARNO(pc);                JS_ASSERT(slot < fp->fun->nvars);                fp->vars[slot] = rval;                break;              case JSOP_FORELEM:                /* FORELEM is not a SET operation, it's more like BINDNAME. */                PUSH_OPND(rval);                break;              default:                /* Convert lval to a non-null object containing id. */                VALUE_TO_OBJECT(cx, lval, obj);                /* Set the variable obj[id] to refer to rval. */                ok = OBJ_SET_PROPERTY(cx, obj, id, &rval);                if (!ok)                    goto out;                break;            }