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

📄 jsemit.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
            /* Ignore with statements enclosing a single let declaration. */            if (letdecl)                continue;            break;        }        /* Skip "maybe scope" statements that don't contain let bindings. */        if (!(stmt->flags & SIF_SCOPE))            continue;        obj = ATOM_TO_OBJECT(stmt->atom);        JS_ASSERT(LOCKED_OBJ_GET_CLASS(obj) == &js_BlockClass);        scope = OBJ_SCOPE(obj);        sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));        if (sprop) {            JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);            if (slotp) {                /*                 * Use LOCKED_OBJ_GET_SLOT since we know obj is single-                 * threaded and owned by this compiler activation.                 */                v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_BLOCK_DEPTH);                JS_ASSERT(JSVAL_IS_INT(v) && JSVAL_TO_INT(v) >= 0);                *slotp = JSVAL_TO_INT(v) + sprop->shortid;            }            return stmt;        }    }    if (slotp)        *slotp = -1;    return stmt;}JSBooljs_LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,                             jsval *vp){    JSBool ok;    JSStackFrame *fp;    JSStmtInfo *stmt;    jsint slot;    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) {            /* XXX this will need revising when 'let const' is added. */            stmt = js_LexicalLookup(&cg->treeContext, atom, &slot, JS_FALSE);            if (stmt)                return JS_TRUE;            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;            if (OBJ_GET_CLASS(cx, obj) == &js_FunctionClass) {                ok = js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(atom),                                             &pobj, &prop);                if (!ok)                    break;                if (prop) {#ifdef DEBUG                    JSScopeProperty *sprop = (JSScopeProperty *)prop;                    /*                     * Any hidden property must be a formal arg or local var,                     * which will shadow a global const of the same name.                     */                    JS_ASSERT(sprop->getter == js_GetArgument ||                              sprop->getter == js_GetLocalVariable);#endif                    OBJ_DROP_PROPERTY(cx, pobj, prop);                    break;                }            }            ok = OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_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, ATOM_TO_JSID(atom), prop,                                            &attrs);                    if (ok && !(~attrs & (JSPROP_READONLY | JSPROP_PERMANENT)))                        ok = OBJ_GET_PROPERTY(cx, obj, ATOM_TO_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;}/* * Allocate an index invariant for all activations of the code being compiled * in cg, that can be used to store and fetch a reference to a cloned RegExp * object that shares the same JSRegExp private data created for the object * literal in pn->pn_atom.  We need clones to hold lastIndex and other direct * properties that should not be shared among threads sharing a precompiled * function or script. * * If the code being compiled is function code, allocate a reserved slot in * the cloned function object that shares its precompiled script with other * cloned function objects and with the compiler-created clone-parent.  There * are fun->nregexps such reserved slots in each function object cloned from * fun->object.  NB: during compilation, funobj slots must never be allocated, * because js_AllocSlot could hand out one of the slots that should be given * to a regexp clone. * * If the code being compiled is global code, reserve the fp->vars slot at * ALE_INDEX(ale), by ensuring that cg->treeContext.numGlobalVars is at least * one more than this index.  For global code, fp->vars is parallel to the * global script->atomMap.vector array, but possibly shorter for the common * case (where var declarations and regexp literals cluster toward the front * of the script or function body). * * Global variable name literals in script->atomMap have fast-global slot * numbers (stored as int-tagged jsvals) in the corresponding fp->vars array * element.  The atomIndex for a regexp object literal thus also addresses an * fp->vars element that is not used by any optimized global variable, so we * use that GC-scanned element to keep the regexp object clone alive, as well * as to lazily create and find it at run-time for the JSOP_REGEXP bytecode. * * In no case can cx->fp->varobj be a Call object here, because that implies * we are compiling eval code, in which case (cx->fp->flags & JSFRAME_EVAL) * is true, and js_GetToken will have already selected JSOP_OBJECT instead of * JSOP_REGEXP, to avoid all this RegExp object cloning business. * * Why clone regexp objects?  ECMA specifies that when a regular expression * literal is scanned, a RegExp object is created.  In the spec, compilation * and execution happen indivisibly, but in this implementation and many of * its embeddings, code is precompiled early and re-executed in multiple * threads, or using multiple global objects, or both, for efficiency. * * In such cases, naively following ECMA leads to wrongful sharing of RegExp * objects, which makes for collisions on the lastIndex property (especially * for global regexps) and on any ad-hoc properties.  Also, __proto__ and * __parent__ refer to the pre-compilation prototype and global objects, a * pigeon-hole problem for instanceof tests. */static JSBoolIndexRegExpClone(JSContext *cx, JSParseNode *pn, JSAtomListElement *ale,                 JSCodeGenerator *cg){    JSObject *varobj, *reobj;    JSClass *clasp;    JSFunction *fun;    JSRegExp *re;    uint16 *countPtr;    uintN cloneIndex;    JS_ASSERT(!(cx->fp->flags & (JSFRAME_EVAL | JSFRAME_COMPILE_N_GO)));    varobj = cx->fp->varobj;    clasp = OBJ_GET_CLASS(cx, varobj);    if (clasp == &js_FunctionClass) {        fun = (JSFunction *) JS_GetPrivate(cx, varobj);        countPtr = &fun->u.i.nregexps;        cloneIndex = *countPtr;    } else {        JS_ASSERT(clasp != &js_CallClass);        countPtr = &cg->treeContext.numGlobalVars;        cloneIndex = ALE_INDEX(ale);    }    if ((cloneIndex + 1) >> 16) {        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                             JSMSG_NEED_DIET, js_script_str);        return JS_FALSE;    }    if (cloneIndex >= *countPtr)        *countPtr = cloneIndex + 1;    reobj = ATOM_TO_OBJECT(pn->pn_atom);    JS_ASSERT(OBJ_GET_CLASS(cx, reobj) == &js_RegExpClass);    re = (JSRegExp *) JS_GetPrivate(cx, reobj);    re->cloneIndex = cloneIndex;    return JS_TRUE;}/* * Emit a bytecode and its 2-byte constant (atom) index immediate operand. * If the atomIndex requires more than 2 bytes, emit a prefix op whose 24-bit * immediate operand indexes the atom in script->atomMap. * * If op has JOF_NAME mode, emit JSOP_FINDNAME to find and push the object in * the scope chain in which the literal name was found, followed by the name * as a string.  This enables us to use the JOF_ELEM counterpart to op. * * Otherwise, if op has JOF_PROP mode, emit JSOP_LITERAL before op, to push * the atom's value key.  For JOF_PROP ops, the object being operated on has * already been pushed, and JSOP_LITERAL will push the id, leaving the stack * in the proper state for a JOF_ELEM counterpart. * * Otherwise, emit JSOP_LITOPX to push the atom index, then perform a special * dispatch on op, but getting op's atom index from the stack instead of from * an unsigned 16-bit immediate operand. */static JSBoolEmitAtomIndexOp(JSContext *cx, JSOp op, jsatomid atomIndex, JSCodeGenerator *cg){    uint32 mode;    JSOp prefixOp;    ptrdiff_t off;    jsbytecode *pc;    if (atomIndex >= JS_BIT(16)) {        mode = (js_CodeSpec[op].format & JOF_MODEMASK);        if (op != JSOP_SETNAME) {            prefixOp = ((mode != JOF_NAME && mode != JOF_PROP) ||#if JS_HAS_XML_SUPPORT                        op == JSOP_GETMETHOD ||                        op == JSOP_SETMETHOD ||#endif                        op == JSOP_SETCONST)                       ? JSOP_LITOPX                       : (mode == JOF_NAME)                       ? JSOP_FINDNAME                       : JSOP_LITERAL;            off = js_EmitN(cx, cg, prefixOp, 3);            if (off < 0)                return JS_FALSE;            pc = CG_CODE(cg, off);            SET_LITERAL_INDEX(pc, atomIndex);        }        switch (op) {          case JSOP_DECNAME:    op = JSOP_DECELEM; break;          case JSOP_DECPROP:    op = JSOP_DECELEM; break;          case JSOP_DELNAME:    op = JSOP_DELELEM; break;          case JSOP_DELPROP:    op = JSOP_DELELEM; break;          case JSOP_FORNAME:    op = JSOP_FORELEM; break;          case JSOP_FORPROP:    op = JSOP_FORELEM; break;          case JSOP_GETPROP:    op = JSOP_GETELEM; break;          case JSOP_GETXPROP:   op = JSOP_GETXELEM; break;          case JSOP_IMPORTPROP: op = JSOP_IMPORTELEM; break;          case JSOP_INCNAME:    op = JSOP_INCELEM; break;          case JSOP_INCPROP:    op = JSOP_INCELEM; break;          case JSOP_INITPROP:   op = JSOP_INITELEM; break;          case JSOP_NAME:       op = JSOP_GETELEM; break;          case JSOP_NAMEDEC:    op = JSOP_ELEMDEC; break;          case JSOP_NAMEINC:    op = JSOP_ELEMINC; break;          case JSOP_PROPDEC:    op = JSOP_ELEMDEC; break;          case JSOP_PROPINC:    op = JSOP_ELEMINC; break;          case JSOP_BINDNAME:   return JS_TRUE;          case JSOP_SETNAME:    op = JSOP_SETELEM; break;          case JSOP_SETPROP:    op = JSOP_SETELEM; break;#if JS_HAS_EXPORT_IMPORT          case JSOP_EXPORTNAME:            ReportStatementTooLarge(cx, cg);            return JS_FALSE;#endif          default:#if JS_HAS_XML_SUPPORT            JS_ASSERT(mode == 0 || op == JSOP_SETCONST ||                      op == JSOP_GETMETHOD || op == JSOP_SETMETHOD);#else            JS_ASSERT(mode == 0 || op == JSOP_SETCONST);#endif            break;        }        return js_Emit1(cx, cg, op) >= 0;    }    EMIT_UINT16_IMM_OP(op, atomIndex);    return JS_TRUE;}/* * Slight sugar for EmitAtomIndexOp, again accessing cx and cg from the macro * caller's lexical environment, and embedding a false return on error. * XXXbe hey, who checks for fun->nvars and fun->nargs overflow?! */#define EMIT_ATOM_INDEX_OP(op, atomIndex)                                     \    JS_BEGIN_MACRO                                                            \        if (!EmitAtomIndexOp(cx, op, atomIndex, cg))                          \            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;    if (op == JSOP_REGEXP && !IndexRegExpClone(cx, pn, ale, cg))        return JS_FALSE;    return EmitAtomIndexOp(cx, op, ALE_INDEX(ale), cg);}/* * This routine tries to optimize name gets and sets to stack slot loads and * stores, given the variables object and scope chain in cx's top frame, the * compile-time context in tc, and a TOK_NAME node pn.  It returns false on * error, true on success. * * The caller can inspect pn->pn_slot for a non-negative slot number to tell * whether optimization occurred, in which case BindNameToSlot also updated * pn->pn_op.  If pn->pn_slot is still -1 on return, pn->pn_op nevertheless * may have been optimized, e.g., from JSOP_NAME to JSOP_ARGUMENTS.  Whether * or not pn->pn_op was modified, if this function finds an argument or local * variable name, pn->pn_attrs will contain the property's attributes after a * successful return. * * NB: if you add more opcodes specialized from JSOP_NAME, etc., don't forget * to update the TOK_FOR (for-in) and TOK_ASSIGN (op=, e.g. +=) special cases * in js_EmitTree. */static JSBoolBindNameToSlot(JSContext *cx, JSTreeContext *tc, JSParseNode *pn,               JSBool letdecl){    JSAtom *atom;    JSStmtInfo *stmt;    jsint slot;    JSOp op;    JSStackFrame *fp;    JSObject *obj, *pobj;    JSClass *clasp;    JSBool optimizeGlobals;    JSPropertyOp getter;    uintN attrs;    JSAtomListElement *ale;    JSProperty *prop;    JSScopeProperty *sprop;    JS_ASSERT(pn->pn_type == TOK_NAME);    if (pn->pn_slot >= 0 || pn->pn_op == JSOP_ARGUMENTS)        return JS_TRUE;    /* QNAME references can never be optimized to use arg/var storage. */    if (pn->pn_op == JSOP_QNAMEPART)        return JS_TRUE;    /*     * We can't optimize if we are compiling a with statement and its body,     * or we're in a catch block whose exception variable has the same name   

⌨️ 快捷键说明

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