⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsemit.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 5 页
字号:
        if (!AddSpanDep(cx, cg, pc, pc, off))            return JS_FALSE;    }    return jmp;}static ptrdiff_tGetJumpOffset(JSCodeGenerator *cg, jsbytecode *pc){    JSSpanDep *sd;    JSJumpTarget *jt;    ptrdiff_t top;    if (!cg->spanDeps)        return GET_JUMP_OFFSET(pc);    sd = GetSpanDep(cg, pc);    jt = sd->target;    if (!JT_HAS_TAG(jt))        return JT_TO_BPDELTA(jt);    top = sd->top;    while (--sd >= cg->spanDeps && sd->top == top)        continue;    sd++;    return JT_CLR_TAG(jt)->offset - sd->offset;}JSBooljs_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,                 ptrdiff_t off){    if (!cg->spanDeps) {        if (JUMP_OFFSET_MIN <= off && off <= JUMP_OFFSET_MAX) {            SET_JUMP_OFFSET(pc, off);            return JS_TRUE;        }        if (!BuildSpanDepTable(cx, cg))            return JS_FALSE;    }    return SetSpanDepTarget(cx, cg, GetSpanDep(cg, pc), off);}JSBooljs_InWithStatement(JSTreeContext *tc){    JSStmtInfo *stmt;    for (stmt = tc->topStmt; stmt; stmt = stmt->down) {        if (stmt->type == STMT_WITH)            return JS_TRUE;    }    return JS_FALSE;}JSBooljs_InCatchBlock(JSTreeContext *tc, JSAtom *atom){    JSStmtInfo *stmt;    for (stmt = tc->topStmt; stmt; stmt = stmt->down) {        if (stmt->type == STMT_CATCH && stmt->label == atom)            return JS_TRUE;    }    return JS_FALSE;}voidjs_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,                 ptrdiff_t top){    stmt->type = type;    SET_STATEMENT_TOP(stmt, top);    stmt->label = NULL;    stmt->down = tc->topStmt;    tc->topStmt = stmt;}/* * Emit a backpatch op with offset pointing to the previous jump of this type, * so that we can walk back up the chain fixing up the op and jump offset. */#define EMIT_BACKPATCH_OP(cx, cg, last, op, jmp)                              \    JS_BEGIN_MACRO                                                            \        ptrdiff_t offset, delta;                                              \        offset = CG_OFFSET(cg);                                               \        delta = offset - (last);                                              \        last = offset;                                                        \        JS_ASSERT(delta > 0);                                                 \        jmp = EmitJump((cx), (cg), (op), (delta));                            \    JS_END_MACRO/* Emit additional bytecode(s) for non-local jumps. */static JSBoolEmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,                      JSOp *returnop){    intN depth;    JSStmtInfo *stmt;    ptrdiff_t jmp;    /*     * Return from within a try block that has a finally clause must be split     * into two ops: JSOP_SETRVAL, to pop the r.v. and store it in fp->rval;     * and JSOP_RETRVAL, which makes control flow go back to the caller, who     * picks up fp->rval as usual.  Otherwise, the stack will be unbalanced     * when executing the finally clause.     *     * We mutate *returnop once only if we find an enclosing try-block (viz,     * STMT_FINALLY) to ensure that we emit just one JSOP_SETRVAL before one     * or more JSOP_GOSUBs and other fixup opcodes emitted by this function.     * Our caller (the TOK_RETURN case of js_EmitTree) then emits *returnop.     * The fixup opcodes and gosubs must interleave in the proper order, from     * inner statement to outer, so that finally clauses run at the correct     * stack depth.     */    if (returnop) {        JS_ASSERT(*returnop == JSOP_RETURN);        for (stmt = cg->treeContext.topStmt; stmt != toStmt;             stmt = stmt->down) {            if (stmt->type == STMT_FINALLY) {                if (js_Emit1(cx, cg, JSOP_SETRVAL) < 0)                    return JS_FALSE;                *returnop = JSOP_RETRVAL;                break;            }        }        /*         * If there are no try-with-finally blocks open around this return         * statement, we can generate a return forthwith and skip generating         * any fixup code.         */        if (*returnop == JSOP_RETURN)            return JS_TRUE;    }    /*     * The non-local jump fixup we emit will unbalance cg->stackDepth, because     * the fixup replicates balanced code such as JSOP_LEAVEWITH emitted at the     * end of a with statement, so we save cg->stackDepth here and restore it     * just before a successful return.     */    depth = cg->stackDepth;    for (stmt = cg->treeContext.topStmt; stmt != toStmt; stmt = stmt->down) {        switch (stmt->type) {          case STMT_FINALLY:            if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)                return JS_FALSE;            EMIT_BACKPATCH_OP(cx, cg, stmt->gosub, JSOP_BACKPATCH_PUSH, jmp);            if (jmp < 0)                return JS_FALSE;            break;          case STMT_WITH:          case STMT_CATCH:            /* There's a With object on the stack that we need to pop. */            if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)                return JS_FALSE;            if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)                return JS_FALSE;            break;          case STMT_FOR_IN_LOOP:            /*             * The iterator and the object being iterated need to be popped.             * JSOP_POP2 isn't decompiled, so it doesn't need to be HIDDEN.             */            if (js_Emit1(cx, cg, JSOP_POP2) < 0)                return JS_FALSE;            break;          case STMT_SUBROUTINE:            /* There's a retsub pc-offset on the stack that we need to pop. */            if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)                return JS_FALSE;            if (js_Emit1(cx, cg, JSOP_POP) < 0)                return JS_FALSE;            break;          default:;        }    }    cg->stackDepth = depth;    return JS_TRUE;}static ptrdiff_tEmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,         ptrdiff_t *last, JSAtomListElement *label, JSSrcNoteType noteType){    intN index;    ptrdiff_t jmp;    if (!EmitNonLocalJumpFixup(cx, cg, toStmt, NULL))        return -1;    if (label) {        index = js_NewSrcNote(cx, cg, noteType);        if (index < 0)            return -1;        if (!js_SetSrcNoteOffset(cx, cg, (uintN)index, 0,                                 (ptrdiff_t) ALE_INDEX(label))) {            return -1;        }    } else if (noteType != SRC_NULL) {        if (js_NewSrcNote(cx, cg, noteType) < 0)            return -1;    }    EMIT_BACKPATCH_OP(cx, cg, *last, JSOP_BACKPATCH, jmp);    return jmp;}static JSBoolBackPatch(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t last,          jsbytecode *target, jsbytecode op){    jsbytecode *pc, *stop;    ptrdiff_t delta, span;    pc = CG_CODE(cg, last);    stop = CG_CODE(cg, -1);    while (pc != stop) {        delta = GetJumpOffset(cg, pc);        span = PTRDIFF(target, pc, jsbytecode);        CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, span);        /*         * Set *pc after jump offset in case bpdelta didn't overflow, but span         * does (if so, CHECK_AND_SET_JUMP_OFFSET might call BuildSpanDepTable         * and need to see the JSOP_BACKPATCH* op at *pc).         */        *pc = op;        pc -= delta;    }    return JS_TRUE;}voidjs_PopStatement(JSTreeContext *tc){    tc->topStmt = tc->topStmt->down;}JSBooljs_PopStatementCG(JSContext *cx, JSCodeGenerator *cg){    JSStmtInfo *stmt;    stmt = cg->treeContext.topStmt;    if (!BackPatch(cx, cg, stmt->breaks, CG_NEXT(cg), JSOP_GOTO) ||        !BackPatch(cx, cg, stmt->continues, CG_CODE(cg, stmt->update),                   JSOP_GOTO)) {        return JS_FALSE;    }    js_PopStatement(&cg->treeContext);    return JS_TRUE;}JSBooljs_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,                             JSParseNode *pn){    jsdouble dval;    jsint ival;    JSAtom *valueAtom;    JSAtomListElement *ale;    /* XXX just do numbers for now */    if (pn->pn_type == TOK_NUMBER) {        dval = pn->pn_dval;        valueAtom = (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival))                    ? js_AtomizeInt(cx, ival, 0)                    : js_AtomizeDouble(cx, dval, 0);        if (!valueAtom)            return JS_FALSE;        ale = js_IndexAtom(cx, atom, &cg->constList);        if (!ale)            return JS_FALSE;        ALE_SET_VALUE(ale, ATOM_KEY(valueAtom));    }    return JS_TRUE;}JSBooljs_LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,                             jsval *vp){    JSBool ok;    JSStackFrame *fp;    JSAtomListElement *ale;    JSObject *obj, *pobj;    JSProperty *prop;    uintN attrs;    /*     * fp chases cg down the stack, but only until we reach the outermost cg.     * This enables propagating consts from top-level into switch cases in a     * function compiled along with the top-level script.  All stack frames     * with matching code generators should be flagged with JSFRAME_COMPILING;     * we check sanity here.     */    *vp = JSVAL_VOID;    ok = JS_TRUE;    fp = cx->fp;    do {        JS_ASSERT(fp->flags & JSFRAME_COMPILING);        obj = fp->varobj;        if (obj == fp->scopeChain &&            !js_InWithStatement(&cg->treeContext) &&            !js_InCatchBlock(&cg->treeContext, atom)) {            ATOM_LIST_SEARCH(ale, &cg->constList, atom);            if (ale) {                *vp = ALE_VALUE(ale);                return JS_TRUE;            }            /*             * Try looking in the variable object for a direct property that             * is readonly and permanent.  We know such a property can't be             * shadowed by another property on obj's prototype chain, or a             * with object or catch variable; nor can prop's value be changed,             * nor can prop be deleted.             */            prop = NULL;            ok = OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &pobj, &prop);            if (ok) {                if (pobj == obj &&                    (fp->flags & (JSFRAME_EVAL | JSFRAME_COMPILE_N_GO))) {                    /*                     * We're compiling code that will be executed immediately,                     * not re-executed against a different scope chain and/or                     * variable object.  Therefore we can get constant values                     * from our variable object here.                     */                    ok = OBJ_GET_ATTRIBUTES(cx, obj, (jsid)atom, prop, &attrs);                    if (ok && !(~attrs & (JSPROP_READONLY | JSPROP_PERMANENT)))                        ok = OBJ_GET_PROPERTY(cx, obj, (jsid)atom, vp);                }                if (prop)                    OBJ_DROP_PROPERTY(cx, pobj, prop);            }            if (!ok || prop)                break;        }        fp = fp->down;    } while ((cg = cg->parent) != NULL);    return ok;}/* * Emit a bytecode and its 2-byte constant (atom) index immediate operand. * NB: We use cx and cg from our caller's lexical environment, and return * false on error. */#define EMIT_ATOM_INDEX_OP(op, atomIndex)                                     \    JS_BEGIN_MACRO                                                            \        if (js_Emit3(cx, cg, op, ATOM_INDEX_HI(atomIndex),                    \                                 ATOM_INDEX_LO(atomIndex)) < 0) {             \            return JS_FALSE;                                                  \        }                                                                     \    JS_END_MACROstatic JSBoolEmitAtomOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg){    JSAtomListElement *ale;    ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList);    if (!ale)        return JS_FALSE;    EMIT_ATOM_INDEX_OP(op, ALE_INDEX(ale));    return JS_TRUE;}/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -