js_FinishRuntimeScriptState(cx);
js_FinishRuntimeScriptState(rt);
js_DestroyContext(JSContext *cx, JSGCMode gcmode){    JSRuntime *rt;    JSBool last;    JSArgumentFormatMap *map;    JSLocalRootStack *lrs;    JSLocalRootChunk *lrc;    rt = cx->runtime;    /* Remove cx from context list first. */    JS_LOCK_GC(rt);    JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING);    JS_REMOVE_LINK(&cx->links);    last = (rt->contextList.next == &rt->contextList);    if (last)        rt->state = JSRTS_LANDING;    JS_UNLOCK_GC(rt);    if (last) {#ifdef JS_THREADSAFE        /*         * If cx is not in a request already, begin one now so that we wait         * for any racing GC started on a not-last context to finish, before         * we plow ahead and unpin atoms.  Note that even though we begin a         * request here if necessary, we end all requests on cx below before         * forcing a final GC.  This lets any not-last context destruction         * racing in another thread try to force or maybe run the GC, but by         * that point, rt->state will not be JSRTS_UP, and that GC attempt         * will return early.         */        if (cx->requestDepth == 0)            JS_BeginRequest(cx);#endif        /* Unpin all pinned atoms before final GC. */        js_UnpinPinnedAtoms(&rt->atomState);        /* Unlock and clear GC things held by runtime pointers. */        js_FinishRuntimeNumberState(cx);        js_FinishRuntimeStringState(cx);        /* Clear debugging state to remove GC roots. */        JS_ClearAllTraps(cx);        JS_ClearAllWatchPoints(cx);    }#if JS_HAS_REGEXPS    /*     * Remove more GC roots in regExpStatics, then collect garbage.     * XXX anti-modularity alert: we rely on the call to js_RemoveRoot within     * XXX this function call to wait for any racing GC to complete, in the     * XXX case where JS_DestroyContext is called outside of a request on cx     */    js_FreeRegExpStatics(cx, &cx->regExpStatics);#endif#ifdef JS_THREADSAFE    /*     * Destroying a context implicitly calls JS_EndRequest().  Also, we must     * end our request here in case we are "last" -- in that event, another     * js_DestroyContext that was not last might be waiting in the GC for our     * request to end.  We'll let it run below, just before we do the truly     * final GC and then free atom state.     *     * At this point, cx must be inaccessible to other threads.  It's off the     * rt->contextList, and it should not be reachable via any object private     * data structure.     */    while (cx->requestDepth != 0)        JS_EndRequest(cx);#endif    if (last) {        /* Always force, so we wait for any racing GC to finish. */        js_ForceGC(cx, GC_LAST_CONTEXT);        /* Iterate until no finalizer removes a GC root or lock. */        while (rt->gcPoke)            js_GC(cx, GC_LAST_CONTEXT);        /* Try to free atom state, now that no unrooted scripts survive. */        if (rt->atomState.liveAtoms == 0)            js_FreeAtomState(cx, &rt->atomState);        /* Also free the script filename table if it exists and is empty. */        if (rt->scriptFilenameTable && rt->scriptFilenameTable->nentries == 0)            js_FinishRuntimeScriptState(cx);        /* Take the runtime down, now that it has no contexts or atoms. */        JS_LOCK_GC(rt);        rt->state = JSRTS_DOWN;        JS_NOTIFY_ALL_CONDVAR(rt->stateChange);        JS_UNLOCK_GC(rt);    } else {        if (gcmode == JS_FORCE_GC)            js_ForceGC(cx, 0);        else if (gcmode == JS_MAYBE_GC)            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);    }    /* Finally, free cx itself. */    free(cx);}