Bug 802829 - Don't add nsXPCWrappedJS objects to CC graph if they only point to a certainly alive object, r=mccr8
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Sat, 20 Oct 2012 22:53:25 +0300
changeset 111005 034634c4125ae8bfd14f9aa16b5df813c16a136b
parent 111004 92e4438ecf5e233da0243c1082e7af1758ce0672
child 111016 4957ebb0625a1f1390928b06f37bd90f9aace47d
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersmccr8
bugs802829
milestone19.0a1
Bug 802829 - Don't add nsXPCWrappedJS objects to CC graph if they only point to a certainly alive object, r=mccr8
js/xpconnect/src/XPCJSRuntime.cpp
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -420,16 +420,44 @@ SuspectDOMExpandos(nsPtrHashKey<JSObject
     const dom::DOMClass* clasp;
     dom::DOMObjectSlot slot = GetDOMClass(obj, clasp);
     MOZ_ASSERT(slot != dom::eNonDOMObject && clasp->mDOMObjectIsISupports);
     nsISupports* native = dom::UnwrapDOMObject<nsISupports>(obj, slot);
     closure->cb->NoteXPCOMRoot(native);
     return PL_DHASH_NEXT;
 }
 
+bool
+CanSkipWrappedJS(nsXPCWrappedJS *wrappedJS)
+{
+    JSObject *obj = wrappedJS->GetJSObjectPreserveColor();
+    // If traversing wrappedJS wouldn't release it, nor
+    // cause any other objects to be added to the graph, no
+    // need to add it to the graph at all.
+    if (nsCCUncollectableMarker::sGeneration &&
+        (!obj || !xpc_IsGrayGCThing(obj)) &&
+        !wrappedJS->IsSubjectToFinalization() &&
+        wrappedJS->GetRootWrapper() == wrappedJS) {
+        if (!wrappedJS->IsAggregatedToNative()) {
+            return true;
+        } else {
+            nsISupports* agg = wrappedJS->GetAggregatedNativeObject();
+            nsXPCOMCycleCollectionParticipant* cp = nullptr;
+            CallQueryInterface(agg, &cp);
+            nsISupports* canonical = nullptr;
+            agg->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
+                                reinterpret_cast<void**>(&canonical));
+            if (cp && canonical && cp->CanSkipInCC(canonical)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
 void
 XPCJSRuntime::AddXPConnectRoots(nsCycleCollectionTraversalCallback &cb)
 {
     // For all JS objects that are held by native objects but aren't held
     // through rooting or locking, we need to add all the native objects that
     // hold them so that the JS objects are colored correctly in the cycle
     // collector. This includes JSContexts that don't have outstanding requests,
     // because their global object wasn't marked by the JS GC. All other JS
@@ -453,25 +481,18 @@ XPCJSRuntime::AddXPConnectRoots(nsCycleC
            if (val.isObject() && !xpc_IsGrayGCThing(&val.toObject()))
                continue;
         }
         cb.NoteXPCOMRoot(v);
     }
 
     for (XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) {
         nsXPCWrappedJS *wrappedJS = static_cast<nsXPCWrappedJS*>(e);
-        JSObject *obj = wrappedJS->GetJSObjectPreserveColor();
-        // If traversing wrappedJS wouldn't release it, nor
-        // cause any other objects to be added to the graph, no
-        // need to add it to the graph at all.
-        if (nsCCUncollectableMarker::sGeneration &&
-            !cb.WantAllTraces() && (!obj || !xpc_IsGrayGCThing(obj)) &&
-            !wrappedJS->IsSubjectToFinalization() &&
-            wrappedJS->GetRootWrapper() == wrappedJS &&
-            !wrappedJS->IsAggregatedToNative()) {
+        if (!cb.WantAllTraces() &&
+            CanSkipWrappedJS(wrappedJS)) {
             continue;
         }
 
         cb.NoteXPCOMRoot(static_cast<nsIXPConnectWrappedJS *>(wrappedJS));
     }
 
     Closure closure = { true, &cb };
     mJSHolders.Enumerate(NoteJSHolder, &closure);