Bug 712743, if node is black, return early from ::Traverse, r=mccr8,sicking
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Sat, 24 Dec 2011 00:28:58 +0200
changeset 83244 0697daa434137c0b12bc3d6b4dfaaec8a6ad7c62
parent 83243 33473863f42cb9a2f4913f89bac6428b9ace6b4e
child 83271 ede336ccaed043083642e1490a31b4b6e1ff5569
push id21743
push useropettay@mozilla.com
push dateFri, 23 Dec 2011 23:51:21 +0000
treeherdermozilla-central@0697daa43413 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8, sicking
bugs712743
milestone12.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 712743, if node is black, return early from ::Traverse, r=mccr8,sicking
content/base/src/nsGenericElement.cpp
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1202,26 +1202,68 @@ nsINode::GetContextForEventHandlers(nsre
 
 /* static */
 void
 nsINode::Trace(nsINode *tmp, TraceCallback cb, void *closure)
 {
   nsContentUtils::TraceWrapper(tmp, cb, closure);
 }
 
+static bool
+IsBlackNode(nsINode* aNode)
+{
+  JSObject* o = aNode->GetWrapperPreserveColor();
+  return o && !xpc_IsGrayGCThing(o);
+}
+
+static bool
+IsXBL(nsINode* aNode)
+{
+  return aNode->IsElement() &&
+         aNode->AsElement()->IsInNamespace(kNameSpaceID_XBL);
+}
+
 /* static */
 bool
 nsINode::Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb)
 {
   nsIDocument *currentDoc = tmp->GetCurrentDoc();
   if (currentDoc &&
       nsCCUncollectableMarker::InGeneration(cb, currentDoc->GetMarkedCCGeneration())) {
     return false;
   }
 
+  if (nsCCUncollectableMarker::sGeneration) {
+    // If we're black no need to traverse.
+    if (IsBlackNode(tmp)) {
+      return false;
+    }
+
+    const PtrBits problematicFlags =
+      (NODE_IS_ANONYMOUS |
+       NODE_IS_IN_ANONYMOUS_SUBTREE |
+       NODE_IS_NATIVE_ANONYMOUS_ROOT |
+       NODE_MAY_BE_IN_BINDING_MNGR |
+       NODE_IS_INSERTION_PARENT);
+
+    if (!tmp->HasFlag(problematicFlags) && !IsXBL(tmp)) {
+      // If we're in a black document, return early.
+      if ((currentDoc && IsBlackNode(currentDoc))) {
+        return false;
+      }
+      // If we're not in anonymous content and we have a black parent,
+      // return early.
+      nsIContent* parent = tmp->GetParent();
+      if (parent && !IsXBL(parent) && IsBlackNode(parent)) {
+        NS_ABORT_IF_FALSE(parent->IndexOf(tmp) >= 0, "Parent doesn't own us?");
+        return false;
+      }
+    }
+  }
+
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetParent())
 
   nsSlots *slots = tmp->GetExistingSlots();
   if (slots) {
     slots->Traverse(cb);
   }