Suspect all native wrappers during cycle collection (last part, rest already done by Graydon). b=368869 r=graydon sr=jst
authordbaron@dbaron.org
Fri, 29 Jun 2007 20:03:30 -0700
changeset 2954 21fcf9c2f24177ea6347608f09d8d1fe09ada076
parent 2953 1fb754d062c7ddcb342945046bfcca0113177ad1
child 2955 2489cfe25d5bc2bf6571ba7e2a2309415817e05d
push idunknown
push userunknown
push dateunknown
reviewersgraydon, jst
bugs368869
milestone1.9a6pre
Suspect all native wrappers during cycle collection (last part, rest already done by Graydon). b=368869 r=graydon sr=jst
js/src/xpconnect/src/nsXPConnect.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcwrappednativescope.cpp
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -568,16 +568,18 @@ nsXPConnect::BeginCycleCollection()
     JSContext *cx = mCycleCollectionContext->GetJSContext();
     gOldJSGCCallback = JS_SetGCCallback(cx, XPCCycleGCCallback);
     JS_SetGCThingCallback(cx, XPCMarkNotification, mObjRefcounts);
     JS_GC(cx);
     JS_SetGCThingCallback(cx, nsnull, nsnull);
     JS_SetGCCallback(cx, gOldJSGCCallback);
     gOldJSGCCallback = nsnull;
 
+    XPCWrappedNativeScope::SuspectAllWrappers(mRuntime);
+
 #ifndef XPCONNECT_STANDALONE
     NS_ASSERTION(mObjRefcounts->mScopes.Count() == 0, "Didn't clear mScopes?");
     XPCWrappedNativeScope::TraverseScopes(*mCycleCollectionContext);
 #endif
 
     return NS_OK;
 }
 
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -1131,16 +1131,19 @@ public:
 
     static void
     SystemIsBeingShutDown(XPCCallContext& ccx);
 
     static void
     TraceJS(JSTracer* trc, XPCJSRuntime* rt);
 
     static void
+    SuspectAllWrappers(XPCJSRuntime* rt);
+
+    static void
     FinishedMarkPhaseOfGC(JSContext* cx, XPCJSRuntime* rt);
 
     static void
     FinishedFinalizationPhaseOfGC(JSContext* cx);
 
     static void
     MarkAllWrappedNativesAndProtos();
 
--- a/js/src/xpconnect/src/xpcwrappednativescope.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp
@@ -266,43 +266,65 @@ WrappedNativeJSGCThingTracer(JSDHashTabl
                              uint32 number, void *arg)
 {
     XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value;
     if(wrapper->HasExternalReference())
     {
         JSTracer* trc = (JSTracer *)arg;
         JS_CALL_OBJECT_TRACER(trc, wrapper->GetFlatJSObject(),
                               "XPCWrappedNative::mFlatJSObject");
+    }
 
-        // FIXME: this call appears to do more harm than good, but
-        // there is reason to imagine it might clean up some cycles
-        // formed by a poor order between C++ and JS garbage cycle
-        // formations. See Bug 368869.
-        //
-        // if (JS_IsGCMarkingTracer(trc))
-        //   nsCycleCollector_suspectCurrent(wrapper);
-    }
     return JS_DHASH_NEXT;
 }
 
 // static
 void
 XPCWrappedNativeScope::TraceJS(JSTracer* trc, XPCJSRuntime* rt)
 {
     // FIXME The lock may not be necessary during tracing as that serializes
     // access to JS runtime. See bug 380139.
     XPCAutoLock lock(rt->GetMapLock());
 
-    // Do JS_CallTracer for all wrapperednatives with external references.
+    // Do JS_CallTracer for all wrapped natives with external references.
     for(XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext)
     {
         cur->mWrappedNativeMap->Enumerate(WrappedNativeJSGCThingTracer, trc);
     }
 }
 
+JS_STATIC_DLL_CALLBACK(JSDHashOperator)
+WrappedNativeSuspecter(JSDHashTable *table, JSDHashEntryHdr *hdr,
+                       uint32 number, void *arg)
+{
+    XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value;
+    XPCWrappedNativeProto* proto = wrapper->GetProto();
+    if(proto && proto->ClassIsMainThreadOnly()) 
+    {
+        NS_ASSERTION(NS_IsMainThread(), 
+                     "Suspecting wrapped natives from non-main thread");
+        nsCycleCollector_suspectCurrent(wrapper);
+    }
+
+    return JS_DHASH_NEXT;
+}
+
+// static
+void
+XPCWrappedNativeScope::SuspectAllWrappers(XPCJSRuntime* rt)
+{
+    XPCAutoLock lock(rt->GetMapLock());
+
+    // Do nsCycleCollector_suspectCurrent for all wrapped natives.
+    for(XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext)
+    {
+        cur->mWrappedNativeMap->Enumerate(WrappedNativeSuspecter, nsnull);
+    }
+}
+
 // static
 void
 XPCWrappedNativeScope::FinishedMarkPhaseOfGC(JSContext* cx, XPCJSRuntime* rt)
 {
     // FIXME The lock may not be necessary since we are inside JSGC_MARK_END
     // callback and GX serializes access to JS runtime. See bug 380139.
     XPCAutoLock lock(rt->GetMapLock());