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); JS_ASSERT(!cx->enumerators); #ifdef JS_THREADSAFE JS_ASSERT(cx->outstandingRequests == 0); #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)); } } JS_REMOVE_LINK(&cx->link); 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); /* Unpin all common atoms before final GC. */ FinishCommonAtoms(rt); /* Clear debugging state to remove GC roots. */ for (CompartmentsIter c(rt); !c.done(); c.next()) c->clearTraps(rt->defaultFreeOp()); JS_ClearAllWatchPoints(cx); PrepareForFullGC(rt); GC(rt, GC_NORMAL, gcreason::LAST_CONTEXT); } else if (mode == DCM_FORCE_GC) { JS_ASSERT(!rt->isHeapBusy()); PrepareForFullGC(rt); GC(rt, GC_NORMAL, gcreason::DESTROY_CONTEXT); } Foreground::delete_(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] == nullptr); #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) { /* * Dump remaining type inference results while we still have a context. * This printing depends on atoms still existing. */ for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) c->types.print(cx, false); } 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); if (cx->outstandingRequests != 0) MOZ_CRASH("Attempted to destroy a context while it is in a request."); cx->roots.checkNoGCRooters(); FinishPersistentRootedChains(cx->roots); 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) { /* * Dump remaining type inference results while we still have a context. * This printing depends on atoms still existing. */ for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) PrintTypes(cx, c, false); } if (mode == DCM_FORCE_GC) { MOZ_ASSERT(!rt->isHeapBusy()); JS::PrepareForFullGC(rt); rt->gc.gc(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); }
void js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) { JSRuntime *rt = cx->runtime; JS_AbortIfWrongThread(rt); JS_ASSERT(!cx->enumerators); #ifdef JS_THREADSAFE JS_ASSERT(cx->outstandingRequests == 0); #endif if (mode != JSDCM_NEW_FAILED) { if (JSContextCallback cxCallback = rt->cxCallback) { /* * JSCONTEXT_DESTROY callback is not allowed to fail and must * return true. */ DebugOnly<JSBool> callbackStatus = cxCallback(cx, JSCONTEXT_DESTROY); JS_ASSERT(callbackStatus); } } JS_LOCK_GC(rt); JS_REMOVE_LINK(&cx->link); bool last = !rt->hasContexts(); if (last || mode == JSDCM_FORCE_GC || mode == JSDCM_MAYBE_GC) { JS_ASSERT(!rt->gcRunning); #ifdef JS_THREADSAFE rt->gcHelperThread.waitBackgroundSweepEnd(); #endif JS_UNLOCK_GC(rt); if (last) { /* * Dump remaining type inference results first. This printing * depends on atoms still existing. */ { AutoLockGC lock(rt); for (CompartmentsIter c(rt); !c.done(); c.next()) c->types.print(cx, false); } /* Unpin all common atoms before final GC. */ js_FinishCommonAtoms(cx); /* Clear debugging state to remove GC roots. */ for (CompartmentsIter c(rt); !c.done(); c.next()) c->clearTraps(cx); JS_ClearAllWatchPoints(cx); js_GC(cx, NULL, GC_NORMAL, gcreason::LAST_CONTEXT); } else if (mode == JSDCM_FORCE_GC) { js_GC(cx, NULL, GC_NORMAL, gcreason::DESTROY_CONTEXT); } else if (mode == JSDCM_MAYBE_GC) { JS_MaybeGC(cx); } JS_LOCK_GC(rt); } #ifdef JS_THREADSAFE rt->gcHelperThread.waitBackgroundSweepEnd(); #endif JS_UNLOCK_GC(rt); Foreground::delete_(cx); }