if (cx->resolving) { JS_DHashTableDestroy(cx->resolving); cx->resolving = NULL;
if (cx->resolvingTable) { JS_DHashTableDestroy(cx->resolvingTable); cx->resolvingTable = NULL;
js_DestroyContext(JSContext *cx, JSGCMode gcmode){    JSRuntime *rt;    JSBool last;    JSArgumentFormatMap *map;    rt = cx->runtime;    /* Remove cx from context list first. */    JS_LOCK_RUNTIME(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_RUNTIME(rt);    if (last) {        /* 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);        /* 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);        /* Take the runtime down, now that it has no contexts or atoms. */        JS_LOCK_RUNTIME(rt);        rt->state = JSRTS_DOWN;        JS_NOTIFY_ALL_CONDVAR(rt->stateChange);        JS_UNLOCK_RUNTIME(rt);    } else {        if (gcmode == JS_FORCE_GC)            js_ForceGC(cx);        else if (gcmode == JS_MAYBE_GC)            JS_MaybeGC(cx);    }    /* Free the stuff hanging off of cx. */    JS_FinishArenaPool(&cx->stackPool);    JS_FinishArenaPool(&cx->codePool);    JS_FinishArenaPool(&cx->notePool);    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->resolving) {        JS_DHashTableDestroy(cx->resolving);        cx->resolving = NULL;    }    /* Finally, free cx itself. */    free(cx);}