goto do_binary;
goto do_binary_op;
js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc){    JSParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL;    switch (pn->pn_arity) {      case PN_FUNC:        if (!js_FoldConstants(cx, pn->pn_body, tc))            return JS_FALSE;        break;      case PN_LIST:        for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {            if (!js_FoldConstants(cx, pn2, tc))                return JS_FALSE;        }        break;      case PN_TERNARY:        /* Any kid may be null (e.g. for (;;)). */        pn1 = pn->pn_kid1;        pn2 = pn->pn_kid2;        pn3 = pn->pn_kid3;        if (pn1 && !js_FoldConstants(cx, pn1, tc))            return JS_FALSE;        if (pn2 && !js_FoldConstants(cx, pn2, tc))            return JS_FALSE;        if (pn3 && !js_FoldConstants(cx, pn3, tc))            return JS_FALSE;        break;      case PN_BINARY:        /* First kid may be null (for default case in switch). */        pn1 = pn->pn_left;        pn2 = pn->pn_right;        if (pn1 && !js_FoldConstants(cx, pn1, tc))            return JS_FALSE;        if (!js_FoldConstants(cx, pn2, tc))            return JS_FALSE;        break;      case PN_UNARY:        /* Our kid may be null (e.g. return; vs. return e;). */        pn1 = pn->pn_kid;        if (pn1 && !js_FoldConstants(cx, pn1, tc))            return JS_FALSE;        break;      case PN_NAME:        /*         * Skip pn1 down along a chain of dotted member expressions to avoid         * excessive recursion.  Our only goal here is to fold constants (if         * any) in the primary expression operand to the left of the first         * dot in the chain.         */        pn1 = pn->pn_expr;        while (pn1 && pn1->pn_arity == PN_NAME)            pn1 = pn1->pn_expr;        if (pn1 && !js_FoldConstants(cx, pn1, tc))            return JS_FALSE;        break;      case PN_NULLARY:        break;    }    switch (pn->pn_type) {      case TOK_IF:        if (ContainsVarStmt(pn2) || ContainsVarStmt(pn3))            break;        /* FALL THROUGH */      case TOK_HOOK:        /* Reduce 'if (C) T; else E' into T for true C, E for false. */        switch (pn1->pn_type) {          case TOK_NUMBER:            if (pn1->pn_dval == 0)                pn2 = pn3;            break;          case TOK_STRING:            if (JSSTRING_LENGTH(ATOM_TO_STRING(pn1->pn_atom)) == 0)                pn2 = pn3;            break;          case TOK_PRIMARY:            if (pn1->pn_op == JSOP_TRUE)                break;            if (pn1->pn_op == JSOP_FALSE || pn1->pn_op == JSOP_NULL) {                pn2 = pn3;                break;            }            /* FALL THROUGH */          default:            /* Early return to dodge common code that copies pn2 to pn. */            return JS_TRUE;        }        if (pn2) {            /* pn2 is the then- or else-statement subtree to compile. */            PN_MOVE_NODE(pn, pn2);        } else {            /* False condition and no else: make pn an empty statement. */            pn->pn_type = TOK_SEMI;            pn->pn_arity = PN_UNARY;            pn->pn_kid = NULL;        }        RecycleTree(pn2, tc);        if (pn3 && pn3 != pn2)            RecycleTree(pn3, tc);        break;      case TOK_PLUS:        if (pn1->pn_type == TOK_STRING && pn2->pn_type == TOK_STRING) {            JSString *left, *right, *str;            left = ATOM_TO_STRING(pn1->pn_atom);            right = ATOM_TO_STRING(pn2->pn_atom);            str = js_ConcatStrings(cx, left, right);            if (!str)                return JS_FALSE;            pn->pn_atom = js_AtomizeString(cx, str, 0);            if (!pn->pn_atom)                return JS_FALSE;            pn->pn_type = TOK_STRING;            pn->pn_op = JSOP_STRING;            pn->pn_arity = PN_NULLARY;            RecycleTree(pn1, tc);            RecycleTree(pn2, tc);            break;        }        goto do_binary;      case TOK_STAR:        /* The * in 'import *;' parses as a nullary star node. */        if (pn->pn_arity == PN_NULLARY)            break;        /* FALL THROUGH */      case TOK_SHOP:      case TOK_MINUS:      case TOK_DIVOP:      do_binary:        if (pn1->pn_type == TOK_NUMBER && pn2->pn_type == TOK_NUMBER) {            jsdouble d, d2;            int32 i, j;            uint32 u;            /* Fold two numeric constants. */            d = pn1->pn_dval;            d2 = pn2->pn_dval;            switch (pn->pn_op) {              case JSOP_LSH:              case JSOP_RSH:                if (!js_DoubleToECMAInt32(cx, d, &i))                    return JS_FALSE;                if (!js_DoubleToECMAInt32(cx, d2, &j))                    return JS_FALSE;                j &= 31;                d = (pn->pn_op == JSOP_LSH) ? i << j : i >> j;                break;              case JSOP_URSH:                if (!js_DoubleToECMAUint32(cx, d, &u))                    return JS_FALSE;                if (!js_DoubleToECMAInt32(cx, d2, &j))                    return JS_FALSE;                j &= 31;                d = u >> j;                break;              case JSOP_ADD:                d += d2;                break;              case JSOP_SUB:                d -= d2;                break;              case JSOP_MUL:                d *= d2;                break;              case JSOP_DIV:                if (d2 == 0) {#ifdef XP_PC                    /* XXX MSVC miscompiles such that (NaN == 0) */                    if (JSDOUBLE_IS_NaN(d2))                        d = *cx->runtime->jsNaN;                    else#endif                    if (d == 0 || JSDOUBLE_IS_NaN(d))                        d = *cx->runtime->jsNaN;                    else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)                        d = *cx->runtime->jsNegativeInfinity;                    else                        d = *cx->runtime->jsPositiveInfinity;                } else {                    d /= d2;                }                break;              case JSOP_MOD:                if (d2 == 0) {                    d = *cx->runtime->jsNaN;                } else {#ifdef XP_PC                  /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */                  if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))#endif                    d = fmod(d, d2);                }                break;              default:;            }            pn->pn_type = TOK_NUMBER;            pn->pn_op = JSOP_NUMBER;            pn->pn_arity = PN_NULLARY;            pn->pn_dval = d;            RecycleTree(pn1, tc);            RecycleTree(pn2, tc);        }        break;      case TOK_UNARYOP:        if (pn1->pn_type == TOK_NUMBER) {            jsdouble d;            int32 i;            /* Operate on one numeric constants. */            d = pn1->pn_dval;            switch (pn->pn_op) {              case JSOP_BITNOT:                if (!js_DoubleToECMAInt32(cx, d, &i))                    return JS_FALSE;                d = ~i;                break;              case JSOP_NEG:#ifdef HPUX                /*                 * Negation of a zero doesn't produce a negative                 * zero on HPUX. Perform the operation by bit                 * twiddling.                 */                JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;#else                d = -d;#endif                break;              case JSOP_POS:                break;              case JSOP_NOT:                pn->pn_type = TOK_PRIMARY;                pn->pn_op = (d == 0) ? JSOP_TRUE : JSOP_FALSE;                pn->pn_arity = PN_NULLARY;                /* FALL THROUGH */              default:                /* Return early to dodge the common TOK_NUMBER code. */                return JS_TRUE;            }            pn->pn_type = TOK_NUMBER;            pn->pn_op = JSOP_NUMBER;            pn->pn_arity = PN_NULLARY;            pn->pn_dval = d;            RecycleTree(pn1, tc);        }        break;      default:;    }    /*     * Flatten a left-associative (left-heavy) tree of a given operator into     * a list, to reduce js_EmitTree recursion.     */    if (pn->pn_arity == PN_BINARY &&        pn1 &&        pn1->pn_type == pn->pn_type &&        pn1->pn_op == pn->pn_op &&        (js_CodeSpec[pn->pn_op].format & JOF_LEFTASSOC)) {        if (pn1->pn_arity == PN_LIST) {            /* We already flattened pn1, so move it to pn and append pn2. */            PN_MOVE_NODE(pn, pn1);            PN_APPEND(pn, pn2);        } else {            /* Convert pn into a list containing pn1's kids followed by pn2. */            pn->pn_arity = PN_LIST;            PN_INIT_LIST_1(pn, pn1->pn_left);            PN_APPEND(pn, pn1->pn_right);            PN_APPEND(pn, pn2);            /* Clear pn1 so it can be recycled by itself, without its kids. */            PN_CLEAR_NODE(pn1);        }        RecycleTree(pn1, tc);    }    return JS_TRUE;}