Bug 333078: XPCOM cycle collector

r=brendan, sicking, bz, dbaron, bsmedberg
This commit is contained in:
graydon@mozilla.com
2007-01-04 22:31:26 +00:00
parent e78315789f
commit c164b31493
67 changed files with 3467 additions and 1467 deletions

View File

@@ -115,6 +115,9 @@
#include "nsContentCreatorFunctions.h"
#include "nsIFocusController.h"
#include "nsCycleCollectionParticipant.h"
#ifdef MOZ_SVG
PRBool NS_SVG_TestFeature(const nsAString &fstr);
#endif /* MOZ_SVG */
@@ -961,46 +964,6 @@ nsGenericElement::~nsGenericElement()
"Please remove this from the document properly");
}
/**
* During the Mark phase of the GC, we need to mark all of the preserved
* wrappers that are reachable via DOM APIs. Since reachability for DOM
* nodes is symmetric, if one DOM node is reachable from another via DOM
* APIs, then they are in the same strongly connected component.
* (Strongly connected components are never reachable from each other
* via DOM APIs.) We can refer to each strongly connected component by
* walking up to the top of the parent chain. This function finds that
* root node for any DOM node.
*/
nsIDOMGCParticipant*
nsGenericElement::GetSCCIndex()
{
// This is an optimized way of walking nsIDOMNode::GetParentNode to
// the top of the tree.
nsINode *top = GetCurrentDoc();
if (!top) {
top = this;
nsINode *parent;
while ((parent = top->GetNodeParent())) {
top = parent;
}
}
return top;
}
void
nsGenericElement::AppendReachableList(nsCOMArray<nsIDOMGCParticipant>& aArray)
{
NS_ASSERTION(GetCurrentDoc() == nsnull,
"shouldn't be an SCC index if we're in a doc");
// This node is the root of a subtree that's been removed from the
// document (since AppendReachableList is only called on SCC index
// nodes). The document is reachable from it (through
// .ownerDocument), but it's not reachable from the document.
aArray.AppendObject(GetOwnerDoc());
}
NS_IMETHODIMP
nsGenericElement::GetNodeName(nsAString& aNodeName)
{
@@ -3009,9 +2972,55 @@ nsGenericElement::doRemoveChild(nsIDOMNode* aOldChild, nsIContent* aParent,
// nsISupports implementation
NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericElement, nsIContent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
// Unlink child content (and unbind our subtree).
{
PRUint32 i;
PRUint32 kids = tmp->mAttrsAndChildren.ChildCount();
for (i = kids; i > 0; i--) {
tmp->mAttrsAndChildren.ChildAt(i-1)->UnbindFromTree();
tmp->mAttrsAndChildren.RemoveChildAt(i-1);
}
}
// Unlink any DOM slots of interest.
{
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots)
slots->mAttributeMap = nsnull;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGenericElement, nsIContent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_LISTENERMANAGER
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_PRESERVED_WRAPPER
// Traverse child content.
{
PRUint32 i;
PRUint32 kids = tmp->mAttrsAndChildren.ChildCount();
for (i = 0; i < kids; i++)
cb.NoteXPCOMChild(tmp->mAttrsAndChildren.GetSafeChildAt(i));
}
// Traverse any DOM slots of interest.
{
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots) {
if (slots->mAttributeMap.get())
cb.NoteXPCOMChild(slots->mAttributeMap.get());
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN(nsGenericElement)
NS_INTERFACE_MAP_ENTRY(nsIContent)
NS_INTERFACE_MAP_ENTRY(nsIDOMGCParticipant)
NS_INTERFACE_MAP_ENTRY(nsINode)
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Node, new nsNode3Tearoff(this))
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMEventReceiver,
@@ -3025,11 +3034,13 @@ NS_INTERFACE_MAP_BEGIN(nsGenericElement)
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
new nsNodeSupportsWeakRefTearoff(this))
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(nsGenericElement)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsGenericElement)
NS_IMPL_RELEASE_WITH_DESTROY(nsGenericElement,
nsNodeUtils::LastRelease(this, PR_TRUE))
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGenericElement, nsIContent)
NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS_WITH_DESTROY(nsGenericElement,
nsIContent,
nsNodeUtils::LastRelease(this, PR_TRUE))
nsresult
nsGenericElement::PostQueryInterface(REFNSIID aIID, void** aInstancePtr)