jsscript.c

来自「java script test programing source code」· C语言 代码 · 共 1,718 行 · 第 1/4 页

C
1,718
字号
    sfe->mark = JS_TRUE;    return HT_ENUMERATE_NEXT;}voidjs_MarkScriptFilenames(JSRuntime *rt, JSBool keepAtoms){    JSCList *head, *link;    ScriptFilenamePrefix *sfp;    if (!rt->scriptFilenameTable)        return;    if (keepAtoms) {        JS_HashTableEnumerateEntries(rt->scriptFilenameTable,                                     js_script_filename_marker,                                     rt);    }    for (head = &rt->scriptFilenamePrefixes, link = head->next;         link != head;         link = link->next) {        sfp = (ScriptFilenamePrefix *) link;        js_MarkScriptFilename(sfp->name);    }}JS_STATIC_DLL_CALLBACK(intN)js_script_filename_sweeper(JSHashEntry *he, intN i, void *arg){    ScriptFilenameEntry *sfe = (ScriptFilenameEntry *) he;    if (!sfe->mark)        return HT_ENUMERATE_REMOVE;    sfe->mark = JS_FALSE;    return HT_ENUMERATE_NEXT;}voidjs_SweepScriptFilenames(JSRuntime *rt){    if (!rt->scriptFilenameTable)        return;    JS_HashTableEnumerateEntries(rt->scriptFilenameTable,                                 js_script_filename_sweeper,                                 rt);#ifdef DEBUG_notme#ifdef DEBUG_SFTBL    printf("script filename table savings so far: %u\n", sftbl_savings);#endif#endif}JSScript *js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 ntrynotes){    JSScript *script;    /* Round up source note count to align script->trynotes for its type. */    if (ntrynotes)        nsrcnotes += JSTRYNOTE_ALIGNMASK;    script = (JSScript *) JS_malloc(cx,                                    sizeof(JSScript) +                                    length * sizeof(jsbytecode) +                                    nsrcnotes * sizeof(jssrcnote) +                                    ntrynotes * sizeof(JSTryNote));    if (!script)        return NULL;    memset(script, 0, sizeof(JSScript));    script->code = script->main = (jsbytecode *)(script + 1);    script->length = length;    script->version = cx->version;    if (ntrynotes) {        script->trynotes = (JSTryNote *)                           ((jsword)(SCRIPT_NOTES(script) + nsrcnotes) &                            ~(jsword)JSTRYNOTE_ALIGNMASK);        memset(script->trynotes, 0, ntrynotes * sizeof(JSTryNote));    }    return script;}JS_FRIEND_API(JSScript *)js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg, JSFunction *fun){    uint32 mainLength, prologLength, nsrcnotes, ntrynotes;    JSScript *script;    const char *filename;    mainLength = CG_OFFSET(cg);    prologLength = CG_PROLOG_OFFSET(cg);    CG_COUNT_FINAL_SRCNOTES(cg, nsrcnotes);    CG_COUNT_FINAL_TRYNOTES(cg, ntrynotes);    script = js_NewScript(cx, prologLength + mainLength, nsrcnotes, ntrynotes);    if (!script)        return NULL;    /* Now that we have script, error control flow must go to label bad. */    script->main += prologLength;    memcpy(script->code, CG_PROLOG_BASE(cg), prologLength * sizeof(jsbytecode));    memcpy(script->main, CG_BASE(cg), mainLength * sizeof(jsbytecode));    script->numGlobalVars = cg->treeContext.numGlobalVars;    if (!js_InitAtomMap(cx, &script->atomMap, &cg->atomList))        goto bad;    filename = cg->filename;    if (filename) {        script->filename = js_SaveScriptFilename(cx, filename);        if (!script->filename)            goto bad;    }    script->lineno = cg->firstLine;    script->depth = cg->maxStackDepth;    if (cg->principals) {        script->principals = cg->principals;        JSPRINCIPALS_HOLD(cx, script->principals);    }    if (!js_FinishTakingSrcNotes(cx, cg, SCRIPT_NOTES(script)))        goto bad;    if (script->trynotes)        js_FinishTakingTryNotes(cx, cg, script->trynotes);    /*     * We initialize fun->u.script to be the script constructed above     * so that the debugger has a valid FUN_SCRIPT(fun).     */    if (fun) {        JS_ASSERT(FUN_INTERPRETED(fun) && !FUN_SCRIPT(fun));        fun->u.i.script = script;        if (cg->treeContext.flags & TCF_FUN_HEAVYWEIGHT)            fun->flags |= JSFUN_HEAVYWEIGHT;    }    /* Tell the debugger about this compiled script. */    js_CallNewScriptHook(cx, script, fun);    return script;bad:    js_DestroyScript(cx, script);    return NULL;}JS_FRIEND_API(void)js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun){    JSRuntime *rt;    JSNewScriptHook hook;    rt = cx->runtime;    hook = rt->newScriptHook;    if (hook) {        JS_KEEP_ATOMS(rt);        hook(cx, script->filename, script->lineno, script, fun,             rt->newScriptHookData);        JS_UNKEEP_ATOMS(rt);    }}JS_FRIEND_API(void)js_CallDestroyScriptHook(JSContext *cx, JSScript *script){    JSRuntime *rt;    JSDestroyScriptHook hook;    rt = cx->runtime;    hook = rt->destroyScriptHook;    if (hook)        hook(cx, script, rt->destroyScriptHookData);}voidjs_DestroyScript(JSContext *cx, JSScript *script){    js_CallDestroyScriptHook(cx, script);    JS_ClearScriptTraps(cx, script);    js_FreeAtomMap(cx, &script->atomMap);    if (script->principals)        JSPRINCIPALS_DROP(cx, script->principals);    if (JS_GSN_CACHE(cx).script == script)        JS_CLEAR_GSN_CACHE(cx);    JS_free(cx, script);}voidjs_MarkScript(JSContext *cx, JSScript *script){    JSAtomMap *map;    uintN i, length;    JSAtom **vector;    map = &script->atomMap;    length = map->length;    vector = map->vector;    for (i = 0; i < length; i++)        GC_MARK_ATOM(cx, vector[i]);    if (script->filename)        js_MarkScriptFilename(script->filename);}typedef struct GSNCacheEntry {    JSDHashEntryHdr     hdr;    jsbytecode          *pc;    jssrcnote           *sn;} GSNCacheEntry;#define GSN_CACHE_THRESHOLD     100jssrcnote *js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc){    ptrdiff_t target, offset;    GSNCacheEntry *entry;    jssrcnote *sn, *result;    uintN nsrcnotes;    target = PTRDIFF(pc, script->code, jsbytecode);    if ((uint32)target >= script->length)        return NULL;    if (JS_GSN_CACHE(cx).script == script) {        JS_METER_GSN_CACHE(cx, hits);        entry = (GSNCacheEntry *)                JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,                                     JS_DHASH_LOOKUP);        return entry->sn;    }    JS_METER_GSN_CACHE(cx, misses);    offset = 0;    for (sn = SCRIPT_NOTES(script); ; sn = SN_NEXT(sn)) {        if (SN_IS_TERMINATOR(sn)) {            result = NULL;            break;        }        offset += SN_DELTA(sn);        if (offset == target && SN_IS_GETTABLE(sn)) {            result = sn;            break;        }    }    if (JS_GSN_CACHE(cx).script != script &&        script->length >= GSN_CACHE_THRESHOLD) {        JS_CLEAR_GSN_CACHE(cx);        nsrcnotes = 0;        for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn);             sn = SN_NEXT(sn)) {            if (SN_IS_GETTABLE(sn))                ++nsrcnotes;        }        if (!JS_DHashTableInit(&JS_GSN_CACHE(cx).table, JS_DHashGetStubOps(),                               NULL, sizeof(GSNCacheEntry), nsrcnotes)) {            JS_GSN_CACHE(cx).table.ops = NULL;        } else {            pc = script->code;            for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn);                 sn = SN_NEXT(sn)) {                pc += SN_DELTA(sn);                if (SN_IS_GETTABLE(sn)) {                    entry = (GSNCacheEntry *)                            JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,                                                 JS_DHASH_ADD);                    entry->pc = pc;                    entry->sn = sn;                }            }            JS_GSN_CACHE(cx).script = script;            JS_METER_GSN_CACHE(cx, fills);        }    }    return result;}uintNjs_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc){    JSAtom *atom;    JSFunction *fun;    uintN lineno;    ptrdiff_t offset, target;    jssrcnote *sn;    JSSrcNoteType type;    /* Cope with JSStackFrame.pc value prior to entering js_Interpret. */    if (!pc)        return 0;    /*     * Special case: function definition needs no line number note because     * the function's script contains its starting line number.     */    if (*pc == JSOP_DEFFUN ||        (*pc == JSOP_LITOPX && pc[1 + LITERAL_INDEX_LEN] == JSOP_DEFFUN)) {        atom = js_GetAtom(cx, &script->atomMap,                          (*pc == JSOP_DEFFUN)                          ? GET_ATOM_INDEX(pc)                          : GET_LITERAL_INDEX(pc));        fun = (JSFunction *) JS_GetPrivate(cx, ATOM_TO_OBJECT(atom));        JS_ASSERT(FUN_INTERPRETED(fun));        return fun->u.i.script->lineno;    }    /*     * General case: walk through source notes accumulating their deltas,     * keeping track of line-number notes, until we pass the note for pc's     * offset within script->code.     */    lineno = script->lineno;    offset = 0;    target = PTRDIFF(pc, script->code, jsbytecode);    for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {        offset += SN_DELTA(sn);        type = (JSSrcNoteType) SN_TYPE(sn);        if (type == SRC_SETLINE) {            if (offset <= target)                lineno = (uintN) js_GetSrcNoteOffset(sn, 0);        } else if (type == SRC_NEWLINE) {            if (offset <= target)                lineno++;        }        if (offset > target)            break;    }    return lineno;}/* The line number limit is the same as the jssrcnote offset limit. */#define SN_LINE_LIMIT   (SN_3BYTE_OFFSET_FLAG << 16)jsbytecode *js_LineNumberToPC(JSScript *script, uintN target){    ptrdiff_t offset, best;    uintN lineno, bestdiff, diff;    jssrcnote *sn;    JSSrcNoteType type;    offset = 0;    best = -1;    lineno = script->lineno;    bestdiff = SN_LINE_LIMIT;    for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {        if (lineno == target)            goto out;        if (lineno > target) {            diff = lineno - target;            if (diff < bestdiff) {                bestdiff = diff;                best = offset;            }        }        offset += SN_DELTA(sn);        type = (JSSrcNoteType) SN_TYPE(sn);        if (type == SRC_SETLINE) {            lineno = (uintN) js_GetSrcNoteOffset(sn, 0);        } else if (type == SRC_NEWLINE) {            lineno++;        }    }    if (best >= 0)        offset = best;out:    return script->code + offset;}JS_FRIEND_API(uintN)js_GetScriptLineExtent(JSScript *script){    uintN lineno;    jssrcnote *sn;    JSSrcNoteType type;    lineno = script->lineno;    for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {        type = (JSSrcNoteType) SN_TYPE(sn);        if (type == SRC_SETLINE) {            lineno = (uintN) js_GetSrcNoteOffset(sn, 0);        } else if (type == SRC_NEWLINE) {            lineno++;        }    }    return 1 + lineno - script->lineno;}#if JS_HAS_GENERATORSjsbytecode *js_FindFinallyHandler(JSScript *script, jsbytecode *pc){    JSTryNote *tn;    ptrdiff_t off;    JSOp op2;    tn = script->trynotes;    if (!tn)        return NULL;    off = pc - script->main;    if (off < 0)        return NULL;    JS_ASSERT(tn->catchStart != 0);    do {        if ((jsuword)(off - tn->start) < (jsuword)tn->length) {            /*             * We have a handler: is it the finally one, or a catch handler?             *             * Catch bytecode begins with:   JSOP_SETSP JSOP_ENTERBLOCK             * Finally bytecode begins with: JSOP_SETSP JSOP_(GOSUB|EXCEPTION)             */            pc = script->main + tn->catchStart;            JS_ASSERT(*pc == JSOP_SETSP);            op2 = pc[JSOP_SETSP_LENGTH];            if (op2 != JSOP_ENTERBLOCK) {                JS_ASSERT(op2 == JSOP_GOSUB || op2 == JSOP_EXCEPTION);                return pc;            }        }    } while ((++tn)->catchStart != 0);    return NULL;}#endif

⌨️ 快捷键说明

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