void js::DestroyContext(JSContext *cx, DestroyContextMode mode) { JSRuntime *rt = cx->runtime; JS_AbortIfWrongThread(rt); #ifdef JS_THREADSAFE if (cx->outstandingRequests != 0) MOZ_CRASH(); #endif if (mode != DCM_NEW_FAILED) { if (JSContextCallback cxCallback = rt->cxCallback) { /* * JSCONTEXT_DESTROY callback is not allowed to fail and must * return true. */ JS_ALWAYS_TRUE(cxCallback(cx, JSCONTEXT_DESTROY)); } } cx->remove(); bool last = !rt->hasContexts(); if (last) { JS_ASSERT(!rt->isHeapBusy()); /* * Dump remaining type inference results first. This printing * depends on atoms still existing. */ for (CompartmentsIter c(rt); !c.done(); c.next()) c->types.print(cx, false); /* Off thread ion compilations depend on atoms still existing. */ for (CompartmentsIter c(rt); !c.done(); c.next()) CancelOffThreadIonCompile(c, NULL); /* Unpin all common names before final GC. */ FinishCommonNames(rt); /* Clear debugging state to remove GC roots. */ for (CompartmentsIter c(rt); !c.done(); c.next()) c->clearTraps(rt->defaultFreeOp()); JS_ClearAllWatchPoints(cx); /* Clear the statics table to remove GC roots. */ rt->staticStrings.finish(); rt->finishSelfHosting(); JS::PrepareForFullGC(rt); GC(rt, GC_NORMAL, JS::gcreason::LAST_CONTEXT); } else if (mode == DCM_FORCE_GC) { JS_ASSERT(!rt->isHeapBusy()); JS::PrepareForFullGC(rt); GC(rt, GC_NORMAL, JS::gcreason::DESTROY_CONTEXT); } js_delete_poison(cx); }
void js::DestroyContext(JSContext *cx, DestroyContextMode mode) { JSRuntime *rt = cx->runtime(); JS_AbortIfWrongThread(rt); #ifdef JS_THREADSAFE if (cx->outstandingRequests != 0) MOZ_CRASH(); #endif #if (defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)) && defined(DEBUG) for (int i = 0; i < THING_ROOT_LIMIT; ++i) JS_ASSERT(cx->thingGCRooters[i] == NULL); #endif if (mode != DCM_NEW_FAILED) { if (JSContextCallback cxCallback = rt->cxCallback) { /* * JSCONTEXT_DESTROY callback is not allowed to fail and must * return true. */ JS_ALWAYS_TRUE(cxCallback(cx, JSCONTEXT_DESTROY, rt->cxCallbackData)); } } cx->remove(); bool last = !rt->hasContexts(); if (last) { JS_ASSERT(!rt->isHeapBusy()); /* * Dump remaining type inference results first. This printing * depends on atoms still existing. */ for (CompartmentsIter c(rt); !c.done(); c.next()) c->types.print(cx, false); /* Off thread compilation and parsing depend on atoms still existing. */ for (CompartmentsIter c(rt); !c.done(); c.next()) CancelOffThreadIonCompile(c, NULL); WaitForOffThreadParsingToFinish(rt); #ifdef JS_WORKER_THREADS if (rt->workerThreadState) rt->workerThreadState->cleanup(rt); #endif /* Unpin all common names before final GC. */ FinishCommonNames(rt); /* Clear debugging state to remove GC roots. */ for (CompartmentsIter c(rt); !c.done(); c.next()) c->clearTraps(rt->defaultFreeOp()); JS_ClearAllWatchPoints(cx); /* Clear the statics table to remove GC roots. */ rt->staticStrings.finish(); JS::PrepareForFullGC(rt); GC(rt, GC_NORMAL, JS::gcreason::LAST_CONTEXT); /* * Clear the self-hosted global and delete self-hosted classes *after* * GC, as finalizers for objects check for clasp->finalize during GC. */ rt->finishSelfHosting(); } else if (mode == DCM_FORCE_GC) { JS_ASSERT(!rt->isHeapBusy()); JS::PrepareForFullGC(rt); GC(rt, GC_NORMAL, JS::gcreason::DESTROY_CONTEXT); } js_delete_poison(cx); }