nsresult nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData) { if (!strcmp(aTopic, "xpcom-shutdown")) { nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (!obs) return NS_ERROR_FAILURE; // No need for kungFuDeathGrip here, yay observerservice! obs->RemoveObserver(this, "xpcom-shutdown"); obs->RemoveObserver(this, "cycle-collector-begin"); sGeneration = 0; return NS_OK; } NS_ASSERTION(!strcmp(aTopic, "cycle-collector-begin"), "wrong topic"); // Increase generation to effectivly unmark all current objects if (!++sGeneration) { ++sGeneration; } nsresult rv; // Iterate all toplevel windows nsCOMPtr<nsISimpleEnumerator> windowList; nsCOMPtr<nsIWindowMediator> med = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID); if (med) { rv = med->GetEnumerator(nsnull, getter_AddRefs(windowList)); NS_ENSURE_SUCCESS(rv, rv); MarkWindowList(windowList); } nsCOMPtr<nsIWindowWatcher> ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID); if (ww) { rv = ww->GetWindowEnumerator(getter_AddRefs(windowList)); NS_ENSURE_SUCCESS(rv, rv); MarkWindowList(windowList); } return NS_OK; }
nsresult nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData) { if (!strcmp(aTopic, "xpcom-shutdown")) { nsGenericElement::ClearContentUnbinder(); nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (!obs) return NS_ERROR_FAILURE; // No need for kungFuDeathGrip here, yay observerservice! obs->RemoveObserver(this, "xpcom-shutdown"); obs->RemoveObserver(this, "cycle-collector-begin"); obs->RemoveObserver(this, "cycle-collector-forget-skippable"); sGeneration = 0; return NS_OK; } NS_ASSERTION(!strcmp(aTopic, "cycle-collector-begin") || !strcmp(aTopic, "cycle-collector-forget-skippable"), "wrong topic"); // JS cleanup can be slow. Do it only if there has been a GC. bool cleanupJS = nsJSContext::CleanupsSinceLastGC() == 0 && !strcmp(aTopic, "cycle-collector-forget-skippable"); bool prepareForCC = !strcmp(aTopic, "cycle-collector-begin"); if (prepareForCC) { nsGenericElement::ClearContentUnbinder(); } // Increase generation to effectivly unmark all current objects if (!++sGeneration) { ++sGeneration; } nsresult rv; // Iterate all toplevel windows nsCOMPtr<nsISimpleEnumerator> windowList; nsCOMPtr<nsIWindowMediator> med = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID); if (med) { rv = med->GetEnumerator(nullptr, getter_AddRefs(windowList)); NS_ENSURE_SUCCESS(rv, rv); MarkWindowList(windowList, cleanupJS, prepareForCC); } nsCOMPtr<nsIWindowWatcher> ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID); if (ww) { rv = ww->GetWindowEnumerator(getter_AddRefs(windowList)); NS_ENSURE_SUCCESS(rv, rv); MarkWindowList(windowList, cleanupJS, prepareForCC); } nsCOMPtr<nsIAppShellService> appShell = do_GetService(NS_APPSHELLSERVICE_CONTRACTID); if (appShell) { nsCOMPtr<nsIXULWindow> hw; appShell->GetHiddenWindow(getter_AddRefs(hw)); if (hw) { nsCOMPtr<nsIDocShell> shell; hw->GetDocShell(getter_AddRefs(shell)); nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell); MarkDocShell(shellTreeNode, cleanupJS, prepareForCC); } } #ifdef MOZ_XUL nsXULPrototypeCache* xulCache = nsXULPrototypeCache::GetInstance(); if (xulCache) { xulCache->MarkInCCGeneration(sGeneration); } #endif static bool previousWasJSCleanup = false; if (cleanupJS) { nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(sGeneration); MarkMessageManagers(); nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); static_cast<nsObserverService *>(obs.get())->UnmarkGrayStrongObservers(); previousWasJSCleanup = true; } else if (previousWasJSCleanup) { previousWasJSCleanup = false; if (!prepareForCC) { xpc_UnmarkSkippableJSHolders(); } } return NS_OK; }