Bug 901290 - Cycle collect more than just at worker shutdown. r=mccr8, a=akeybl
authorKyle Huey <khuey@kylehuey.com>
Thu, 12 Sep 2013 09:24:05 -0400
changeset 154022 7354d3c16740780915e0fb8efb81cb857e13a359
parent 154021 178978aaff0ca90498bca878715825cc9e26cc3a
child 154023 7d8eccddb0347283a091fb5141c25c501c33b3fa
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8, akeybl
bugs901290
milestone25.0a2
Bug 901290 - Cycle collect more than just at worker shutdown. r=mccr8, a=akeybl
dom/workers/RuntimeService.cpp
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -821,17 +821,18 @@ CreateJSContextForWorker(WorkerPrivate* 
 class WorkerJSRuntime : public mozilla::CycleCollectedJSRuntime
 {
 public:
   // The heap size passed here doesn't matter, we will change it later in the
   // call to JS_SetGCParameter inside CreateJSContextForWorker.
   WorkerJSRuntime(WorkerPrivate* aWorkerPrivate)
   : CycleCollectedJSRuntime(WORKER_DEFAULT_RUNTIME_HEAPSIZE,
                             JS_NO_HELPER_THREADS,
-                            false)
+                            false),
+    mWorkerPrivate(aWorkerPrivate)
   {
     // We need to ensure that a JSContext outlives the cycle collector, and
     // that the internal JSContext created by ctypes is not the last JSContext
     // to die.  So we create an unused JSContext here and destroy it after
     // the cycle collector shuts down.  Thus all cycles will be broken before
     // the last GC and all finalizers will be run.
     mLastJSContext = JS_NewContext(Runtime(), 0);
     MOZ_ASSERT(mLastJSContext);
@@ -840,17 +841,22 @@ public:
   ~WorkerJSRuntime()
   {
     // All JSContexts except mLastJSContext should be destroyed now.  The
     // worker global will be unrooted and the shutdown cycle collection
     // should break all remaining cycles.  Destroying mLastJSContext will run
     // the GC the final time and finalize any JSObjects that were participating
     // in cycles that were broken during CC shutdown.
     nsCycleCollector_shutdownThreads();
+
+    // If we try to CC after this point, we're gonna have a bad time.
+    mWorkerPrivate = nullptr;
+
     nsCycleCollector_shutdown();
+
     JS_DestroyContext(mLastJSContext);
     mLastJSContext = nullptr;
   }
 
   // Make this public for now.  Ideally we'd hide the JSRuntime inside.
   JSRuntime*
   Runtime() const
   {
@@ -861,17 +867,32 @@ public:
   DispatchDeferredDeletion(bool aContinuation) MOZ_OVERRIDE
   {
     MOZ_ASSERT(!aContinuation);
 
     // Do it immediately, no need for asynchronous behavior here.
     nsCycleCollector_doDeferredDeletion();
   }
 
+  virtual void CustomGCCallback(JSGCStatus aStatus) MOZ_OVERRIDE
+  {
+    if (!mWorkerPrivate) {
+      // We're shutting down, no need to do anything.
+      return;
+    }
+
+    mWorkerPrivate->AssertIsOnWorkerThread();
+
+    if (aStatus == JSGC_END) {
+      nsCycleCollector_collect(true, nullptr, nullptr);
+    }
+  }
+
 private:
+  WorkerPrivate* mWorkerPrivate;
   JSContext* mLastJSContext;
 };
 
 class WorkerThreadRunnable : public nsRunnable
 {
   WorkerPrivate* mWorkerPrivate;
 
 public: