/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
staticbool sInited = 0; // The initial value of sGeneration should not be the same as the // value it is given at xpcom-shutdown, because this will make any GCs // before we first CC benignly violate the black-gray invariant, due // to dom::TraceBlackJS().
uint32_t nsCCUncollectableMarker::sGeneration = 1; #include"nsXULPrototypeCache.h"
nsCOMPtr<nsIObserver> marker = new nsCCUncollectableMarker;
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (!obs) return NS_ERROR_FAILURE;
nsresult rv;
// This makes the observer service hold an owning reference to the marker
rv = obs->AddObserver(marker, "xpcom-shutdown", false);
NS_ENSURE_SUCCESS(rv, rv);
if (nonLeafMM) {
MarkChildMessageManagers(nonLeafMM); continue;
}
tabMM->MarkForCC();
// XXX hack warning, but works, since we know that // callback is frameloader.
mozilla::dom::ipc::MessageManagerCallback* cb = tabMM->GetCallback(); if (cb) {
nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
InProcessBrowserChildMessageManager* et =
fl->GetBrowserChildMessageManager(); if (!et) { continue;
}
et->MarkForCC();
EventListenerManager* elm = et->GetExistingListenerManager(); if (elm) {
elm->MarkForCC();
}
}
}
}
staticvoid MarkMessageManagers() { if (nsFrameMessageManager::GetChildProcessManager()) { // ContentProcessMessageManager's MarkForCC also marks ChildProcessManager.
ContentProcessMessageManager* pg = ContentProcessMessageManager::Get(); if (pg) {
pg->MarkForCC();
}
}
// The global message manager only exists in the root process. if (!XRE_IsParentProcess()) { return;
}
RefPtr<ChromeMessageBroadcaster> strongGlobalMM =
nsFrameMessageManager::GetGlobalMessageManager(); if (!strongGlobalMM) { return;
}
ChromeMessageBroadcaster* globalMM = strongGlobalMM;
strongGlobalMM = nullptr;
MarkChildMessageManagers(globalMM);
if (nsFrameMessageManager::sParentProcessManager) {
nsFrameMessageManager::sParentProcessManager->MarkForCC();
uint32_t childCount =
nsFrameMessageManager::sParentProcessManager->ChildCount(); for (uint32_t i = 0; i < childCount; ++i) {
RefPtr<MessageListenerManager> childMM =
nsFrameMessageManager::sParentProcessManager->GetChildAt(i); if (!childMM) { continue;
}
MessageListenerManager* child = childMM;
childMM = nullptr;
child->MarkForCC();
}
} if (nsFrameMessageManager::sSameProcessParentManager) {
nsFrameMessageManager::sSameProcessParentManager->MarkForCC();
}
}
RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(rootDocShell); if (browserChild) {
RefPtr<BrowserChildMessageManager> mm =
browserChild->GetMessageManager(); if (mm) { // MarkForCC ends up calling UnmarkGray on message listeners, which // TraceBlackJS can't do yet.
mm->MarkForCC();
}
}
}
}
}
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");
// JS cleanup can be slow. Do it only if this is the first forget-skippable // after a GC. constbool cleanupJS = nsJSContext::HasHadCleanupSinceLastGC() &&
!strcmp(aTopic, "cycle-collector-forget-skippable");
constbool prepareForCC = !strcmp(aTopic, "cycle-collector-begin"); if (prepareForCC) {
Element::ClearContentUnbinder();
}
// Increase generation to effectively unmark all current objects if (!++sGeneration) {
++sGeneration;
}
// 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);
if (cleanupJS) { // After a GC we start clean up phases from the beginning, // but we don't want to do the additional clean up phases here // since we have done already plenty of gray unmarking while going through // frame message managers and docshells.
sFSState = eInitial; return NS_OK;
} else {
++sFSState;
}
switch (sFSState) { case eUnmarkJSEventListeners: {
nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(); break;
} case eUnmarkMessageManagers: {
MarkMessageManagers(); break;
} case eUnmarkStrongObservers: {
nsCOMPtr<nsIObserverService> obs =
mozilla::services::GetObserverService(); static_cast<nsObserverService*>(obs.get())->UnmarkGrayStrongObservers(); break;
} case eUnmarkJSHolders: {
xpc_UnmarkSkippableJSHolders(); break;
} default: { break;
}
}
return NS_OK;
}
void mozilla::dom::TraceBlackJS(JSTracer* aTrc) { if (!nsCCUncollectableMarker::sGeneration) { return;
}
if (ContentProcessMessageManager::WasCreated() &&
nsFrameMessageManager::GetChildProcessManager()) { auto* pg = ContentProcessMessageManager::Get(); if (pg) {
mozilla::TraceScriptHolder(ToSupports(pg), aTrc);
}
}
// Mark globals of active windows black.
nsGlobalWindowOuter::OuterWindowByIdTable* windowsById =
nsGlobalWindowOuter::GetWindowsTable(); if (windowsById) { for (nsGlobalWindowOuter* window : windowsById->Values()) { if (!window->IsCleanedUp()) {
nsGlobalWindowInner* inner = nullptr; for (PRCList* win = PR_LIST_HEAD(window); win != window;
win = PR_NEXT_LINK(inner)) {
inner = static_cast<nsGlobalWindowInner*>(win); if (inner->IsCurrentInnerWindow() ||
(inner->GetExtantDoc() &&
inner->GetExtantDoc()->GetBFCacheEntry())) {
inner->TraceGlobalJSObject(aTrc);
EventListenerManager* elm = inner->GetExistingListenerManager(); if (elm) {
elm->TraceListeners(aTrc);
}
CustomElementRegistry* cer = inner->GetExistingCustomElements(); if (cer) {
cer->TraceDefinitions(aTrc);
}
}
}
if (window->IsRootOuterWindow()) { // In child process trace all the BrowserChildMessageManagers. // Since there is one root outer window per // BrowserChildMessageManager, we need to look for only those windows, // not all.
nsIDocShell* ds = window->GetDocShell(); if (ds) {
nsCOMPtr<nsIBrowserChild> browserChild = ds->GetBrowserChild(); if (browserChild) {
RefPtr<ContentFrameMessageManager> mm;
browserChild->GetMessageManager(getter_AddRefs(mm)); if (mm) {
nsCOMPtr<nsISupports> browserChildAsSupports =
do_QueryInterface(browserChild);
mozilla::TraceScriptHolder(browserChildAsSupports, aTrc);
EventListenerManager* elm = mm->GetExistingListenerManager(); if (elm) {
elm->TraceListeners(aTrc);
} // As of now there isn't an easy way to trace message listeners.
}
}
}
}
}
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.