{ JSOp switchop; uint32 ncases, tablen = 0; jsint i, low, high; jsdouble d; size_t switchsize, tablesize; JSParseNode **table; JSBool hasDefault = JS_FALSE; ptrdiff_t defaultOffset = -1;   switchop = JSOP_TABLESWITCH;   if (!js_EmitTree(cx, cg, pn->pn_kid1)) return JS_FALSE;   top = CG_OFFSET(cg); js_PushStatement(&cg->treeContext, &stmtInfo, STMT_SWITCH, top);  pn2 = pn->pn_kid2; ncases = pn2->pn_count;  if (ncases == 0 || (ncases == 1 && (hasDefault = (pn2->pn_head->pn_type == TOK_DEFAULT)))) { ncases = 0; low = 0; high = -1; } else { #define INTMAP_LENGTH   256 jsbitmap intmap_space[INTMAP_LENGTH]; jsbitmap *intmap = NULL; int32 intmap_bitlen = 0;  low  = JSVAL_INT_MAX; high = JSVAL_INT_MIN;  for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { if (pn3->pn_type == TOK_DEFAULT) { hasDefault = JS_TRUE; ncases--;    continue; }  JS_ASSERT(pn3->pn_type == TOK_CASE); if (switchop == JSOP_CONDSWITCH) continue;  pn4 = pn3->pn_left; switch (pn4->pn_type) { case TOK_NUMBER: d = pn4->pn_dval; if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) { pn3->pn_val = INT_TO_JSVAL(i); } else { atom = js_AtomizeDouble(cx, d, 0); if (!atom) { ok = JS_FALSE; goto release; } pn3->pn_val = ATOM_KEY(atom); } break; case TOK_STRING: pn3->pn_val = ATOM_KEY(pn4->pn_atom); break; case TOK_PRIMARY: if (pn4->pn_op == JSOP_TRUE) { pn3->pn_val = JSVAL_TRUE; break; } if (pn4->pn_op == JSOP_FALSE) { pn3->pn_val = JSVAL_FALSE; break; }  default: switchop = JSOP_CONDSWITCH; continue; }  JS_ASSERT(JSVAL_IS_NUMBER(pn3->pn_val) || JSVAL_IS_STRING(pn3->pn_val) || JSVAL_IS_BOOLEAN(pn3->pn_val));  if (switchop != JSOP_TABLESWITCH) continue; if (!JSVAL_IS_INT(pn3->pn_val)) { switchop = JSOP_LOOKUPSWITCH; continue; } i = JSVAL_TO_INT(pn3->pn_val); if ((jsuint)(i + (jsint)JS_BIT(15)) >= (jsuint)JS_BIT(16)) { switchop = JSOP_LOOKUPSWITCH; continue; } if (i < low) low = i; if (high < i) high = i;   if (i < 0) i += JS_BIT(16); if (i >= intmap_bitlen) { if (!intmap && i < (INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2)) { intmap = intmap_space; intmap_bitlen = INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2; } else {  intmap_bitlen = JS_BIT(16); intmap = (jsbitmap *) JS_malloc(cx, (JS_BIT(16) >> JS_BITS_PER_WORD_LOG2) * sizeof(jsbitmap)); if (!intmap) { JS_ReportOutOfMemory(cx); return JS_FALSE; } } memset(intmap, 0, intmap_bitlen >> JS_BITS_PER_BYTE_LOG2); } if (JS_TEST_BIT(intmap, i)) { switchop = JSOP_LOOKUPSWITCH; continue; } JS_SET_BIT(intmap, i); }  release: if (intmap && intmap != intmap_space) JS_free(cx, intmap); if (!ok) return JS_FALSE;   if (switchop == JSOP_TABLESWITCH) { tablen = (uint32)(high - low + 1); if (tablen >= JS_BIT(16) || tablen > 2 * ncases) switchop = JSOP_LOOKUPSWITCH; } }   noteIndex = js_NewSrcNote3(cx, cg, SRC_SWITCH, 0, 0); if (noteIndex < 0) return JS_FALSE;  if (switchop == JSOP_CONDSWITCH) {  switchsize = 0; } else if (switchop == JSOP_TABLESWITCH) {  switchsize = (size_t)(JUMP_OFFSET_LEN * (3 + tablen)); } else {  switchsize = (size_t)(JUMP_OFFSET_LEN + ATOM_INDEX_LEN + (ATOM_INDEX_LEN + JUMP_OFFSET_LEN) * ncases); }   if (js_EmitN(cx, cg, switchop, switchsize) < 0) return JS_FALSE;  off = -1; if (switchop == JSOP_CONDSWITCH) { intN caseNoteIndex = -1;   for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { pn4 = pn3->pn_left; if (pn4 && !js_EmitTree(cx, cg, pn4)) return JS_FALSE; if (caseNoteIndex >= 0) {  if (!js_SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0, CG_OFFSET(cg) - off)) { return JS_FALSE; } } if (pn3->pn_type == TOK_DEFAULT) continue; caseNoteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0); if (caseNoteIndex < 0) return JS_FALSE; off = EmitJump(cx, cg, JSOP_CASE, 0); if (off < 0) return JS_FALSE; pn3->pn_offset = off; if (pn3 == pn2->pn_head) {  if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, off - top)) { return JS_FALSE; } } }   defaultOffset = EmitJump(cx, cg, JSOP_DEFAULT, 0); if (defaultOffset < 0) return JS_FALSE; } else if (switchop == JSOP_TABLESWITCH) {  pc = CG_CODE(cg, top + JUMP_OFFSET_LEN); SET_JUMP_OFFSET(pc, low); pc += JUMP_OFFSET_LEN; SET_JUMP_OFFSET(pc, high); pc += JUMP_OFFSET_LEN; } else { JS_ASSERT(switchop == JSOP_LOOKUPSWITCH);   pc = CG_CODE(cg, top + JUMP_OFFSET_LEN); SET_ATOM_INDEX(pc, ncases); }   for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { if (switchop == JSOP_CONDSWITCH && pn3->pn_type != TOK_DEFAULT) CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, pn3->pn_offset); pn4 = pn3->pn_right; if (!js_EmitTree(cx, cg, pn4)) return JS_FALSE; pn3->pn_offset = pn4->pn_offset; if (pn3->pn_type == TOK_DEFAULT) off = pn3->pn_offset - top; }  if (!hasDefault) {  off = CG_OFFSET(cg) - top; }   JS_ASSERT(off != -1);   pc = NULL; if (switchop == JSOP_CONDSWITCH) { JS_ASSERT(defaultOffset != -1); if (!js_SetJumpOffset(cx, cg, CG_CODE(cg, defaultOffset), off - (defaultOffset - top))) { return JS_FALSE; } } else { pc = CG_CODE(cg, top); if (!js_SetJumpOffset(cx, cg, pc, off)) return JS_FALSE; pc += JUMP_OFFSET_LEN; }   off = CG_OFFSET(cg) - top; if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, off)) return JS_FALSE;  if (switchop == JSOP_TABLESWITCH) {  pc += 2 * JUMP_OFFSET_LEN;   if (tablen) {  tablesize = (size_t)tablen * sizeof *table; table = (JSParseNode **) JS_malloc(cx, tablesize); if (!table) return JS_FALSE; memset(table, 0, tablesize); for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { if (pn3->pn_type == TOK_DEFAULT) continue; i = JSVAL_TO_INT(pn3->pn_val); i -= low; JS_ASSERT((uint32)i < tablen); table[i] = pn3; } for (i = 0; i < (jsint)tablen; i++) { pn3 = table[i]; off = pn3 ? pn3->pn_offset - top : 0; ok = js_SetJumpOffset(cx, cg, pc, off); if (!ok) break; pc += JUMP_OFFSET_LEN; } JS_free(cx, table); if (!ok) return JS_FALSE; } } else if (switchop == JSOP_LOOKUPSWITCH) {  pc += ATOM_INDEX_LEN;  for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { if (pn3->pn_type == TOK_DEFAULT) continue; atom = js_AtomizeValue(cx, pn3->pn_val, 0); if (!atom) return JS_FALSE; ale = js_IndexAtom(cx, atom, &cg->atomList); if (!ale) return JS_FALSE; SET_ATOM_INDEX(pc, ALE_INDEX(ale)); pc += ATOM_INDEX_LEN;  off = pn3->pn_offset - top; if (!js_SetJumpOffset(cx, cg, pc, off)) return JS_FALSE; pc += JUMP_OFFSET_LEN; } }  ok = js_PopStatementCG(cx, cg); break; }
ok = EmitSwitch(cx, cg, pn, &stmtInfo); break;
js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn){    JSBool ok, useful, wantval;    JSStmtInfo *stmt, stmtInfo;    ptrdiff_t top, off, tmp, beq, jmp;    JSParseNode *pn2, *pn3, *pn4;    JSAtom *atom;    JSAtomListElement *ale;    jsatomid atomIndex;    intN noteIndex;    JSSrcNoteType noteType;    jsbytecode *pc;    JSOp op;    uint32 argc;    ok = JS_TRUE;    cg->emitLevel++;    pn->pn_offset = top = CG_OFFSET(cg);    /* Emit notes to tell the current bytecode's source line number. */    UPDATE_LINE_NUMBER_NOTES(cx, cg, pn);    switch (pn->pn_type) {      case TOK_FUNCTION:      {        void *cg2mark;        JSCodeGenerator *cg2;        JSFunction *fun;        /* Generate code for the function's body. */        cg2mark = JS_ARENA_MARK(&cx->tempPool);        JS_ARENA_ALLOCATE_TYPE(cg2, JSCodeGenerator, &cx->tempPool);        if (!cg2) {            JS_ReportOutOfMemory(cx);            return JS_FALSE;        }        if (!js_InitCodeGenerator(cx, cg2, cg->codePool, cg->notePool,                                  cg->filename, pn->pn_pos.begin.lineno,                                  cg->principals)) {            return JS_FALSE;        }        cg2->treeContext.flags = pn->pn_flags | TCF_IN_FUNCTION;        cg2->treeContext.tryCount = pn->pn_tryCount;        fun = (JSFunction *) JS_GetPrivate(cx, ATOM_TO_OBJECT(pn->pn_funAtom));        if (!js_EmitFunctionBody(cx, cg2, pn->pn_body, fun))            return JS_FALSE;        /*         * We need an activation object if an inner peeks out, or if such         * inner-peeking caused one of our inners to become heavyweight.         */        if (cg2->treeContext.flags &            (TCF_FUN_USES_NONLOCALS | TCF_FUN_HEAVYWEIGHT)) {            cg->treeContext.flags |= TCF_FUN_HEAVYWEIGHT;        }        js_FinishCodeGenerator(cx, cg2);        JS_ARENA_RELEASE(&cx->tempPool, cg2mark);        /* Make the function object a literal in the outer script's pool. */        ale = js_IndexAtom(cx, pn->pn_funAtom, &cg->atomList);        if (!ale)            return JS_FALSE;        atomIndex = ALE_INDEX(ale);#if JS_HAS_LEXICAL_CLOSURE        /* Emit a bytecode pointing to the closure object in its immediate. */        if (pn->pn_op != JSOP_NOP) {            EMIT_ATOM_INDEX_OP(pn->pn_op, atomIndex);            break;        }#endif        /* Top-level named functions need a nop for decompilation. */        noteIndex = js_NewSrcNote2(cx, cg, SRC_FUNCDEF, (ptrdiff_t)atomIndex);        if (noteIndex < 0 ||            js_Emit1(cx, cg, JSOP_NOP) < 0) {            return JS_FALSE;        }        /*         * Top-levels also need a prolog op to predefine their names in the         * variable object, or if local, to fill their stack slots.         */        CG_SWITCH_TO_PROLOG(cg);#if JS_HAS_LEXICAL_CLOSURE        if (cg->treeContext.flags & TCF_IN_FUNCTION) {            JSObject *obj, *pobj;            JSScopeProperty *sprop;            uintN slot;            obj = OBJ_GET_PARENT(cx, fun->object);            if (!js_LookupProperty(cx, obj, (jsid)fun->atom, &pobj,                                   (JSProperty **)&sprop)) {                return JS_FALSE;            }            JS_ASSERT(sprop && pobj == obj);            slot = sprop->shortid;            OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);            /* Emit [JSOP_DEFLOCALFUN, local variable slot, atomIndex]. */            off = js_EmitN(cx, cg, JSOP_DEFLOCALFUN, VARNO_LEN+ATOM_INDEX_LEN);            if (off < 0)                return JS_FALSE;            pc = CG_CODE(cg, off);            SET_VARNO(pc, slot);            pc += VARNO_LEN;            SET_ATOM_INDEX(pc, atomIndex);        } else#endif            EMIT_ATOM_INDEX_OP(JSOP_DEFFUN, atomIndex);        CG_SWITCH_TO_MAIN(cg);        break;      }#if JS_HAS_EXPORT_IMPORT      case TOK_EXPORT:        pn2 = pn->pn_head;        if (pn2->pn_type == TOK_STAR) {            /*             * 'export *' must have no other elements in the list (what would             * be the point?).             */            if (js_Emit1(cx, cg, JSOP_EXPORTALL) < 0)                return JS_FALSE;        } else {            /*             * If not 'export *', the list consists of NAME nodes identifying             * properties of the variables object to flag as exported.             */            do {                ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList);                if (!ale)                    return JS_FALSE;                EMIT_ATOM_INDEX_OP(JSOP_EXPORTNAME, ALE_INDEX(ale));            } while ((pn2 = pn2->pn_next) != NULL);        }        break;      case TOK_IMPORT:        for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {            /*             * Each subtree on an import list is rooted by a DOT or LB node.             * A DOT may have a null pn_atom member, in which case pn_op must             * be JSOP_IMPORTALL -- see EmitPropOp above.             */            if (!js_EmitTree(cx, cg, pn2))                return JS_FALSE;        }        break;#endif /* JS_HAS_EXPORT_IMPORT */      case TOK_IF:        /* Initialize so we can detect else-if chains and avoid recursion. */        stmtInfo.type = STMT_IF;        beq = jmp = -1;        noteIndex = -1;      if_again:        /* Emit code for the condition before pushing stmtInfo. */        if (!js_EmitTree(cx, cg, pn->pn_kid1))            return JS_FALSE;        if (stmtInfo.type == STMT_IF) {            js_PushStatement(&cg->treeContext, &stmtInfo, STMT_IF,                             CG_OFFSET(cg));        } else {            /*             * We came here from the goto further below that detects else-if             * chains, so we must mutate stmtInfo back into a STMT_IF record.             * Also (see below for why) we need a note offset for SRC_IF_ELSE             * to help the decompiler.             */            JS_ASSERT(stmtInfo.type == STMT_ELSE);            stmtInfo.type = STMT_IF;            if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq))                return JS_FALSE;        }        /* Emit an annotated branch-if-false around the then part. */        pn3 = pn->pn_kid3;        noteIndex = js_NewSrcNote(cx, cg, pn3 ? SRC_IF_ELSE : SRC_IF);        if (noteIndex < 0)            return JS_FALSE;        beq = EmitJump(cx, cg, JSOP_IFEQ, 0);        if (beq < 0)            return JS_FALSE;        /* Emit code for the then and optional else parts. */        if (!js_EmitTree(cx, cg, pn->pn_kid2))            return JS_FALSE;        if (pn3) {            /* Modify stmtInfo so we know we're in the else part. */            stmtInfo.type = STMT_ELSE;            /*             * Emit a JSOP_BACKPATCH op to jump from the end of our then part             * around the else part.  The js_PopStatementCG call at the bottom             * of this switch case will fix up the backpatch chain linked from             * stmtInfo.breaks.             */            jmp = EmitGoto(cx, cg, &stmtInfo, &stmtInfo.breaks, NULL, SRC_NULL);            if (jmp < 0)                return JS_FALSE;            /* Ensure the branch-if-false comes here, then emit the else. */            CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);            if (pn3->pn_type == TOK_IF) {                pn = pn3;                goto if_again;            }            if (!js_EmitTree(cx, cg, pn3))                return JS_FALSE;            /*             * Annotate SRC_IF_ELSE with the offset from branch to jump, for             * the decompiler's benefit.  We can't just "back up" from the pc             * of the else clause, because we don't know whether an extended             * jump was required to leap from the end of the then clause over             * the else clause.             */            if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq))                return JS_FALSE;        } else {            /* No else part, fixup the branch-if-false to come here. */            CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);        }        ok = js_PopStatementCG(cx, cg);        break;#if JS_HAS_SWITCH_STATEMENT      case TOK_SWITCH:      {        JSOp switchop;        uint32 ncases, tablen = 0;        jsint i, low, high;        jsdouble d;        size_t switchsize, tablesize;        JSParseNode **table;        JSBool hasDefault = JS_FALSE;        ptrdiff_t defaultOffset = -1;        /* Try for most optimal, fall back if not dense ints, and per ECMAv2. */        switchop = JSOP_TABLESWITCH;        /* Emit code for the discriminant first. */        if (!js_EmitTree(cx, cg, pn->pn_kid1))            return JS_FALSE;        /* Switch bytecodes run from here till end of final case. */        top = CG_OFFSET(cg);        js_PushStatement(&cg->treeContext, &stmtInfo, STMT_SWITCH, top);        pn2 = pn->pn_kid2;        ncases = pn2->pn_count;        if (ncases == 0 ||            (ncases == 1 &&             (hasDefault = (pn2->pn_head->pn_type == TOK_DEFAULT)))) {            ncases = 0;            low = 0;            high = -1;        } else {#define INTMAP_LENGTH   256            jsbitmap intmap_space[INTMAP_LENGTH];            jsbitmap *intmap = NULL;            int32 intmap_bitlen = 0;            low  = JSVAL_INT_MAX;            high = JSVAL_INT_MIN;            for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {                if (pn3->pn_type == TOK_DEFAULT) {                    hasDefault = JS_TRUE;                    ncases--;   /* one of the "cases" was the default */                    continue;                }                JS_ASSERT(pn3->pn_type == TOK_CASE);                if (switchop == JSOP_CONDSWITCH)                    continue;                pn4 = pn3->pn_left;                switch (pn4->pn_type) {                  case TOK_NUMBER:                    d = pn4->pn_dval;                    if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {                        pn3->pn_val = INT_TO_JSVAL(i);                    } else {                        atom = js_AtomizeDouble(cx, d, 0);                        if (!atom) {                            ok = JS_FALSE;                            goto release;                        }                        pn3->pn_val = ATOM_KEY(atom);                    }                    break;                  case TOK_STRING:                    pn3->pn_val = ATOM_KEY(pn4->pn_atom);                    break;                  case TOK_PRIMARY:                    if (pn4->pn_op == JSOP_TRUE) {                        pn3->pn_val = JSVAL_TRUE;                        break;                    }                    if (pn4->pn_op == JSOP_FALSE) {                        pn3->pn_val = JSVAL_FALSE;                        break;                    }                    /* FALL THROUGH */                  default:                    switchop = JSOP_CONDSWITCH;                    continue;                }                JS_ASSERT(JSVAL_IS_NUMBER(pn3->pn_val) ||                          JSVAL_IS_STRING(pn3->pn_val) ||                          JSVAL_IS_BOOLEAN(pn3->pn_val));                if (switchop != JSOP_TABLESWITCH)                    continue;                if (!JSVAL_IS_INT(pn3->pn_val)) {                    switchop = JSOP_LOOKUPSWITCH;                    continue;                }                i = JSVAL_TO_INT(pn3->pn_val);                if ((jsuint)(i + (jsint)JS_BIT(15)) >= (jsuint)JS_BIT(16)) {                    switchop = JSOP_LOOKUPSWITCH;                    continue;                }                if (i < low)                    low = i;                if (high < i)                    high = i;                /*                 * Check for duplicates, which require a JSOP_LOOKUPSWITCH.                 * We bias i by 65536 if it's negative, and hope that's a rare                 * case (because it requires a malloc'd bitmap).                 */                if (i < 0)                    i += JS_BIT(16);                if (i >= intmap_bitlen) {                    if (!intmap &&                        i < (INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2)) {                        intmap = intmap_space;                        intmap_bitlen = INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2;                    } else {                        /* Just grab 8K for the worst-case bitmap. */                        intmap_bitlen = JS_BIT(16);                        intmap = (jsbitmap *)                            JS_malloc(cx,                                      (JS_BIT(16) >> JS_BITS_PER_WORD_LOG2)                                      * sizeof(jsbitmap));                        if (!intmap) {                            JS_ReportOutOfMemory(cx);                            return JS_FALSE;                        }                    }                    memset(intmap, 0, intmap_bitlen >> JS_BITS_PER_BYTE_LOG2);                }                if (JS_TEST_BIT(intmap, i)) {                    switchop = JSOP_LOOKUPSWITCH;                    continue;                }                JS_SET_BIT(intmap, i);            }          release:            if (intmap && intmap != intmap_space)                JS_free(cx, intmap);            if (!ok)                return JS_FALSE;            /*             * Compute table length and select lookup instead if overlarge or             * more than half-sparse.             */            if (switchop == JSOP_TABLESWITCH) {                tablen = (uint32)(high - low + 1);                if (tablen >= JS_BIT(16) || tablen > 2 * ncases)                    switchop = JSOP_LOOKUPSWITCH;            }        }        /*         * Emit a note with two offsets: first tells total switch code length,         * second tells offset to first JSOP_CASE if condswitch.         */        noteIndex = js_NewSrcNote3(cx, cg, SRC_SWITCH, 0, 0);        if (noteIndex < 0)            return JS_FALSE;        if (switchop == JSOP_CONDSWITCH) {            /*             * 0 bytes of immediate for unoptimized ECMAv2 switch.             */            switchsize = 0;        } else if (switchop == JSOP_TABLESWITCH) {            /*             * 3 offsets (len, low, high) before the table, 1 per entry.             */            switchsize = (size_t)(JUMP_OFFSET_LEN * (3 + tablen));        } else {            /*             * JSOP_LOOKUPSWITCH:             * 1 offset (len) and 1 atom index (npairs) before the table,             * 1 atom index and 1 jump offset per entry.             */            switchsize = (size_t)(JUMP_OFFSET_LEN + ATOM_INDEX_LEN +                                  (ATOM_INDEX_LEN + JUMP_OFFSET_LEN) * ncases);        }        /*         * Emit switchop followed by switchsize bytes of jump or lookup table.         *         * If switchop is JSOP_LOOKUPSWITCH or JSOP_TABLESWITCH, it is crucial         * to emit the immediate operand(s) by which bytecode readers such as         * BuildSpanDepTable discover the length of the switch opcode *before*         * calling js_SetJumpOffset (which may call BuildSpanDepTable).  It's         * also important to zero all unknown jump offset immediate operands,         * so they can be converted to span dependencies with null targets to         * be computed later (js_EmitN zeros switchsize bytes after switchop).         */        if (js_EmitN(cx, cg, switchop, switchsize) < 0)            return JS_FALSE;        off = -1;        if (switchop == JSOP_CONDSWITCH) {            intN caseNoteIndex = -1;            /* Emit code for evaluating cases and jumping to case statements. */            for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {                pn4 = pn3->pn_left;                if (pn4 && !js_EmitTree(cx, cg, pn4))                    return JS_FALSE;                if (caseNoteIndex >= 0) {                    /* off is the previous JSOP_CASE's bytecode offset. */                    if (!js_SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0,                                             CG_OFFSET(cg) - off)) {                        return JS_FALSE;                    }                }                if (pn3->pn_type == TOK_DEFAULT)                    continue;                caseNoteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0);                if (caseNoteIndex < 0)                    return JS_FALSE;                off = EmitJump(cx, cg, JSOP_CASE, 0);                if (off < 0)                    return JS_FALSE;                pn3->pn_offset = off;                if (pn3 == pn2->pn_head) {                    /* Switch note's second offset is to first JSOP_CASE. */                    if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1,                                             off - top)) {                        return JS_FALSE;                    }                }            }            /* Emit default even if no explicit default statement. */            defaultOffset = EmitJump(cx, cg, JSOP_DEFAULT, 0);            if (defaultOffset < 0)                return JS_FALSE;        } else if (switchop == JSOP_TABLESWITCH) {            /* Fill in switch bounds, which we know fit in 16-bit offsets. */            pc = CG_CODE(cg, top + JUMP_OFFSET_LEN);            SET_JUMP_OFFSET(pc, low);            pc += JUMP_OFFSET_LEN;            SET_JUMP_OFFSET(pc, high);            pc += JUMP_OFFSET_LEN;        } else {            JS_ASSERT(switchop == JSOP_LOOKUPSWITCH);            /* Fill in the number of cases. */            pc = CG_CODE(cg, top + JUMP_OFFSET_LEN);            SET_ATOM_INDEX(pc, ncases);        }        /* Emit code for each case's statements, copying pn_offset up to pn3. */        for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {            if (switchop == JSOP_CONDSWITCH && pn3->pn_type != TOK_DEFAULT)                CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, pn3->pn_offset);            pn4 = pn3->pn_right;            if (!js_EmitTree(cx, cg, pn4))                return JS_FALSE;            pn3->pn_offset = pn4->pn_offset;            if (pn3->pn_type == TOK_DEFAULT)                off = pn3->pn_offset - top;        }        if (!hasDefault) {            /* If no default case, offset for default is to end of switch. */            off = CG_OFFSET(cg) - top;        }        /* We better have set "off" by now. */        JS_ASSERT(off != -1);        /* Set the default offset (to end of switch if no default). */        pc = NULL;        if (switchop == JSOP_CONDSWITCH) {            JS_ASSERT(defaultOffset != -1);            if (!js_SetJumpOffset(cx, cg, CG_CODE(cg, defaultOffset),                                  off - (defaultOffset - top))) {                return JS_FALSE;            }        } else {            pc = CG_CODE(cg, top);            if (!js_SetJumpOffset(cx, cg, pc, off))                return JS_FALSE;            pc += JUMP_OFFSET_LEN;        }        /* Set the SRC_SWITCH note's offset operand to tell end of switch. */        off = CG_OFFSET(cg) - top;        if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, off))            return JS_FALSE;        if (switchop == JSOP_TABLESWITCH) {            /* Skip over the already-initialized switch bounds. */            pc += 2 * JUMP_OFFSET_LEN;            /* Fill in the jump table, if there is one. */            if (tablen) {                /* Avoid bloat for a compilation unit with many switches. */                tablesize = (size_t)tablen * sizeof *table;                table = (JSParseNode **) JS_malloc(cx, tablesize);                if (!table)                    return JS_FALSE;                memset(table, 0, tablesize);                for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {                    if (pn3->pn_type == TOK_DEFAULT)                        continue;                    i = JSVAL_TO_INT(pn3->pn_val);                    i -= low;                    JS_ASSERT((uint32)i < tablen);                    table[i] = pn3;                }                for (i = 0; i < (jsint)tablen; i++) {                    pn3 = table[i];                    off = pn3 ? pn3->pn_offset - top : 0;                    ok = js_SetJumpOffset(cx, cg, pc, off);                    if (!ok)                        break;                    pc += JUMP_OFFSET_LEN;                }                JS_free(cx, table);                if (!ok)                    return JS_FALSE;            }        } else if (switchop == JSOP_LOOKUPSWITCH) {            /* Skip over the already-initialized number of cases. */            pc += ATOM_INDEX_LEN;            for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {                if (pn3->pn_type == TOK_DEFAULT)                    continue;                atom = js_AtomizeValue(cx, pn3->pn_val, 0);                if (!atom)                    return JS_FALSE;                ale = js_IndexAtom(cx, atom, &cg->atomList);                if (!ale)                    return JS_FALSE;                SET_ATOM_INDEX(pc, ALE_INDEX(ale));                pc += ATOM_INDEX_LEN;                off = pn3->pn_offset - top;                if (!js_SetJumpOffset(cx, cg, pc, off))                    return JS_FALSE;                pc += JUMP_OFFSET_LEN;            }        }        ok = js_PopStatementCG(cx, cg);        break;      }#endif /* JS_HAS_SWITCH_STATEMENT */      case TOK_WHILE:        js_PushStatement(&cg->treeContext, &stmtInfo, STMT_WHILE_LOOP, top);        if (!js_EmitTree(cx, cg, pn->pn_left))            return JS_FALSE;        noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE);        if (noteIndex < 0)            return JS_FALSE;        beq = EmitJump(cx, cg, JSOP_IFEQ, 0);        if (beq < 0)            return JS_FALSE;        if (!js_EmitTree(cx, cg, pn->pn_right))            return JS_FALSE;        jmp = EmitJump(cx, cg, JSOP_GOTO, top - CG_OFFSET(cg));        if (jmp < 0)            return JS_FALSE;        CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);        if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq))            return JS_FALSE;        ok = js_PopStatementCG(cx, cg);        break;#if JS_HAS_DO_WHILE_LOOP      case TOK_DO:        /* Emit an annotated nop so we know to decompile a 'do' keyword. */        if (js_NewSrcNote(cx, cg, SRC_WHILE) < 0 ||            js_Emit1(cx, cg, JSOP_NOP) < 0) {            return JS_FALSE;        }        /* Compile the loop body. */        top = CG_OFFSET(cg);        js_PushStatement(&cg->treeContext, &stmtInfo, STMT_DO_LOOP, top);        if (!js_EmitTree(cx, cg, pn->pn_left))            return JS_FALSE;        /* Set loop and enclosing label update offsets, for continue. */        stmt = &stmtInfo;        do {            stmt->update = CG_OFFSET(cg);        } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL);        /* Compile the loop condition, now that continues know where to go. */        if (!js_EmitTree(cx, cg, pn->pn_right))            return JS_FALSE;        /*         * No source note needed, because JSOP_IFNE is used only for do-while.         * If we ever use JSOP_IFNE for other purposes, we can still avoid yet         * another note here, by storing (jmp - top) in the SRC_WHILE note's         * offset, and fetching that delta in order to decompile recursively.         */        if (EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg)) < 0)            return JS_FALSE;        ok = js_PopStatementCG(cx, cg);        break;#endif /* JS_HAS_DO_WHILE_LOOP */      case TOK_FOR:        beq = 0;                /* suppress gcc warnings */        pn2 = pn->pn_left;        js_PushStatement(&cg->treeContext, &stmtInfo, STMT_FOR_LOOP, top);        if (pn2->pn_type == TOK_IN) {            /* If the left part is var x = i, bind x, evaluate i, and pop. */            pn3 = pn2->pn_left;            if (pn3->pn_type == TOK_VAR && pn3->pn_head->pn_expr) {                if (!js_EmitTree(cx, cg, pn3))                    return JS_FALSE;                /* Set pn3 to the variable name, to avoid another var note. */                pn3 = pn3->pn_head;                JS_ASSERT(pn3->pn_type == TOK_NAME);            }            /* Fix stmtInfo and emit a push to allocate the iterator. */            stmtInfo.type = STMT_FOR_IN_LOOP;            noteIndex = -1;            if (js_Emit1(cx, cg, JSOP_PUSH) < 0)                return JS_FALSE;            /* Compile the object expression to the right of 'in'. */            if (!js_EmitTree(cx, cg, pn2->pn_right))                return JS_FALSE;            if (js_Emit1(cx, cg, JSOP_TOOBJECT) < 0)                return JS_FALSE;            top = CG_OFFSET(cg);            SET_STATEMENT_TOP(&stmtInfo, top);            /* Compile a JSOP_FOR* bytecode based on the left hand side. */            switch (pn3->pn_type) {              case TOK_VAR:                pn3 = pn3->pn_head;                if (js_NewSrcNote(cx, cg, SRC_VAR) < 0)                    return JS_FALSE;                /* FALL THROUGH */              case TOK_NAME:                pn3->pn_op = JSOP_FORNAME;                if (!LookupArgOrVar(cx, &cg->treeContext, pn3))                    return JS_FALSE;                op = pn3->pn_op;                if (pn3->pn_slot >= 0) {                    if (pn3->pn_attrs & JSPROP_READONLY)                        op = JSOP_GETVAR;                    atomIndex = (jsatomid) pn3->pn_slot;                    EMIT_ATOM_INDEX_OP(op, atomIndex);                } else {                    if (!EmitAtomOp(cx, pn3, op, cg))                        return JS_FALSE;                }                break;              case TOK_DOT:                if (!EmitPropOp(cx, pn3, JSOP_FORPROP, cg))                    return JS_FALSE;                break;              case TOK_LB:                /*                 * We separate the first/next bytecode from the enumerator                 * variable binding to avoid any side-effects in the index                 * expression (e.g., for (x[i++] in {}) should not bind x[i]                 * or increment i at all).                 */                if (!js_Emit1(cx, cg, JSOP_FORELEM))                    return JS_FALSE;                /*                 * Emit a SRC_WHILE note with offset telling the distance to                 * the loop-closing jump (we can't reckon from the branch at                 * the top of the loop, because the loop-closing jump might be                 * need to be an extended jump, independent of whether the                 * branch is short or long).                 */                noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE);                if (noteIndex < 0)                    return JS_FALSE;                beq = EmitJump(cx, cg, JSOP_IFEQ, 0);                if (beq < 0)                    return JS_FALSE;                /* Now that we're safely past the IFEQ, commit side effects. */                if (!EmitElemOp(cx, pn3, JSOP_ENUMELEM, cg))                    return JS_FALSE;                break;              default:                JS_ASSERT(0);            }            if (pn3->pn_type != TOK_LB) {                /* Annotate so the decompiler can find the loop-closing jump. */                noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE);                if (noteIndex < 0)                    return JS_FALSE;                /* Pop and test the loop condition generated by JSOP_FOR*. */                beq = EmitJump(cx, cg, JSOP_IFEQ, 0);                if (beq < 0)                    return JS_FALSE;            }        } else {