ptrdiff_t start, end, catchStart, finallyCatch, catchjmp = -1; JSParseNode *iter = pn;   #define EMIT_FINALLY_JSR(cx, cg)                                              \ PR_BEGIN_MACRO                                                        \ if (!js_Emit3(cx, cg, JSOP_JSR, 0, 0))                                \ return JS_FALSE;                                                  \ PR_END_MACRO
ptrdiff_t start, end, catchStart, finallyCatch, catchjmp = -1; JSParseNode *iter = pn; uint16 depth;   #define EMIT_FINALLY_GOSUB(cx, cg)                                            \ PR_BEGIN_MACRO                                                        \ if (!js_Emit3(cx, cg, JSOP_GOSUB, 0, 0))                              \ return JS_FALSE;                                                  \ PR_END_MACRO
js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn){    JSBool ok;    uintN lineno, delta;    JSCodeGenerator cg2;    JSStmtInfo *stmt, stmtInfo;    ptrdiff_t top, off, tmp, beq, jmp;    JSParseNode *pn2, *pn3, *pn4;    JSAtom *atom;    JSAtomListElement *ale;    jsatomid atomIndex;    intN noteIndex;    JSOp op;    uint32 argc;    pn->pn_offset = top = CG_OFFSET(cg);    /* Emit notes to tell the current bytecode's source line number. */    lineno = pn->pn_pos.begin.lineno;    delta = lineno - cg->currentLine;    cg->currentLine = lineno;    if (delta) {    	/*         * Encode any change in the current source line number by using either         * several SRC_NEWLINE notes or one SRC_SETLINE note, whichever         * consumes less space.         */    	if (delta >= (uintN)(2 + ((lineno > SN_3BYTE_OFFSET_MASK) << 1))) {	    if (js_NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)lineno) < 0)		return JS_FALSE;    	} else {	    do {	    	if (js_NewSrcNote(cx, cg, SRC_NEWLINE) < 0)		    return JS_FALSE;	    } while (--delta != 0);	}    }    switch (pn->pn_type) {      case TOK_FUNCTION:      {	JSFunction *fun;	/* Fold constants and generate code for the function's body. */	pn2 = pn->pn_body;	if (!js_FoldConstants(cx, pn2))	    return JS_FALSE;	if (!js_InitCodeGenerator(cx, &cg2, cg->filename,				  pn->pn_pos.begin.lineno,				  cg->principals)) {	    return JS_FALSE;	}	cg2.treeContext.tryCount = pn->pn_tryCount;	fun = pn->pn_fun;	if (!js_EmitFunctionBody(cx, &cg2, pn2, fun))	    return JS_FALSE;	js_ResetCodeGenerator(cx, &cg2);	/* Make the function object a literal in the outer script's pool. */	atom = js_AtomizeObject(cx, fun->object, 0);	if (!atom)	    return JS_FALSE;	ale = js_IndexAtom(cx, atom, &cg->atomList);	if (!ale)	    return JS_FALSE;	/* Emit a bytecode or srcnote naming the literal in its immediate. */#if JS_HAS_LEXICAL_CLOSURE	if (pn->pn_op != JSOP_NOP) {	    EMIT_ATOM_INDEX_OP(pn->pn_op, ale->index);	    break;	}#endif	noteIndex = js_NewSrcNote2(cx, cg, SRC_FUNCDEF, (ptrdiff_t)ale->index);	if (noteIndex < 0 ||	    js_Emit1(cx, cg, JSOP_NOP) < 0) {	    return JS_FALSE;	}	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 variable 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);	    } 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:	/* Emit code for the condition before pushing stmtInfo. */	if (!js_EmitTree(cx, cg, pn->pn_kid1))	    return JS_FALSE;	js_PushStatement(&cg->treeContext, &stmtInfo, STMT_IF, CG_OFFSET(cg));	/* Emit an annotated branch-if-false around the then part. */	noteIndex = js_NewSrcNote(cx, cg, SRC_IF);	if (noteIndex < 0)	    return JS_FALSE;	beq = js_Emit3(cx, cg, JSOP_IFEQ, 0, 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;	pn3 = pn->pn_kid3;	if (pn3) {	    /* Modify stmtInfo and the branch-if-false source note. */	    stmtInfo.type = STMT_ELSE;	    SN_SET_TYPE(&cg->notes[noteIndex], SRC_IF_ELSE);	    /* Jump at end of then part around the else part. */	    jmp = js_Emit3(cx, cg, JSOP_GOTO, 0, 0);	    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 (!js_EmitTree(cx, cg, pn3))		return JS_FALSE;	    /* Fixup the jump around the else part. */	    CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);	} else {	    /* No else part, fixup the branch-if-false to come here. */	    CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);	}	return js_PopStatementCG(cx, cg);#if JS_HAS_SWITCH_STATEMENT      case TOK_SWITCH:      {	JSOp switchop;	uint32 ncases, tablen;	JSScript *script;	jsint i, low, high;	size_t switchsize, tablesize;	void *mark;	JSParseNode **table;	jsbytecode *pc;	/* 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);	switchop = JSOP_TABLESWITCH;	pn2 = pn->pn_kid2;	ncases = pn2->pn_count;	if (pn2->pn_count == 0) {	    low = high = 0;	    tablen = 0;	    ok = JS_TRUE;	} else {	    low  = JSVAL_INT_MAX;	    high = JSVAL_INT_MIN;	    cg2.base = NULL;	    for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {		PR_ASSERT(pn3->pn_type == TOK_CASE);		if (!cg2.base) {		    if (!js_InitCodeGenerator(cx, &cg2, cg->filename,					      pn3->pn_pos.begin.lineno,					      cg->principals)) {			return JS_FALSE;		    }		} else {		    js_ResetCodeGenerator(cx, &cg2);		}		pn4 = pn3->pn_left;		cg2.currentLine = pn4->pn_pos.begin.lineno;		if (!js_EmitTree(cx, &cg2, pn4))		    return JS_FALSE;		if (js_Emit1(cx, &cg2, JSOP_POPV) < 0)		    return JS_FALSE;		script = js_NewScriptFromCG(cx, &cg2, NULL);		if (!script)		    return JS_FALSE;		/*		 * The GC must not run during this case expression evaluation.		 * It won't if it runs only from the branch callback (because		 * the only branches possible in a case expression come from ?:		 * expressions, and those generate downward branches, while the		 * branch callback runs only for upward branches).		 */		ok = js_Execute(cx, cx->fp->scopeChain, script, NULL, cx->fp,				JS_FALSE, &pn3->pn_val);		js_DestroyScript(cx, script);		if (!ok)		    return JS_FALSE;		if (!JSVAL_IS_NUMBER(pn3->pn_val) &&		    !JSVAL_IS_STRING(pn3->pn_val) &&		    !JSVAL_IS_BOOLEAN(pn3->pn_val)) {		    JS_ReportError(cx,				   "%s, line %u: invalid case expression",				   cg2.filename ? cg2.filename : "stdin",				   pn4->pn_pos.begin.lineno);		    return JS_FALSE;		}		if (switchop == JSOP_LOOKUPSWITCH)		    continue;		if (!JSVAL_IS_INT(pn3->pn_val)) {		    switchop = JSOP_LOOKUPSWITCH;		    continue;		}		i = JSVAL_TO_INT(pn3->pn_val);		if ((jsuint)(i + (jsint)PR_BIT(15)) >= (jsuint)PR_BIT(16)) {		    switchop = JSOP_LOOKUPSWITCH;		    continue;		}		if (i < low)		    low = i;		if (high < i)		    high = i;	    }	    if (cg2.base)		js_ResetCodeGenerator(cx, &cg2);	    if (switchop == JSOP_TABLESWITCH) {		tablen = (uint32)(high - low + 1);		if (tablen >= PR_BIT(16) || tablen > 2 * ncases)		    switchop = JSOP_LOOKUPSWITCH;	    }	}	/* Emit a note with an offset telling total switch code length. */	noteIndex = js_NewSrcNote2(cx, cg, SRC_SWITCH, 0);	if (noteIndex < 0)	    return JS_FALSE;	if (switchop == JSOP_TABLESWITCH) {	    /*	     * 3 offsets (len, low, high) before the table, 1 per entry.	     */	    switchsize = (size_t)(6 + 2 * tablen);	} else {	    /*	     * 1 offset (len) and 1 atom index (npairs) before the table,	     * 1 atom index and 1 jump offset per entry.	     */	    switchsize = (size_t)(4 + 4 * ncases);	}	/* Emit switchop and switchsize bytes of jump or lookup table. */	if (js_EmitN(cx, cg, switchop, switchsize) < 0)	    return JS_FALSE;	/* Emit code for each case's statements, copying pn_offset up to pn3. */	for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {	    pn4 = pn3->pn_right;	    if (!js_EmitTree(cx, cg, pn4))	    	return JS_FALSE;	    pn3->pn_offset = pn4->pn_offset;	}	/* Emit the default case (if any) and compute default offset. */	pn3 = pn->pn_kid3;	if (pn3) {	    if (!js_EmitTree(cx, cg, pn3))	    	return JS_FALSE;	    off = pn3->pn_offset - top;	} else {	    off = CG_OFFSET(cg) - top;	}	/* Set the default offset (to end of switch if no default). */	pc = CG_CODE(cg, top);	if (!js_SetJumpOffset(cx, cg, pc, off))	    return JS_FALSE;	pc += 2;	/* Set the SRC_SWITCH note's offset operand to tell end of switch. */	off = CG_OFFSET(cg) - top;	if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, (ptrdiff_t)off))	    return JS_FALSE;	/* Fill in jump or lookup table. */	if (switchop == JSOP_TABLESWITCH) {	    if (!js_SetJumpOffset(cx, cg, pc, low))		return JS_FALSE;	    pc += 2;	    if (!js_SetJumpOffset(cx, cg, pc, high))		return JS_FALSE;	    pc += 2;	    if (tablen) {		/* Avoid bloat for a compilation unit with many switches. */		mark = PR_ARENA_MARK(&cx->tempPool);		tablesize = (size_t)tablen * sizeof *table;		PR_ARENA_ALLOCATE(table, &cx->tempPool, tablesize);		if (!table) {		    JS_ReportOutOfMemory(cx);		    return JS_FALSE;		}		memset(table, 0, tablesize);		for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {		    i = JSVAL_TO_INT(pn3->pn_val);		    i -= low;		    PR_ASSERT((uint32)i < tablen);		    table[i] = pn3;		}		for (i = 0; i < (jsint)tablen; i++) {		    pn3 = table[i];		    off = pn3 ? pn3->pn_offset - top : 0;		    if (!js_SetJumpOffset(cx, cg, pc, off))			return JS_FALSE;		    pc += 2;		}		PR_ARENA_RELEASE(&cx->tempPool, mark);	    }	} else {	    SET_ATOM_INDEX(pc, ncases);	    pc += 2;	    for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {		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);		pc += 2;		off = pn3->pn_offset - top;		if (!js_SetJumpOffset(cx, cg, pc, off))		    return JS_FALSE;		pc += 2;	    }	}	return js_PopStatementCG(cx, cg);      }#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 = js_Emit3(cx, cg, JSOP_IFEQ, 0, 0);	if (beq < 0)	    return JS_FALSE;	if (!js_EmitTree(cx, cg, pn->pn_right))	    return JS_FALSE;	jmp = js_Emit3(cx, cg, JSOP_GOTO, 0, 0);	if (jmp < 0)	    return JS_FALSE;	CHECK_AND_SET_JUMP_OFFSET(cx, cg, CG_CODE(cg,jmp), top - jmp);	CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);	return js_PopStatementCG(cx, cg);#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;	/* Re-use the SRC_WHILE note, this time for the JSOP_IFNE opcode. */	if (js_NewSrcNote(cx, cg, SRC_WHILE) < 0)	    return JS_FALSE;	jmp = top - CG_OFFSET(cg);	if (js_Emit3(cx, cg, JSOP_IFNE,		     JUMP_OFFSET_HI(jmp), JUMP_OFFSET_LO(jmp)) < 0) {	    return JS_FALSE;	}	return js_PopStatementCG(cx, cg);#endif /* JS_HAS_DO_WHILE_LOOP */      case TOK_FOR:	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;	      	PR_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*2 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:		if (!EmitAtomOp(cx, pn3, JSOP_FORNAME2, cg))		    return JS_FALSE;	      	break;	      case TOK_DOT:	      	if (!EmitPropOp(cx, pn3, JSOP_FORPROP2, cg))		    return JS_FALSE;	      	break;	      case TOK_LB:	      	if (!EmitElemOp(cx, pn3, JSOP_FORELEM2, cg))		    return JS_FALSE;	      	break;	      default:	      	PR_ASSERT(0);	    }	    /* Pop and test the loop condition generated by JSOP_FOR*2. */	    beq = js_Emit3(cx, cg, JSOP_IFEQ, 0, 0);	    if (beq < 0)		return JS_FALSE;	} else {	    if (!pn2->pn_kid1) {		/* No initializer: emit an annotated nop for the decompiler. */		noteIndex = js_NewSrcNote(cx, cg, SRC_FOR);		if (noteIndex < 0 ||		    js_Emit1(cx, cg, JSOP_NOP) < 0) {		    return JS_FALSE;		}	    } else {		if (!js_EmitTree(cx, cg, pn2->pn_kid1))		    return JS_FALSE;		noteIndex = js_NewSrcNote(cx, cg, SRC_FOR);		if (noteIndex < 0 ||		    js_Emit1(cx, cg, JSOP_POP) < 0) {		    return JS_FALSE;		}	    }	    top = CG_OFFSET(cg);	    SET_STATEMENT_TOP(&stmtInfo, top);	    if (!pn2->pn_kid2) {		/* No loop condition: flag this fact in the source notes. */		if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, 0))		    return JS_FALSE;		beq = 0;	    } else {		if (!js_EmitTree(cx, cg, pn2->pn_kid2))		    return JS_FALSE;		if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0,					 (ptrdiff_t)(CG_OFFSET(cg) - top))) {		    return JS_FALSE;		}		beq = js_Emit3(cx, cg, JSOP_IFEQ, 0, 0);		if (beq < 0)		    return JS_FALSE;	    }	}	/* Emit code for the loop body. */	if (!js_EmitTree(cx, cg, pn->pn_right))	    return JS_FALSE;	if (pn2->pn_type != TOK_IN) {	    /* Set the second note offset so we can find the update part. */	    PR_ASSERT(noteIndex != -1);	    if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 1,				     (ptrdiff_t)(CG_OFFSET(cg) - top))) {		return JS_FALSE;	    }	    pn3 = pn2->pn_kid3;	    if (pn3) {		/* Set loop and enclosing "update" offsets, for continue. */		stmt = &stmtInfo;		do {		    stmt->update = CG_OFFSET(cg);		} while ((stmt = stmt->down) != NULL &&			 stmt->type == STMT_LABEL);		if (!js_EmitTree(cx, cg, pn3))		    return JS_FALSE;		if (js_Emit1(cx, cg, JSOP_POP) < 0)		    return JS_FALSE;		/* Restore the absolute line number for source note readers. */		off = (ptrdiff_t) pn->pn_pos.end.lineno;		if (cg->currentLine != (uintN) off) {		    if (js_NewSrcNote2(cx, cg, SRC_SETLINE, off) < 0)			return JS_FALSE;		    cg->currentLine = (uintN) off;		}	    }	    /* The third note offset helps us find the loop-closing jump. */	    if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 2,				     (ptrdiff_t)(CG_OFFSET(cg) - top))) {		return JS_FALSE;	    }	}	/* Emit the loop-closing jump and fixup all jump offsets. */	jmp = js_Emit3(cx, cg, JSOP_GOTO, 0, 0);	if (jmp < 0)	    return JS_FALSE;	CHECK_AND_SET_JUMP_OFFSET(cx, cg, CG_CODE(cg,jmp), top - jmp);	if (beq > 0)	    CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);	/* Now fixup all breaks and continues (before for/in's final POP2). */	if (!js_PopStatementCG(cx, cg))	    return JS_FALSE;	if (pn2->pn_type == TOK_IN) {	    /*	     * Generate the object and iterator pop opcodes after popping the	     * stmtInfo stack, so breaks will go to this pop bytecode.	     */	    if (js_Emit1(cx, cg, JSOP_POP2) < 0)		return JS_FALSE;	}	break;      case TOK_BREAK:	stmt = cg->treeContext.topStmt;	atom = pn->pn_atom;	if (atom) {	    ale = js_IndexAtom(cx, atom, &cg->atomList);	    if (!ale)	    	return JS_FALSE;	    while (stmt->type != STMT_LABEL || stmt->label != atom)		stmt = stmt->down;	} else {	    ale = NULL;	    while (!STMT_IS_LOOP(stmt) && stmt->type != STMT_SWITCH)		stmt = stmt->down;	}	if (js_EmitBreak(cx, cg, stmt, ale) < 0)	    return JS_FALSE;	break;      case TOK_CONTINUE:	stmt = cg->treeContext.topStmt;	atom = pn->pn_atom;	if (atom) {	    ale = js_IndexAtom(cx, atom, &cg->atomList);	    if (!ale)	    	return JS_FALSE;	    while (stmt->type != STMT_LABEL || stmt->label != atom)		stmt = stmt->down;	} else {	    ale = NULL;	    while (!STMT_IS_LOOP(stmt))		stmt = stmt->down;	    if (js_NewSrcNote(cx, cg, SRC_CONTINUE) < 0)		return JS_FALSE;	}	if (js_EmitContinue(cx, cg, stmt, ale) < 0)	    return JS_FALSE;	break;      case TOK_WITH:	if (!js_EmitTree(cx, cg, pn->pn_left))	    return JS_FALSE;	js_PushStatement(&cg->treeContext, &stmtInfo, STMT_WITH, CG_OFFSET(cg));	if (js_Emit1(cx, cg, JSOP_ENTERWITH) < 0)	    return JS_FALSE;	if (!js_EmitTree(cx, cg, pn->pn_right))	    return JS_FALSE;	if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)	    return JS_FALSE;	return js_PopStatementCG(cx, cg);#if JS_HAS_EXCEPTIONS      case TOK_TRY: {	ptrdiff_t start, end, catchStart, finallyCatch, catchjmp = -1;	JSParseNode *iter = pn;	/* XXX use -(CG_OFFSET + 1) */#define EMIT_FINALLY_JSR(cx, cg)                                              \	PR_BEGIN_MACRO                                                        \	if (!js_Emit3(cx, cg, JSOP_JSR, 0, 0))                                \	    return JS_FALSE;                                                  \	PR_END_MACRO;	/*	 * When a finally block is `active' (STMT_FINALLY on the treeContext),	 * non-local jumps result in a JSR being written into the bytecode	 * stream for later fixup.  The jsr is written with offset 0 for the	 * innermost finally, -1 for the next, etc.  As the finally fixup code	 * runs for each finished try/finally, it will fix the JSRs with	 * offset 0 to match the appropriate finally code for its block	 * and decrement all others by one.	 *	 * NOTE: This will cause problems if we use JSRs for something other	 * than finally handling in the future.  Caveat hacker!	 */	if (pn->pn_kid3) {	    js_PushStatement(&cg->treeContext, &stmtInfo, STMT_FINALLY,			     CG_OFFSET(cg));	}	/* mark try location for decompilation, then emit try block */	if (js_NewSrcNote2(cx, cg, SRC_TRYFIN, 0) < 0 ||	    js_Emit1(cx, cg, JSOP_NOP) < 0)	    return JS_FALSE;	start = CG_OFFSET(cg);	if(!js_EmitTree(cx, cg, pn->pn_kid1))	    return JS_FALSE;	/* emit (hidden) jump over catch and/or finally */	if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)	    return JS_FALSE;	if (pn->pn_kid3)	    EMIT_FINALLY_JSR(cx, cg);	if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)	    return JS_FALSE;	jmp = js_Emit3(cx, cg, JSOP_GOTO, 0, 0);	if (jmp < 0)	    return JS_FALSE;	end = CG_OFFSET(cg);	/* if this try has a catch block, emit it */	if (pn->pn_kid2) {	    catchStart = end;	    /*	     * The emitted code for a catch block looks like:	     *	     * [ popscope ]                       only if 2nd+ catch block	     * name Object	     * pushobj	     * newinit	     * exception	     * initprop <atom>                    maybe marked SRC_CATCHGUARD	     * enterwith	     * [< catchguard code >]              if there's a catchguard	     * ifeq <offset to next catch block>	     * < catch block contents >	     * leavewith	     * goto <end of catch blocks>         non-local; finally applies	     *	     * If there's no catch block without a catchguard, the last	     * <offset to next catch block> points to rethrow code.  This	     * code will jsr to the finally code if appropriate, and is	     * also used for the catch-all trynote for capturing exceptions	     * thrown from catch{} blocks.	     */	    do {		JSStmtInfo stmtInfo2;		JSParseNode *disc;		ptrdiff_t guardnote;		iter = iter->pn_kid2;		disc = iter->pn_kid1;		if (catchjmp != -1) {		    /* fix up and clean up previous catch block */		    CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, catchjmp);		    if ((uintN)++cg->stackDepth > cg->maxStackDepth)			cg->maxStackDepth = cg->stackDepth;		    if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||			js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)			return JS_FALSE;		}		/* non-zero guardnote is length of catchguard */		guardnote = js_NewSrcNote2(cx, cg, SRC_CATCH, 0);		if (guardnote < 0 ||		    js_Emit1(cx, cg, JSOP_NOP) < 0)		    return JS_FALSE;		/* construct the scope holder and push it on */		ale = js_IndexAtom(cx, cx->runtime->atomState.ObjectAtom,				   &cg->atomList);		if (!ale)		    return JS_FALSE;       		EMIT_ATOM_INDEX_OP(JSOP_NAME, ale->index);		if (js_Emit1(cx, cg, JSOP_PUSHOBJ) < 0 ||		    js_Emit1(cx, cg, JSOP_NEWINIT) < 0 ||		    js_Emit1(cx, cg, JSOP_EXCEPTION) < 0)		    return JS_FALSE;		/* setprop <atomIndex> */		ale = js_IndexAtom(cx, disc->pn_atom, &cg->atomList);		if (!ale)		    return JS_FALSE; 		EMIT_ATOM_INDEX_OP(JSOP_INITPROP, ale->index);		if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||		    js_Emit1(cx, cg, JSOP_ENTERWITH) < 0)		    return JS_FALSE;		/* boolean_expr */		if (disc->pn_expr) {		    ptrdiff_t guardstart = CG_OFFSET(cg);		    if (!js_EmitTree(cx, cg, disc->pn_expr))			return JS_FALSE;		    /* ifeq <next block> */		    catchjmp = js_Emit3(cx, cg, JSOP_IFEQ, 0, 0);		    if (catchjmp < 0)			return JS_FALSE;		    if (!js_SetSrcNoteOffset(cx, cg, guardnote, 0,					     (ptrdiff_t)CG_OFFSET(cg) -					     guardstart))			return JS_FALSE;		}		/* emit catch block */		js_PushStatement(&cg->treeContext, &stmtInfo2, STMT_WITH,				 CG_OFFSET(cg));		if (!js_EmitTree(cx, cg, iter->pn_kid3))		    return JS_FALSE;		js_PopStatementCG(cx, cg);		/*		 * jump over the remaining catch blocks		 * this counts as a non-local jump, so do the finally thing		 */		/* popscope */		if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||		    js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)		    return JS_FALSE;		/* jsr <finally>, if required */		if (pn->pn_kid3)		    EMIT_FINALLY_JSR(cx, cg);		/* this will get fixed up to jump to after catch/finally */		if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||		    js_Emit3(cx, cg, JSOP_GOTO, 0, 0) < 0)		    return JS_FALSE;		if (!iter->pn_kid2)		    break;	    } while (iter);	}	/*	 * we use a [leavewith],[jsr],rethrow block for rethrowing	 * when there's no unguarded catch, and also for	 * running finally code while letting an uncaught exception	 * pass through	 */	if (pn->pn_kid3 ||	    (catchjmp != -1 && iter->pn_kid1->pn_expr)) {	    if (catchjmp != -1) {		CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, catchjmp);	    }	    /* last discriminant jumps to rethrow if none match */	    if ((uintN)++cg->stackDepth > cg->maxStackDepth)		cg->maxStackDepth = cg->stackDepth;	    if (pn->pn_kid2 &&		(js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||		 js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0))		return JS_FALSE;	    if (pn->pn_kid3) {		finallyCatch = CG_OFFSET(cg);		EMIT_FINALLY_JSR(cx, cg);	    }	    if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||		js_Emit1(cx, cg, JSOP_EXCEPTION) < 0 ||		js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||		js_Emit1(cx, cg, JSOP_THROW) < 0)		return JS_FALSE;	}	/* if we've got a finally, it goes here, and we have to fix up	   the jsrs that might have been emitted before non-local jumps */	if (pn->pn_kid3) {	    ptrdiff_t finallyIndex;	    finallyIndex = CG_OFFSET(cg);	    if (!FixupFinallyJumps(cx, cg, start, finallyIndex))		return JS_FALSE;	    js_PopStatementCG(cx, cg);	    if (js_NewSrcNote2(cx, cg, SRC_TRYFIN, 1) < 0 ||		js_Emit1(cx, cg, JSOP_NOP) < 0 ||		!js_EmitTree(cx, cg, pn->pn_kid3) ||		js_Emit1(cx, cg, JSOP_RETSUB) < 0)		return JS_FALSE;	}	if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 ||	    js_Emit1(cx, cg, JSOP_NOP) < 0)	    return JS_FALSE;	/* fix up the end-of-try/catch jumps to come here */	if (!FixupCatchJumps(cx, cg, start, CG_OFFSET(cg)))	    return JS_FALSE;	CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);	/*	 * Add the try note last, to let post-order give us the right ordering	 * (first to last, inner to outer).	 */	if (pn->pn_kid2 &&	    !js_NewTryNote(cx, cg, start, end, catchStart))	    return JS_FALSE;	/*	 * If we've got a finally, mark try+catch region with additional	 * trynote to catch exceptions (re)thrown from a catch block or	 * for the try{}finally{} case.	 */	if (pn->pn_kid3 &&	    !js_NewTryNote(cx, cg, start, finallyCatch-1, finallyCatch))	    return JS_FALSE;	break;      }#endif /* JS_HAS_EXCEPTIONS */      case TOK_VAR:	noteIndex = -1;	for (pn2 = pn->pn_head; ; pn2 = pn2->pn_next) {	    PR_ASSERT(pn2->pn_type == TOK_NAME);	    op = pn2->pn_op;	    if (pn2->pn_slot >= 0) {		atomIndex = (jsatomid) pn2->pn_slot;	    } else {		ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList);		if (!ale)		    return JS_FALSE;		atomIndex = ale->index;	    }	    if (pn2->pn_expr) {		if (op == JSOP_SETNAME2)		    EMIT_ATOM_INDEX_OP(JSOP_BINDNAME, atomIndex);		if (!js_EmitTree(cx, cg, pn2->pn_expr))		    return JS_FALSE;	    }	    if (pn2 == pn->pn_head && js_NewSrcNote(cx, cg, SRC_VAR) < 0)		return JS_FALSE;	    EMIT_ATOM_INDEX_OP(op, atomIndex);	    tmp = CG_OFFSET(cg);	    if (noteIndex >= 0) {		if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, tmp - off))		    return JS_FALSE;	    }	    if (!pn2->pn_next)	    	break;	    off = tmp;	    noteIndex = js_NewSrcNote2(cx, cg, SRC_COMMA, 0);	    if (noteIndex < 0 ||		js_Emit1(cx, cg, JSOP_POP) < 0) {		return JS_FALSE;	    }	}	if (pn->pn_op != JSOP_NOP) {	    if (js_Emit1(cx, cg, pn->pn_op) < 0)		return JS_FALSE;      	}      	break;      case TOK_RETURN:	pn2 = pn->pn_kid;	if (pn2) {	    if (!js_EmitTree(cx, cg, pn2))		return JS_FALSE;	} else {	    if (js_Emit1(cx, cg, JSOP_PUSH) < 0)		return JS_FALSE;      	}	if (js_Emit1(cx, cg, JSOP_RETURN) < 0)	    return JS_FALSE;	break;      case TOK_LC:	js_PushStatement(&cg->treeContext, &stmtInfo, STMT_BLOCK, top);	for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {	    if (!js_EmitTree(cx, cg, pn2))		return JS_FALSE;	}	return js_PopStatementCG(cx, cg);      case TOK_SEMI:	if (pn->pn_kid) {	    if (!js_EmitTree(cx, cg, pn->pn_kid))		return JS_FALSE;	    if (js_Emit1(cx, cg, JSOP_POPV) < 0)		return JS_FALSE;      	}      	break;      case TOK_COLON:	/* Emit an annotated nop so we know to decompile a label. */	atom = pn->pn_atom;	ale = js_IndexAtom(cx, atom, &cg->atomList);	if (!ale)	    return JS_FALSE;	pn2 = pn->pn_expr;	noteIndex = js_NewSrcNote2(cx, cg,				   (pn2->pn_type == TOK_LC)				   ? SRC_LABELBRACE				   : SRC_LABEL,				   (ptrdiff_t)ale->index);	if (noteIndex < 0 ||	    js_Emit1(cx, cg, JSOP_NOP) < 0) {	    return JS_FALSE;	}	/* Emit code for the labeled statement. */	js_PushStatement(&cg->treeContext, &stmtInfo, STMT_LABEL, CG_OFFSET(cg));	stmtInfo.label = atom;	if (!js_EmitTree(cx, cg, pn2))	    return JS_FALSE;	if (!js_PopStatementCG(cx, cg))	    return JS_FALSE;	/* If the statement was compound, emit a note for the end brace. */	if (pn2->pn_type == TOK_LC) {	    if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 ||		js_Emit1(cx, cg, JSOP_NOP) < 0) {		return JS_FALSE;	    }	}      	break;      case TOK_COMMA:	/*	 * Emit SRC_COMMA notes on each JSOP_POP between comma operands.	 * These notes help the decompiler bracket the bytecodes generated	 * from each sub-expression that follows a comma.	 */	noteIndex = -1;	for (pn2 = pn->pn_head; ; pn2 = pn2->pn_next) {	    if (!js_EmitTree(cx, cg, pn2))		return JS_FALSE;	    tmp = CG_OFFSET(cg);	    if (noteIndex >= 0) {		if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, tmp - off))		    return JS_FALSE;	    }	    if (!pn2->pn_next)		break;	    off = tmp;	    noteIndex = js_NewSrcNote2(cx, cg, SRC_COMMA, 0);	    if (noteIndex < 0 ||		js_Emit1(cx, cg, JSOP_POP) < 0) {		return JS_FALSE;	    }	}      	break;      case TOK_ASSIGN:      	/*      	 * Check left operand type and generate specialized code for it.      	 * Specialize to avoid ECMA "reference type" values on the operand      	 * stack, which impose pervasive runtime "GetValue" costs.      	 */	pn2 = pn->pn_left;	PR_ASSERT(pn2->pn_type != TOK_RP);      	switch (pn2->pn_type) {	  case TOK_NAME:	    if (pn2->pn_slot >= 0) {	    	atomIndex = (jsatomid) pn2->pn_slot;	    } else {		ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList);		if (!ale)		    return JS_FALSE;		atomIndex = ale->index;		EMIT_ATOM_INDEX_OP(JSOP_BINDNAME, atomIndex);	    }	    break;	  case TOK_DOT:	    if (!js_EmitTree(cx, cg, pn2->pn_expr))	    	return JS_FALSE;	    ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList);	    if (!ale)	    	return JS_FALSE;	    atomIndex = ale->index;	    break;	  case TOK_LB:	    if (!js_EmitTree(cx, cg, pn2->pn_left))		return JS_FALSE;	    if (!js_EmitTree(cx, cg, pn2->pn_right))		return JS_FALSE;	    break;	  default:	    PR_ASSERT(0);	}	/* If += or similar, dup the left operand and get its value. */	op = pn->pn_op;	if (op != JSOP_NOP) {	    switch (pn2->pn_type) {	      case TOK_NAME:		if (pn2->pn_op != JSOP_SETNAME2) {		    EMIT_ATOM_INDEX_OP((pn2->pn_op == JSOP_SETARG)				       ? JSOP_GETARG				       : JSOP_GETVAR,				       atomIndex);		    break;		}		/* FALL THROUGH */	      case TOK_DOT:		if (js_Emit1(cx, cg, JSOP_DUP) < 0)		    return JS_FALSE;		EMIT_ATOM_INDEX_OP(JSOP_GETPROP, atomIndex);		break;	      case TOK_LB:		if (js_Emit1(cx, cg, JSOP_DUP2) < 0)		    return JS_FALSE;		if (js_Emit1(cx, cg, JSOP_GETELEM) < 0)		    return JS_FALSE;		break;	      default:;	    }	}	/* Now emit the right operand (it may affect the namespace). */	if (!js_EmitTree(cx, cg, pn->pn_right))	    return JS_FALSE;	/* If += etc., emit the binary operator with a decompiler note. */	if (op != JSOP_NOP) {	    if (js_NewSrcNote(cx, cg, SRC_ASSIGNOP) < 0 ||		js_Emit1(cx, cg, op) < 0) {		return JS_FALSE;	    }	}	/* Left parts such as a.b.c and a[b].c need a decompiler note. */	if (pn2->pn_type != TOK_NAME) {	    if (js_NewSrcNote2(cx, cg, SRC_PCBASE,			       (ptrdiff_t)(CG_OFFSET(cg) - top)) < 0) {		return JS_FALSE;	    }	}	/* Finally, emit the specialized assignment bytecode. */	switch (pn2->pn_type) {	  case TOK_NAME:	  case TOK_DOT:	    EMIT_ATOM_INDEX_OP(pn2->pn_op, atomIndex);	    break;	  case TOK_LB:	    if (js_Emit1(cx, cg, JSOP_SETELEM) < 0)		return JS_FALSE;	    break;	  default:;	}      	break;      case TOK_HOOK:	/* Emit the condition, then branch if false to the else part. */	if (!js_EmitTree(cx, cg, pn->pn_kid1))	    return JS_FALSE;	if (js_NewSrcNote(cx, cg, SRC_COND) < 0)	    return JS_FALSE;	beq = js_Emit3(cx, cg, JSOP_IFEQ, 0, 0);	if (beq < 0 || !js_EmitTree(cx, cg, pn->pn_kid2))	    return JS_FALSE;	/* Jump around else, fixup the branch, emit else, fixup jump. */	jmp = js_Emit3(cx, cg, JSOP_GOTO, 0, 0);	if (jmp < 0)	    return JS_FALSE;	CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);	if (!js_EmitTree(cx, cg, pn->pn_kid3))	    return JS_FALSE;	CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);	break;      case TOK_OR:	/* Emit left operand, emit pop-if-converts-to-false-else-jump. */	if (!js_EmitTree(cx, cg, pn->pn_left))	    return JS_FALSE;#if JS_BUG_SHORT_CIRCUIT	beq = js_Emit3(cx, cg, JSOP_IFEQ, 0, 0);	tmp = js_Emit1(cx, cg, JSOP_TRUE);	jmp = js_Emit3(cx, cg, JSOP_GOTO, 0, 0);	if (beq < 0 || tmp < 0 || jmp < 0)	    return JS_FALSE;	CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);#else	/*	 * JSOP_OR converts the operand on the stack to boolean, and if true,	 * leaves the original operand value on the stack and jumps; otherwise	 * it pops and falls into the next bytecode.	 */	jmp = js_Emit3(cx, cg, JSOP_OR, 0, 0);	if (jmp < 0)	    return JS_FALSE;#endif	if (!js_EmitTree(cx, cg, pn->pn_right))	    return JS_FALSE;	CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);	break;      case TOK_AND:	/* && is like || except it uses a pop-if-converts-to-true-else-jump. */	if (!js_EmitTree(cx, cg, pn->pn_left))	    return JS_FALSE;#if JS_BUG_SHORT_CIRCUIT	beq = js_Emit3(cx, cg, JSOP_IFNE, 0, 0);	tmp = js_Emit1(cx, cg, JSOP_FALSE);	jmp = js_Emit3(cx, cg, JSOP_GOTO, 0, 0);	if (beq < 0 || tmp < 0 || jmp < 0)	    return JS_FALSE;	CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);#else	jmp = js_Emit3(cx, cg, JSOP_AND, 0, 0);	if (jmp < 0)	    return JS_FALSE;#endif	if (!js_EmitTree(cx, cg, pn->pn_right))	    return JS_FALSE;	CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);	break;      case TOK_BITOR:      case TOK_BITXOR:      case TOK_BITAND:      case TOK_EQOP:      case TOK_RELOP:#if JS_HAS_IN_OPERATOR      case TOK_IN:#endif#if JS_HAS_INSTANCEOF      case TOK_INSTANCEOF:#endif      case TOK_SHOP:      case TOK_PLUS:      case TOK_MINUS:      case TOK_STAR:      case TOK_DIVOP:      	/* Binary operators that evaluate both operands unconditionally. */      	if (!js_EmitTree(cx, cg, pn->pn_left))	    return JS_FALSE;      	if (!js_EmitTree(cx, cg, pn->pn_right))	    return JS_FALSE;	if (js_Emit1(cx, cg, pn->pn_op) < 0)	    return JS_FALSE;	break;#if JS_HAS_EXCEPTIONS      case TOK_THROW:#endif      case TOK_UNARYOP:	/* Unary op, including unary +/-. */	if (!js_EmitTree(cx, cg, pn->pn_kid))	    return JS_FALSE;	if (js_Emit1(cx, cg, pn->pn_op) < 0)	    return JS_FALSE;	break;      case TOK_INC:      case TOK_DEC:	/* Emit lvalue-specialized code for ++/-- operators. */	pn2 = pn->pn_kid;	PR_ASSERT(pn2->pn_type != TOK_RP);	op = pn->pn_op;	switch (pn2->pn_type) {	  case TOK_NAME:	    if (pn->pn_num >= 0) {		atomIndex = (jsatomid) pn->pn_num;		EMIT_ATOM_INDEX_OP(op, atomIndex);	    } else {		if (!EmitAtomOp(cx, pn2, op, cg))		    return JS_FALSE;	    }	    break;	  case TOK_DOT:	    if (!EmitPropOp(cx, pn2, op, cg))	    	return JS_FALSE;	    break;	  case TOK_LB:	    if (!EmitElemOp(cx, pn2, op, cg))	    	return JS_FALSE;	    break;	  default:	    PR_ASSERT(0);	}      	break;      case TOK_NEW:      	/* Code for (new f()) and f() are the same, except for the opcode. */      	op = JSOP_NEW;      	goto emit_call;      case TOK_DELETE:	/* Delete is also lvalue-specialized to avoid reference types. */	pn2 = pn->pn_kid;	PR_ASSERT(pn2->pn_type != TOK_RP);      	switch (pn2->pn_type) {	  case TOK_NAME:	    if (!EmitAtomOp(cx, pn2, JSOP_DELNAME, cg))	    	return JS_FALSE;	    break;	  case TOK_DOT:	    if (!EmitPropOp(cx, pn2, JSOP_DELPROP, cg))	    	return JS_FALSE;	    break;	  case TOK_LB:	    if (!EmitElemOp(cx, pn2, JSOP_DELELEM, cg))	    	return JS_FALSE;	    break;	  default:	    PR_ASSERT(0);	}      	break;      case TOK_DOT:	/*	 * Pop a stack operand, convert it to object, get a property named by	 * this bytecode's immediate-indexed atom operand, and push its value	 * (not a reference to it).  This bytecode sets the virtual machine's	 * "obj" register to the left operand's ToObject conversion result,	 * for use by JSOP_PUSHOBJ.	 */	return EmitPropOp(cx, pn, pn->pn_op, cg);      case TOK_LB:	/*	 * Pop two operands, convert the left one to object and the right one	 * to property name (atom or tagged int), get the named property, and	 * push its value.  Set the "obj" register to the result of ToObject	 * on the left operand.	 */	return EmitElemOp(cx, pn, pn->pn_op, cg);      case TOK_LP:	/*	 * Emit function call or operator new (constructor call) code.  First	 * emit code for the left operand to evaluate the call- or construct-	 * able object expression.	 */	op = JSOP_CALL;      emit_call:	pn2 = pn->pn_head;	if (!js_EmitTree(cx, cg, pn2))	    return JS_FALSE;	/*	 * Push the virtual machine's "obj" register, which was set by a name,	 * property, or element get (or set) bytecode.	 */	if (js_Emit1(cx, cg, JSOP_PUSHOBJ) < 0)	    return JS_FALSE;      	/*      	 * Emit code for each argument in order, then emit the JSOP_CALL or      	 * JSOP_NEW bytecode with a two-byte immediate telling how many args      	 * were pushed on the operand stack.      	 */      	for (pn2 = pn2->pn_next; pn2; pn2 = pn2->pn_next) {	    if (!js_EmitTree(cx, cg, pn2))		return JS_FALSE;      	}	argc = pn->pn_count - 1;	if (js_Emit3(cx, cg, op, ARGC_HI(argc), ARGC_LO(argc)) < 0)	    return JS_FALSE;	break;#if JS_HAS_INITIALIZERS      case TOK_RB:	/*	 * Emit code for [a, b, c] of the form:	 *   t = new Array; t[0] = a; t[1] = b; t[2] = c; t;	 * but use a stack slot for t and avoid dup'ing and popping it via	 * the JSOP_NEWINIT and JSOP_INITELEM bytecodes.	 */	ale = js_IndexAtom(cx, cx->runtime->atomState.ArrayAtom,			   &cg->atomList);	if (!ale)	    return JS_FALSE;	EMIT_ATOM_INDEX_OP(JSOP_NAME, ale->index);	if (js_Emit1(cx, cg, JSOP_PUSHOBJ) < 0)	    return JS_FALSE;	if (js_Emit1(cx, cg, JSOP_NEWINIT) < 0)	    return JS_FALSE;	pn2 = pn->pn_head;#if JS_HAS_SHARP_VARS	if (pn2 && pn2->pn_type == TOK_DEFSHARP) {	    EMIT_ATOM_INDEX_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);	    pn2 = pn2->pn_next;	}#endif	for (atomIndex = 0; pn2; pn2 = pn2->pn_next) {	    /* PrimaryExpr enforced ATOM_INDEX_LIMIT, so in-line optimize. */	    PR_ASSERT(atomIndex < ATOM_INDEX_LIMIT);	    if (atomIndex == 0) {		if (js_Emit1(cx, cg, JSOP_ZERO) < 0)		    return JS_FALSE;	    } else if (atomIndex == 1) {		if (js_Emit1(cx, cg, JSOP_ONE) < 0)		    return JS_FALSE;	    } else {		EMIT_ATOM_INDEX_OP(JSOP_UINT16, (jsatomid)atomIndex);	    }	    /* Sub-optimal: holes in a sparse initializer are void-filled. */	    if (pn2->pn_type == TOK_COMMA) {		if (js_Emit1(cx, cg, JSOP_PUSH) < 0)		    return JS_FALSE;	    } else {		if (!js_EmitTree(cx, cg, pn2))		    return JS_FALSE;	    }	    if (js_Emit1(cx, cg, JSOP_INITELEM) < 0)		return JS_FALSE;	    atomIndex++;	}	if (pn->pn_extra) {	    /* Emit a source note so we know to decompile an extra comma. */	    if (js_NewSrcNote(cx, cg, SRC_COMMA) < 0)		return JS_FALSE;	}	/* Emit an op for sharp array cleanup and decompilation. */	if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0)	    return JS_FALSE;	break;      case TOK_RC:	/*	 * Emit code for {p:a, '%q':b, 2:c} of the form:	 *   t = new Object; t.p = a; t['%q'] = b; t[2] = c; t;	 * but use a stack slot for t and avoid dup'ing and popping it via	 * the JSOP_NEWINIT and JSOP_INITELEM bytecodes.	 */	ale = js_IndexAtom(cx, cx->runtime->atomState.ObjectAtom,			   &cg->atomList);	if (!ale)	    return JS_FALSE;	EMIT_ATOM_INDEX_OP(JSOP_NAME, ale->index);	if (js_Emit1(cx, cg, JSOP_PUSHOBJ) < 0)	    return JS_FALSE;	if (js_Emit1(cx, cg, JSOP_NEWINIT) < 0)	    return JS_FALSE;	pn2 = pn->pn_head;#if JS_HAS_SHARP_VARS	if (pn2 && pn2->pn_type == TOK_DEFSHARP) {	    EMIT_ATOM_INDEX_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);	    pn2 = pn2->pn_next;	}#endif	for (; pn2; pn2 = pn2->pn_next) {	    /* Emit an index for t[2], else map an atom for t.p or t['%q']. */	    pn3 = pn2->pn_left;	    switch (pn3->pn_type) {	      case TOK_NUMBER:		if (!EmitNumberOp(cx, pn3->pn_dval, cg))		    return JS_FALSE;		break;	      case TOK_NAME:	      case TOK_STRING:		ale = js_IndexAtom(cx, pn3->pn_atom, &cg->atomList);		if (!ale)		    return JS_FALSE;		break;	      default:		PR_ASSERT(0);	    }	    /* Emit code for the property initializer. */	    if (!js_EmitTree(cx, cg, pn2->pn_right))		return JS_FALSE;	    /* Annotate JSOP_INITELEM so we decompile 2:c and not just c. */	    if (pn3->pn_type == TOK_NUMBER) {		if (js_NewSrcNote(cx, cg, SRC_LABEL) < 0)		    return JS_FALSE;		if (js_Emit1(cx, cg, JSOP_INITELEM) < 0)		    return JS_FALSE;	    } else {		EMIT_ATOM_INDEX_OP(JSOP_INITPROP, ale->index);	    }	}	/* Emit an op for sharpArray cleanup and decompilation. */	if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0)	    return JS_FALSE;	break;#if JS_HAS_SHARP_VARS      case TOK_DEFSHARP:	if (!js_EmitTree(cx, cg, pn->pn_kid))	    return JS_FALSE;	EMIT_ATOM_INDEX_OP(JSOP_DEFSHARP, (jsatomid) pn->pn_num);      	break;      case TOK_USESHARP:	EMIT_ATOM_INDEX_OP(JSOP_USESHARP, (jsatomid) pn->pn_num);      	break;#endif /* JS_HAS_SHARP_VARS */#endif /* JS_HAS_INITIALIZERS */      case TOK_RP:      	/*      	 * The node for (e) has e as its kid, enabling users who want to nest	 * assignment expressions in conditions to avoid the error correction	 * done by Condition (from x = y to x == y) by double-parenthesizing.	 *	 * We also emit an annotated NOP so we can decompile user parentheses,	 * but that's just a nicety (the decompiler does not preserve comments	 * or white space, and it parenthesizes for correct precedence anyway,	 * so this nop nicety should be considered with a cold eye, especially	 * if another srcnote type is needed).      	 */      	if (!js_EmitTree(cx, cg, pn->pn_kid))	    return JS_FALSE;	if (js_NewSrcNote(cx, cg, SRC_PAREN) < 0 ||	    js_Emit1(cx, cg, JSOP_NOP) < 0) {	    return JS_FALSE;	}      	break;      case TOK_NAME:      	if (pn->pn_slot >= 0) {	    EMIT_ATOM_INDEX_OP(pn->pn_op, (jsatomid) pn->pn_slot);	    break;	}	/* FALL THROUGH */      case TOK_STRING:      case TOK_OBJECT:	/*	 * The scanner and parser associate JSOP_NAME with TOK_NAME, although	 * other bytecodes may result instead (JSOP_BINDNAME/JSOP_SETNAME2,	 * JSOP_FORNAME2, etc.).  Among JSOP_*NAME* variants, only JSOP_NAME	 * may generate the first operand of a call or new expression, so only	 * it sets the "obj" virtual machine register to the object along the	 * scope chain in which the name was found.	 *	 * Token types for STRING and OBJECT have corresponding bytecode ops	 * in pn_op and emit the same format as NAME, so they share this code.	 */	return EmitAtomOp(cx, pn, pn->pn_op, cg);      case TOK_NUMBER:	return EmitNumberOp(cx, pn->pn_dval, cg);      case TOK_PRIMARY:	return js_Emit1(cx, cg, pn->pn_op) >= 0;#if JS_HAS_DEBUGGER_KEYWORD      case TOK_DEBUGGER:	return js_Emit1(cx, cg, JSOP_DEBUGGER) >= 0;#endif /* JS_HAS_DEBUGGER_KEYWORD */      default:      	PR_ASSERT(0);    }    return JS_TRUE;}