Bug 966762 - Add chrome JS function to unlink ghost windows. r=smaug

This commit is contained in:
Andrew McCreight 2014-02-19 13:27:15 -08:00
parent fbecfce6d2
commit 558195773a
6 changed files with 83 additions and 1 deletions

View File

@ -1809,6 +1809,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
#ifdef DEBUG
void
nsGlobalWindow::RiskyUnlink()
{
NS_CYCLE_COLLECTION_INNERNAME.Unlink(this);
}
#endif
struct TraceData
{
const TraceCallbacks& callbacks;

View File

@ -604,6 +604,12 @@ public:
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsGlobalWindow,
nsIDOMEventTarget)
#ifdef DEBUG
// Call Unlink on this window. This may cause bad things to happen, so use
// with caution.
void RiskyUnlink();
#endif
virtual NS_HIDDEN_(JSObject*)
GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey);

View File

@ -836,3 +836,45 @@ nsWindowMemoryReporter::GhostWindowsReporter::DistinguishedAmount()
return ghostWindows.Count();
}
#ifdef DEBUG
static PLDHashOperator
UnlinkGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void *)
{
nsGlobalWindow::WindowByIdTable* windowsById =
nsGlobalWindow::GetWindowsTable();
if (!windowsById) {
return PL_DHASH_NEXT;
}
nsRefPtr<nsGlobalWindow> window = windowsById->Get(aIDHashKey->GetKey());
if (window) {
window->RiskyUnlink();
}
return PL_DHASH_NEXT;
}
/* static */ void
nsWindowMemoryReporter::UnlinkGhostWindows()
{
if (!sWindowReporter) {
return;
}
nsGlobalWindow::WindowByIdTable* windowsById =
nsGlobalWindow::GetWindowsTable();
if (!windowsById) {
return;
}
// Hold on to every window in memory so that window objects can't be
// destroyed while we're calling the UnlinkGhostWindows callback.
WindowArray windows;
windowsById->Enumerate(GetWindows, &windows);
// Get the IDs of all the "ghost" windows, and unlink them all.
nsTHashtable<nsUint64HashKey> ghostWindows;
sWindowReporter->CheckForGhostWindows(&ghostWindows);
ghostWindows.EnumerateEntries(UnlinkGhostWindowsEnumerator, nullptr);
}
#endif

View File

@ -146,6 +146,14 @@ public:
static void Init();
#ifdef DEBUG
/**
* Unlink all known ghost windows, to enable investigating what caused them
* to become ghost windows in the first place.
*/
static void UnlinkGhostWindows();
#endif
private:
/**
* nsGhostWindowReporter generates the "ghost-windows" report, which counts

View File

@ -121,7 +121,7 @@ interface ScheduledGCCallback : nsISupports
/**
* interface of Components.utils
*/
[scriptable, uuid(f4b12240-02aa-47e5-99d5-43cd50fbd4b7)]
[scriptable, uuid(0b81b4f2-cad7-4602-a5cb-b99c9d514196)]
interface nsIXPCComponents_Utils : nsISupports
{
@ -279,6 +279,12 @@ interface nsIXPCComponents_Utils : nsISupports
*/
void schedulePreciseShrinkingGC(in ScheduledGCCallback callback);
/*
* In a debug build, unlink any ghost windows. This is only for debugging
* leaks, and can cause bad things to happen if called.
*/
void unlinkGhostWindows();
/**
* Return the keys in a weak map. This operation is
* non-deterministic because it is affected by the scheduling of the

View File

@ -2857,6 +2857,18 @@ nsXPCComponents_Utils::SchedulePreciseShrinkingGC(ScheduledGCCallback* aCallback
return NS_DispatchToMainThread(event);
}
/* void unlinkGhostWindows(); */
NS_IMETHODIMP
nsXPCComponents_Utils::UnlinkGhostWindows()
{
#ifdef DEBUG
nsWindowMemoryReporter::UnlinkGhostWindows();
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
/* [implicit_jscontext] jsval nondeterministicGetWeakMapKeys(in jsval aMap); */
NS_IMETHODIMP
nsXPCComponents_Utils::NondeterministicGetWeakMapKeys(HandleValue aMap,