if (pn->pn_op == JSOP_NAME && atom == cx->runtime->atomState.argumentsAtom) { pn->pn_op = JSOP_ARGUMENTS;
if (atom == cx->runtime->atomState.argumentsAtom) { if (!(tc->flags & TCF_FUN_SETS_ARGS)) { JS_ASSERT(*opp == JSOP_NAME); *opp = JSOP_ARGUMENTS; }
LookupArgOrVar(JSContext *cx, JSTreeContext *tc, JSParseNode *pn){    JSObject *obj, *pobj;    JSClass *clasp;    JSAtom *atom;    JSScopeProperty *sprop;    JSOp op;    JS_ASSERT(pn->pn_type == TOK_NAME);    if (pn->pn_slot >= 0 || pn->pn_op == JSOP_ARGUMENTS)        return JS_TRUE;    /*     * We can't optimize if var and function collide.     * XXX suboptimal: keep track of colliding names and deoptimize only those     */    if (tc->flags & TCF_FUN_VS_VAR)        return JS_TRUE;    /*     * We can't optimize if we're not compiling a function body, whether via     * eval, or directly when compiling a function statement or expression.     */    obj = cx->fp->varobj;    clasp = OBJ_GET_CLASS(cx, obj);    if (clasp != &js_FunctionClass && clasp != &js_CallClass)        return JS_TRUE;    /*     * We can't optimize if we're in an eval called inside a with statement,     * or we're compiling a with statement and its body, or we're in a catch     * block whose exception variable has the same name as pn.     */    atom = pn->pn_atom;    if (cx->fp->scopeChain != obj ||        js_InWithStatement(tc) ||        js_InCatchBlock(tc, atom)) {        return JS_TRUE;    }    /*     * Ok, we may be able to optimize name to stack slot.  We must check for     * the predefined arguments variable.  It may be overridden by assignment,     * in which case the function is heavyweight and the interpreter will look     * up 'arguments' in the function's call object.     */    if (pn->pn_op == JSOP_NAME &&        atom == cx->runtime->atomState.argumentsAtom) {        pn->pn_op = JSOP_ARGUMENTS;        return JS_TRUE;    }    /*     * Look for an argument or variable property in the function, or its call     * object, not found in any prototype object.  Rewrite pn_op and update pn     * accordingly.  NB: We know that JSOP_DELNAME on an argument or variable     * must evaluate to false, due to JSPROP_PERMANENT.     */    if (!js_LookupProperty(cx, obj, (jsid)atom, &pobj, (JSProperty **)&sprop))        return JS_FALSE;    op = pn->pn_op;    if (sprop) {        if (pobj == obj) {            JSPropertyOp getter = SPROP_GETTER(sprop, pobj);            if (getter == js_GetArgument) {                switch (op) {                  case JSOP_NAME:    op = JSOP_GETARG; break;                  case JSOP_SETNAME: op = JSOP_SETARG; break;                  case JSOP_INCNAME: op = JSOP_INCARG; break;                  case JSOP_NAMEINC: op = JSOP_ARGINC; break;                  case JSOP_DECNAME: op = JSOP_DECARG; break;                  case JSOP_NAMEDEC: op = JSOP_ARGDEC; break;                  case JSOP_FORNAME: op = JSOP_FORARG; break;                  case JSOP_DELNAME: op = JSOP_FALSE; break;                  default: JS_ASSERT(0);                }            } else if (getter == js_GetLocalVariable ||                       getter == js_GetCallVariable)            {                switch (op) {                  case JSOP_NAME:    op = JSOP_GETVAR; break;                  case JSOP_SETNAME: op = JSOP_SETVAR; break;                  case JSOP_INCNAME: op = JSOP_INCVAR; break;                  case JSOP_NAMEINC: op = JSOP_VARINC; break;                  case JSOP_DECNAME: op = JSOP_DECVAR; break;                  case JSOP_NAMEDEC: op = JSOP_VARDEC; break;                  case JSOP_FORNAME: op = JSOP_FORVAR; break;                  case JSOP_DELNAME: op = JSOP_FALSE; break;                  default: JS_ASSERT(0);                }            }            if (op != pn->pn_op) {                pn->pn_op = op;                pn->pn_slot = JSVAL_TO_INT(sprop->id);            }            pn->pn_attrs = sprop->attrs;        }        OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);    }    return JS_TRUE;}