Bug 899367 - Explicitly traverse outer windows, rather than doing it via JSContext iteration. r=mccr8
authorBobby Holley <bobbyholley@gmail.com>
Wed, 04 Sep 2013 14:06:54 -0700
changeset 158485 bb9646daf4c382ba31f91df5acd20a6e62a5fb38
parent 158484 c800b53263d221923333191d3e1933af1bac6112
child 158486 6ca662ba7c557d378bd2641dc737c5c031ba9e58
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs899367
milestone26.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 899367 - Explicitly traverse outer windows, rather than doing it via JSContext iteration. r=mccr8 Note that this machinery will go away in further patches. But we want to be deliberate about each of these steps.
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
js/xpconnect/src/XPCJSRuntime.cpp
xpcom/base/CycleCollectedJSRuntime.cpp
xpcom/base/CycleCollectedJSRuntime.h
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -74,17 +74,19 @@
 #include "prlog.h"
 #include "prthread.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
-
+#include "mozilla/CycleCollectedJSRuntime.h"
+
+#include "nsCycleCollectionNoteRootCallback.h"
 #include "GeckoProfiler.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 const size_t gStackSize = 8192;
 
 #ifdef PR_LOGGING
@@ -2950,16 +2952,31 @@ mozilla::dom::TraceOuterWindows(JSTracer
         (outer = js::DefaultObjectForContextOrNull(cx->mContext)))
     {
       JS::AssertGCThingMustBeTenured(outer);
       JS_CallObjectTracer(aTracer, &outer, "Outer Window");
     }
   }
 }
 
