jscntxt.c
来自「java script test programing source code」· C语言 代码 · 共 1,230 行 · 第 1/3 页
C
1,230 行
JS_MaybeGC(cx); } /* Free the stuff hanging off of cx. */ JS_FinishArenaPool(&cx->stackPool); JS_FinishArenaPool(&cx->tempPool); if (cx->lastMessage) free(cx->lastMessage); /* Remove any argument formatters. */ map = cx->argumentFormatMap; while (map) { JSArgumentFormatMap *temp = map; map = map->next; JS_free(cx, temp); } /* Destroy the resolve recursion damper. */ if (cx->resolvingTable) { JS_DHashTableDestroy(cx->resolvingTable); cx->resolvingTable = NULL; } lrs = cx->localRootStack; if (lrs) { while ((lrc = lrs->topChunk) != &lrs->firstChunk) { lrs->topChunk = lrc->down; JS_free(cx, lrc); } JS_free(cx, lrs); }#ifdef JS_THREADSAFE js_ClearContextThread(cx);#endif /* Finally, free cx itself. */ free(cx);}JSBooljs_ValidContextPointer(JSRuntime *rt, JSContext *cx){ JSCList *cl; for (cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next) { if (cl == &cx->links) return JS_TRUE; } JS_RUNTIME_METER(rt, deadContexts); return JS_FALSE;}JSContext *js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp){ JSContext *cx = *iterp; if (unlocked) JS_LOCK_GC(rt); if (!cx) cx = (JSContext *)&rt->contextList; cx = (JSContext *)cx->links.next; if (&cx->links == &rt->contextList) cx = NULL; *iterp = cx; if (unlocked) JS_UNLOCK_GC(rt); return cx;}JS_STATIC_DLL_CALLBACK(const void *)resolving_GetKey(JSDHashTable *table, JSDHashEntryHdr *hdr){ JSResolvingEntry *entry = (JSResolvingEntry *)hdr; return &entry->key;}JS_STATIC_DLL_CALLBACK(JSDHashNumber)resolving_HashKey(JSDHashTable *table, const void *ptr){ const JSResolvingKey *key = (const JSResolvingKey *)ptr; return ((JSDHashNumber)JS_PTR_TO_UINT32(key->obj) >> JSVAL_TAGBITS) ^ key->id;}JS_PUBLIC_API(JSBool)resolving_MatchEntry(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *ptr){ const JSResolvingEntry *entry = (const JSResolvingEntry *)hdr; const JSResolvingKey *key = (const JSResolvingKey *)ptr; return entry->key.obj == key->obj && entry->key.id == key->id;}static const JSDHashTableOps resolving_dhash_ops = { JS_DHashAllocTable, JS_DHashFreeTable, resolving_GetKey, resolving_HashKey, resolving_MatchEntry, JS_DHashMoveEntryStub, JS_DHashClearEntryStub, JS_DHashFinalizeStub, NULL};JSBooljs_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag, JSResolvingEntry **entryp){ JSDHashTable *table; JSResolvingEntry *entry; table = cx->resolvingTable; if (!table) { table = JS_NewDHashTable(&resolving_dhash_ops, NULL, sizeof(JSResolvingEntry), JS_DHASH_MIN_SIZE); if (!table) goto outofmem; cx->resolvingTable = table; } entry = (JSResolvingEntry *) JS_DHashTableOperate(table, key, JS_DHASH_ADD); if (!entry) goto outofmem; if (entry->flags & flag) { /* An entry for (key, flag) exists already -- dampen recursion. */ entry = NULL; } else { /* Fill in key if we were the first to add entry, then set flag. */ if (!entry->key.obj) entry->key = *key; entry->flags |= flag; } *entryp = entry; return JS_TRUE;outofmem: JS_ReportOutOfMemory(cx); return JS_FALSE;}voidjs_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag, JSResolvingEntry *entry, uint32 generation){ JSDHashTable *table; /* * Clear flag from entry->flags and return early if other flags remain. * We must take care to re-lookup entry if the table has changed since * it was found by js_StartResolving. */ table = cx->resolvingTable; if (!entry || table->generation != generation) { entry = (JSResolvingEntry *) JS_DHashTableOperate(table, key, JS_DHASH_LOOKUP); } JS_ASSERT(JS_DHASH_ENTRY_IS_BUSY(&entry->hdr)); entry->flags &= ~flag; if (entry->flags) return; /* * Do a raw remove only if fewer entries were removed than would cause * alpha to be less than .5 (alpha is at most .75). Otherwise, we just * call JS_DHashTableOperate to re-lookup the key and remove its entry, * compressing or shrinking the table as needed. */ if (table->removedCount < JS_DHASH_TABLE_SIZE(table) >> 2) JS_DHashTableRawRemove(table, &entry->hdr); else JS_DHashTableOperate(table, key, JS_DHASH_REMOVE);}JSBooljs_EnterLocalRootScope(JSContext *cx){ JSLocalRootStack *lrs; int mark; lrs = cx->localRootStack; if (!lrs) { lrs = (JSLocalRootStack *) JS_malloc(cx, sizeof *lrs); if (!lrs) return JS_FALSE; lrs->scopeMark = JSLRS_NULL_MARK; lrs->rootCount = 0; lrs->topChunk = &lrs->firstChunk; lrs->firstChunk.down = NULL; cx->localRootStack = lrs; } /* Push lrs->scopeMark to save it for restore when leaving. */ mark = js_PushLocalRoot(cx, lrs, INT_TO_JSVAL(lrs->scopeMark)); if (mark < 0) return JS_FALSE; lrs->scopeMark = (uint32) mark; return JS_TRUE;}voidjs_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval){ JSLocalRootStack *lrs; uint32 mark, m, n; JSLocalRootChunk *lrc; /* Defend against buggy native callers. */ lrs = cx->localRootStack; JS_ASSERT(lrs && lrs->rootCount != 0); if (!lrs || lrs->rootCount == 0) return; mark = lrs->scopeMark; JS_ASSERT(mark != JSLRS_NULL_MARK); if (mark == JSLRS_NULL_MARK) return; /* Free any chunks being popped by this leave operation. */ m = mark >> JSLRS_CHUNK_SHIFT; n = (lrs->rootCount - 1) >> JSLRS_CHUNK_SHIFT; while (n > m) { lrc = lrs->topChunk; JS_ASSERT(lrc != &lrs->firstChunk); lrs->topChunk = lrc->down; JS_free(cx, lrc); --n; } /* * Pop the scope, restoring lrs->scopeMark. If rval is a GC-thing, push * it on the caller's scope, or store it in lastInternalResult if we are * leaving the outermost scope. We don't need to allocate a new lrc * because we can overwrite the old mark's slot with rval. */ lrc = lrs->topChunk; m = mark & JSLRS_CHUNK_MASK; lrs->scopeMark = (uint32) JSVAL_TO_INT(lrc->roots[m]); if (JSVAL_IS_GCTHING(rval) && !JSVAL_IS_NULL(rval)) { if (mark == 0) { cx->weakRoots.lastInternalResult = rval; } else { /* * Increment m to avoid the "else if (m == 0)" case below. If * rval is not a GC-thing, that case would take care of freeing * any chunk that contained only the old mark. Since rval *is* * a GC-thing here, we want to reuse that old mark's slot. */ lrc->roots[m++] = rval; ++mark; } } lrs->rootCount = (uint32) mark; /* * Free the stack eagerly, risking malloc churn. The alternative would * require an lrs->entryCount member, maintained by Enter and Leave, and * tested by the GC in addition to the cx->localRootStack non-null test. * * That approach would risk hoarding 264 bytes (net) per context. Right * now it seems better to give fresh (dirty in CPU write-back cache, and * the data is no longer needed) memory back to the malloc heap. */ if (mark == 0) { cx->localRootStack = NULL; JS_free(cx, lrs); } else if (m == 0) { lrs->topChunk = lrc->down; JS_free(cx, lrc); }}voidjs_ForgetLocalRoot(JSContext *cx, jsval v){ JSLocalRootStack *lrs; uint32 i, j, m, n, mark; JSLocalRootChunk *lrc, *lrc2; jsval top; lrs = cx->localRootStack; JS_ASSERT(lrs && lrs->rootCount); if (!lrs || lrs->rootCount == 0) return; /* Prepare to pop the top-most value from the stack. */ n = lrs->rootCount - 1; m = n & JSLRS_CHUNK_MASK; lrc = lrs->topChunk; top = lrc->roots[m]; /* Be paranoid about calls on an empty scope. */ mark = lrs->scopeMark; JS_ASSERT(mark < n); if (mark >= n) return; /* If v was not the last root pushed in the top scope, find it. */ if (top != v) { /* Search downward in case v was recently pushed. */ i = n; j = m; lrc2 = lrc; while (--i > mark) { if (j == 0) lrc2 = lrc2->down; j = i & JSLRS_CHUNK_MASK; if (lrc2->roots[j] == v) break; } /* If we didn't find v in this scope, assert and bail out. */ JS_ASSERT(i != mark); if (i == mark) return; /* Swap top and v so common tail code can pop v. */ lrc2->roots[j] = top; } /* Pop the last value from the stack. */ lrc->roots[m] = JSVAL_NULL; lrs->rootCount = n; if (m == 0) { JS_ASSERT(n != 0); JS_ASSERT(lrc != &lrs->firstChunk); lrs->topChunk = lrc->down; JS_free(cx, lrc); }}intjs_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v){ uint32 n, m; JSLocalRootChunk *lrc; n = lrs->rootCount; m = n & JSLRS_CHUNK_MASK; if (n == 0 || m != 0) { /* * At start of first chunk, or not at start of a non-first top chunk. * Check for lrs->rootCount overflow. */ if ((uint32)(n + 1) == 0) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_MANY_LOCAL_ROOTS); return -1; } lrc = lrs->topChunk; JS_ASSERT(n != 0 || lrc == &lrs->firstChunk); } else { /* * After lrs->firstChunk, trying to index at a power-of-two chunk * boundary: need a new chunk. */ lrc = (JSLocalRootChunk *) JS_malloc(cx, sizeof *lrc); if (!lrc) return -1; lrc->down = lrs->topChunk; lrs->topChunk = lrc; } lrs->rootCount = n + 1; lrc->roots[m] = v; return (int) n;}voidjs_MarkLocalRoots(JSContext *cx, JSLocalRootStack *lrs){ uint32 n, m, mark; JSLocalRootChunk *lrc; n = lrs->rootCount; if (n == 0) return; mark = lrs->scopeMark; lrc = lrs->topChunk; do { while (--n > mark) {#ifdef GC_MARK_DEBUG char name[22]; JS_snprintf(name, sizeof name, "<local root %u>", n);#endif m = n & JSLRS_CHUNK_MASK; JS_ASSERT(JSVAL_IS_GCTHING(lrc->roots[m])); GC_MARK(cx, JSVAL_TO_GCTHING(lrc->roots[m]), name); if (m == 0) lrc = lrc->down; } m = n & JSLRS_CHUNK_MASK; mark = JSVAL_TO_INT(lrc->roots[m]); if (m == 0) lrc = lrc->down; } while (n != 0); JS_ASSERT(!lrc);}static voidReportError(JSContext *cx, const char *message, JSErrorReport *reportp)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?