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 + -
显示快捷键?