Bug 1045945 - Initialize the destroy principals callback for workers. r=bent, a=lmandel
authorJon Coppeard <jcoppeard@mozilla.com>
Mon, 15 Sep 2014 16:49:11 +0100
changeset 225182 5c5b67febe2cec3d1468b940312910d97be54698
parent 225181 719d5e69451dc135eda6e3dc6b90e98f499be6fa
child 225183 4d9f624f127cc3a34c93a5e07664726ba5311035
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent, lmandel
bugs1045945
milestone34.0a2
Bug 1045945 - Initialize the destroy principals callback for workers. r=bent, a=lmandel
dom/workers/Principal.cpp
dom/workers/Principal.h
dom/workers/RuntimeService.cpp
js/public/Principals.h
--- a/dom/workers/Principal.cpp
+++ b/dom/workers/Principal.cpp
@@ -1,28 +1,42 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Principal.h"
 
 #include "jsapi.h"
+#include "mozilla/Assertions.h"
 
 BEGIN_WORKERS_NAMESPACE
 
 JSPrincipals*
 GetWorkerPrincipal()
 {
-  static Atomic<bool> sInitialized(false);
   static JSPrincipals sPrincipal;
 
-  bool isInitialized = sInitialized.exchange(true);
-  if (!isInitialized) {
-    sPrincipal.refcount = 1;
+  /*
+   * To make sure the the principals refcount is initialized to one, atomically
+   * increment it on every pass though this function. If we discover this wasn't
+   * the first time, decrement it again. This avoids the need for
+   * synchronization.
+   */
+  int32_t prevRefcount = sPrincipal.refcount++;
+  if (prevRefcount > 0) {
+    --sPrincipal.refcount;
+  } else {
 #ifdef DEBUG
     sPrincipal.debugToken = kJSPrincipalsDebugToken;
 #endif
   }
+
   return &sPrincipal;
 }
 
+void
+DestroyWorkerPrincipals(JSPrincipals* aPrincipals)
+{
+  MOZ_ASSERT_UNREACHABLE("Worker principals refcount should never fall below one");
+}
+
 END_WORKERS_NAMESPACE
--- a/dom/workers/Principal.h
+++ b/dom/workers/Principal.h
@@ -8,11 +8,14 @@
 
 #include "Workers.h"
 
 BEGIN_WORKERS_NAMESPACE
 
 JSPrincipals*
 GetWorkerPrincipal();
 
+void
+DestroyWorkerPrincipals(JSPrincipals* aPrincipals);
+
 END_WORKERS_NAMESPACE
 
 #endif /* mozilla_dom_workers_principal_h__ */
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -56,16 +56,17 @@
 #ifdef MOZ_NUWA_PROCESS
 #include "ipc/Nuwa.h"
 #endif
 
 #ifdef DEBUG
 #include "nsThreadManager.h"
 #endif
 
+#include "Principal.h"
 #include "ServiceWorker.h"
 #include "SharedWorker.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 
 #ifdef ENABLE_TESTS
 #include "BackgroundChildImpl.h"
 #include "mozilla/ipc/PBackgroundChild.h"
@@ -850,16 +851,17 @@ public:
   // The heap size passed here doesn't matter, we will change it later in the
   // call to JS_SetGCParameter inside CreateJSContextForWorker.
   WorkerJSRuntime(JSRuntime* aParentRuntime, WorkerPrivate* aWorkerPrivate)
     : CycleCollectedJSRuntime(aParentRuntime,
                               WORKER_DEFAULT_RUNTIME_HEAPSIZE,
                               WORKER_DEFAULT_NURSERY_SIZE),
     mWorkerPrivate(aWorkerPrivate)
   {
+    JS_InitDestroyPrincipalsCallback(Runtime(), DestroyWorkerPrincipals);
   }
 
   ~WorkerJSRuntime()
   {
     auto rtPrivate = static_cast<WorkerThreadRuntimePrivate*>(JS_GetRuntimePrivate(Runtime()));
     delete rtPrivate;
     JS_SetRuntimePrivate(Runtime(), nullptr);
 
--- a/js/public/Principals.h
+++ b/js/public/Principals.h
@@ -19,16 +19,18 @@ struct JSPrincipals {
     /* Don't call "destroy"; use reference counting macros below. */
     mozilla::Atomic<int32_t> refcount;
 
 #ifdef JS_DEBUG
     /* A helper to facilitate principals debugging. */
     uint32_t    debugToken;
 #endif
 
+    JSPrincipals() : refcount(0) {}
+
     void setDebugToken(uint32_t token) {
 # ifdef JS_DEBUG
         debugToken = token;
 # endif
     }
 
     /*
      * This is not defined by the JS engine but should be provided by the