+void
+mozilla::dom::TraverseOuterWindows(nsCycleCollectionNoteRootCallback& aCb)
+{
+  nsCycleCollectionParticipant* participant = mozilla::CycleCollectedJSRuntime::JSContextParticipant();
+  for (nsJSContext* cx = sContextList; cx; cx = cx->mNext) {
+    JSObject* outer;
+    if (cx->mContext &&
+        (outer = js::DefaultObjectForContextOrNull(cx->mContext)) &&
+        xpc_IsGrayGCThing(outer))
+    {
+      aCb.NoteNativeRoot(cx->mContext, participant);
+    }
+  }
+}
+
 // A fast-array class for JS.  This class supports both nsIJSScriptArray and
 // nsIArray.  If it is JS itself providing and consuming this class, all work
 // can be done via nsIJSScriptArray, and avoid the conversion of elements
 // to/from nsISupports.
 // When consumed by non-JS (eg, another script language), conversion is done
 // on-the-fly.
 class nsJSArgArray MOZ_FINAL : public nsIJSArgArray {
 public:
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -15,29 +15,31 @@
 #include "nsIArray.h"
 #include "mozilla/Attributes.h"
 #include "nsThreadUtils.h"
 
 class nsICycleCollectorListener;
 class nsIXPConnectJSObjectHolder;
 class nsRootedJSValueArray;
 class nsScriptNameSpaceManager;
+class nsCycleCollectionNoteRootCallback;
 
 namespace mozilla {
 template <class> class Maybe;
 }
 
 // The amount of time we wait between a request to GC (due to leaving
 // a page) and doing the actual GC.
 #define NS_GC_DELAY                 4000 // ms
 
 namespace mozilla {
 namespace dom {
 
 void TraceOuterWindows(JSTracer *aTracer);
+void TraverseOuterWindows(nsCycleCollectionNoteRootCallback& aCb);
 
 } /* namespace dom */
 } /* namespace mozilla */
 
 class nsJSContext : public nsIScriptContext
 {
 public:
   nsJSContext(bool aGCOnDestruction, nsIScriptGlobalObject* aGlobalObject);
@@ -177,16 +179,17 @@ private:
   PRTime mModalStateTime;
   uint32_t mModalStateDepth;
 
   nsJSContext *mNext;
   nsJSContext **mPrev;
 
   /* This function needs access to the linked list members above. */
   friend void mozilla::dom::TraceOuterWindows(JSTracer *aTracer);
+  friend void mozilla::dom::TraverseOuterWindows(nsCycleCollectionNoteRootCallback& aCb);
 
   // mGlobalObjectRef ensures that the outer window stays alive as long as the
   // context does. It is eventually collected by the cycle collector.
   nsCOMPtr<nsIScriptGlobalObject> mGlobalObjectRef;
 
   static int JSOptionChangedCallback(const char *pref, void *data);
 
   static bool DOMOperationCallback(JSContext *cx);
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -556,16 +556,20 @@ CanSkipWrappedJS(nsXPCWrappedJS *wrapped
     return false;
 }
 
 void
 XPCJSRuntime::TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback &cb)
 {
     XPCAutoLock lock(mMapLock);
 
+    // Traverse outer windows, which are the default compartment objects for DOM
+    // JSContexts.
+    dom::TraverseOuterWindows(cb);
+
     XPCWrappedNativeScope::SuspectAllWrappers(this, cb);
 
     for (XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) {
         XPCTraceableVariant* v = static_cast<XPCTraceableVariant*>(e);
         if (nsCCUncollectableMarker::InGeneration(cb,
                                                   v->CCGeneration())) {
            jsval val = v->GetJSValPreserveColor();
            if (val.isObject() && !xpc_IsGrayGCThing(&val.toObject()))
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -710,42 +710,19 @@ CycleCollectedJSRuntime::TraverseObjectS
   TraverseObjectShimClosure* closure =
       static_cast<TraverseObjectShimClosure*>(aData);
 
   MOZ_ASSERT(js::GCThingTraceKind(aThing) == JSTRACE_OBJECT);
   closure->self->TraverseGCThing(CycleCollectedJSRuntime::TRAVERSE_CPP, aThing,
                                  JSTRACE_OBJECT, closure->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
-// roots were marked by the JS GC and will be colored correctly in the cycle
-// collector.
-void
-CycleCollectedJSRuntime::MaybeTraverseGlobals(nsCycleCollectionNoteRootCallback& aCb) const
-{
-  JSContext *iter = nullptr, *acx;
-  while ((acx = JS_ContextIterator(Runtime(), &iter))) {
-    // Add the context to the CC graph only if traversing it would
-    // end up doing something.
-    JSObject* global = js::DefaultObjectForContextOrNull(acx);
-    if (global && xpc_IsGrayGCThing(global)) {
-      aCb.NoteNativeRoot(acx, JSContextParticipant());
-    }
-  }
-}
-
 void
 CycleCollectedJSRuntime::TraverseNativeRoots(nsCycleCollectionNoteRootCallback& aCb)
 {
-  MaybeTraverseGlobals(aCb);
-
   // NB: This is here just to preserve the existing XPConnect order. I doubt it
   // would hurt to do this after the JS holders.
   TraverseAdditionalNativeRoots(aCb);
 
   Closure closure = { true, &aCb };
   mJSHolders.Enumerate(NoteJSHolder, &closure);
 }
 
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -137,18 +137,16 @@ private:
                   nsCycleCollectionTraversalCallback& aCb);
 
   void
   TraverseZone(JS::Zone* aZone, nsCycleCollectionTraversalCallback& aCb);
 
   static void
   TraverseObjectShim(void* aData, void* aThing);
 
-  void MaybeTraverseGlobals(nsCycleCollectionNoteRootCallback& aCb) const;
-
   void TraverseNativeRoots(nsCycleCollectionNoteRootCallback& aCb);
 
   static void TraceBlackJS(JSTracer* aTracer, void* aData);
   static void TraceGrayJS(JSTracer* aTracer, void* aData);
   static void GCCallback(JSRuntime* aRuntime, JSGCStatus aStatus, void* aData);
   static bool ContextCallback(JSContext* aCx, unsigned aOperation,
                               void* aData);