Bug 713462, don't traverse black content lists, r=mccr8
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Thu, 29 Dec 2011 23:21:33 +0200
changeset 84725 1d0a814ebf12fd72b68691dd6aa092e0be8644d6
parent 84724 95ccf0a6a95a3cd5f45d2e19a13f3ae993182f1d
child 84726 0d684c34d1e4e7c0bd6779711119edac141ae106
child 109077 2e59a622b0900d82c1e2a7fd0153ff22c7291f46
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs713462
milestone12.0a1
Bug 713462, don't traverse black content lists, r=mccr8
content/base/src/nsContentList.cpp
content/base/src/nsGenericElement.cpp
dom/base/nsWrapperCache.h
dom/base/nsWrapperCacheInlines.h
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -42,19 +42,19 @@
  * getElementsByTagName, some properties on nsIDOMHTMLDocument, etc).
  */
 
 #include "nsContentList.h"
 #include "nsIContent.h"
 #include "nsIDOMNode.h"
 #include "nsIDocument.h"
 #include "nsGenericElement.h"
-
+#include "nsWrapperCacheInlines.h"
 #include "nsContentUtils.h"
-
+#include "nsCCUncollectableMarker.h"
 #include "nsGkAtoms.h"
 
 #include "dombindings.h"
 
 // Form related includes
 #include "nsIDOMHTMLFormElement.h"
 
 #include "pldhash.h"
@@ -75,18 +75,21 @@ nsBaseContentList::~nsBaseContentList()
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsBaseContentList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsBaseContentList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mElements)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBaseContentList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+  if (nsCCUncollectableMarker::sGeneration && tmp->IsBlack()) {
+    return NS_SUCCESS_INTERRUPTED_TRAVERSE;
+  }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mElements)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsBaseContentList)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 #define NS_CONTENT_LIST_INTERFACES(_class)                                    \
     NS_INTERFACE_TABLE_ENTRY(_class, nsINodeList)                             \
     NS_INTERFACE_TABLE_ENTRY(_class, nsIDOMNodeList)
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1203,23 +1203,16 @@ 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
@@ -1228,36 +1221,36 @@ nsINode::Traverse(nsINode *tmp, nsCycleC
   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)) {
+    if (tmp->IsBlack()) {
       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))) {
+      if ((currentDoc && currentDoc->IsBlack())) {
         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)) {
+      if (parent && !IsXBL(parent) && parent->IsBlack()) {
         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())
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -185,16 +185,21 @@ public:
    */
   virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
                                bool *triedToWrap)
   {
     *triedToWrap = false;
     return nsnull;
   }
 
+  /**
+   * Returns true if the object has a non-gray wrapper.
+   */
+  bool IsBlack();
+
 private:
   // Only meant to be called by nsContentUtils.
   void SetPreservingWrapper(bool aPreserve)
   {
     if(aPreserve) {
       mWrapperPtrBits |= WRAPPER_BIT_PRESERVED;
     }
     else {
--- a/dom/base/nsWrapperCacheInlines.h
+++ b/dom/base/nsWrapperCacheInlines.h
@@ -134,9 +134,16 @@ nsWrapperCache::ClearWrapperIfProxy()
         return;
     }
 
     RemoveExpandoObject();
 
     SetWrapperBits(NULL);
 }
 
+inline bool
+nsWrapperCache::IsBlack()
+{
+  JSObject* o = GetWrapperPreserveColor();
+  return o && !xpc_IsGrayGCThing(o);
+}
+
 #endif /* nsWrapperCache_h___ */