Don't initialize gfxPrefs with libpref in the GPU process. (bug 1280822 part 1, r=milan)
authorDavid Anderson <danderson@mozilla.com>
Sun, 26 Jun 2016 23:33:14 -0700
changeset 342737 6ec2097515dc60d8dde4532eb8db1d767a89ffa0
parent 342714 e68e0c28c1b1ed8ac55693f4fb0f6ebb14b74436
child 342738 d787bc79425f6cd02c4a8bbf8279f3a7afbadf1e
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmilan
bugs1280822
milestone50.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
Don't initialize gfxPrefs with libpref in the GPU process. (bug 1280822 part 1, r=milan)
gfx/thebes/gfxPrefs.cpp
gfx/thebes/gfxPrefs.h
modules/libpref/Preferences.cpp
modules/libpref/Preferences.h
--- a/gfx/thebes/gfxPrefs.cpp
+++ b/gfx/thebes/gfxPrefs.cpp
@@ -3,16 +3,17 @@
  * 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 "gfxPrefs.h"
 
 #include "mozilla/Preferences.h"
 #include "MainThreadUtils.h"
 #include "mozilla/gfx/Preferences.h"
+#include "nsXULAppAPI.h"
 
 using namespace mozilla;
 
 gfxPrefs* gfxPrefs::sInstance = nullptr;
 bool gfxPrefs::sInstanceHasBeenDestroyed = false;
 
 class PreferenceAccessImpl : public mozilla::gfx::PreferenceAccess
 {
@@ -46,16 +47,23 @@ gfxPrefs::DestroySingleton()
 bool
 gfxPrefs::SingletonExists()
 {
   return sInstance != nullptr;
 }
 
 gfxPrefs::gfxPrefs()
 {
+  // UI, content, and plugin processes use XPCOM and should have prefs
+  // ready by the time we initialize gfxPrefs.
+  MOZ_ASSERT_IF(XRE_IsContentProcess() ||
+                XRE_IsParentProcess() ||
+                XRE_GetProcessType() == GeckoProcessType_Plugin,
+                Preferences::IsServiceAvailable());
+
   gfxPrefs::AssertMainThread();
   mMoz2DPrefAccess = new PreferenceAccessImpl;
   mozilla::gfx::PreferenceAccess::SetAccess(mMoz2DPrefAccess);
 }
 
 gfxPrefs::~gfxPrefs()
 {
   gfxPrefs::AssertMainThread();
@@ -67,76 +75,97 @@ gfxPrefs::~gfxPrefs()
   mMoz2DPrefAccess = nullptr;
 }
 
 void gfxPrefs::AssertMainThread()
 {
   MOZ_ASSERT(NS_IsMainThread(), "this code must be run on the main thread");
 }
 
+// On lightweight processes such as for GMP and GPU, XPCOM is not initialized,
+// and therefore we don't have access to Preferences. When XPCOM is not
+// available we rely on manual synchronization of gfxPrefs values over IPC.
+/* static */ bool
+gfxPrefs::IsPrefsServiceAvailable()
+{
+  return Preferences::IsServiceAvailable();
+}
+
 void gfxPrefs::PrefAddVarCache(bool* aVariable,
                                const char* aPref,
                                bool aDefault)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddBoolVarCache(aVariable, aPref, aDefault);
 }
 
 void gfxPrefs::PrefAddVarCache(int32_t* aVariable,
                                const char* aPref,
                                int32_t aDefault)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddIntVarCache(aVariable, aPref, aDefault);
 }
 
 void gfxPrefs::PrefAddVarCache(uint32_t* aVariable,
                                const char* aPref,
                                uint32_t aDefault)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddUintVarCache(aVariable, aPref, aDefault);
 }
 
 void gfxPrefs::PrefAddVarCache(float* aVariable,
                                const char* aPref,
                                float aDefault)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddFloatVarCache(aVariable, aPref, aDefault);
 }
 
 bool gfxPrefs::PrefGet(const char* aPref, bool aDefault)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   return Preferences::GetBool(aPref, aDefault);
 }
 
 int32_t gfxPrefs::PrefGet(const char* aPref, int32_t aDefault)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   return Preferences::GetInt(aPref, aDefault);
 }
 
 uint32_t gfxPrefs::PrefGet(const char* aPref, uint32_t aDefault)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   return Preferences::GetUint(aPref, aDefault);
 }
 
 float gfxPrefs::PrefGet(const char* aPref, float aDefault)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   return Preferences::GetFloat(aPref, aDefault);
 }
 
 void gfxPrefs::PrefSet(const char* aPref, bool aValue)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::SetBool(aPref, aValue);
 }
 
 void gfxPrefs::PrefSet(const char* aPref, int32_t aValue)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::SetInt(aPref, aValue);
 }
 
 void gfxPrefs::PrefSet(const char* aPref, uint32_t aValue)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::SetUint(aPref, aValue);
 }
 
 void gfxPrefs::PrefSet(const char* aPref, float aValue)
 {
+  MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::SetFloat(aPref, aValue);
 }
 
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -79,36 +79,40 @@ private:
   // Enums for the update policy.
   enum class UpdatePolicy {
     Skip, // Set the value to default, skip any Preferences calls
     Once, // Evaluate the preference once, unchanged during the session
     Live  // Evaluate the preference and set callback so it stays current/live
   };
 
   // Since we cannot use const char*, use a function that returns it.
-  template <UpdatePolicy Update, class T, T Default(void), const char* Pref(void)>
+  template <UpdatePolicy Update, class T, T Default(void), const char* Prefname(void)>
   class PrefTemplate
   {
   public:
     PrefTemplate()
     : mValue(Default())
     {
-      Register(Update, Pref());
+      // If not using the Preferences service, values are synced over IPC, so
+      // there's no need to register us as a Preferences observer.
+      if (IsPrefsServiceAvailable()) {
+        Register(Update, Prefname());
+      }
     }
     void Register(UpdatePolicy aUpdate, const char* aPreference)
     {
       AssertMainThread();
-      switch(aUpdate) {
+      switch (aUpdate) {
         case UpdatePolicy::Skip:
           break;
         case UpdatePolicy::Once:
           mValue = PrefGet(aPreference, mValue);
           break;
         case UpdatePolicy::Live:
-          PrefAddVarCache(&mValue,aPreference, mValue);
+          PrefAddVarCache(&mValue, aPreference, mValue);
           break;
         default:
           MOZ_CRASH("Incomplete switch");
       }
     }
     void Set(UpdatePolicy aUpdate, const char* aPref, T aValue)
     {
       AssertMainThread();
@@ -488,16 +492,17 @@ public:
   static void DestroySingleton();
   static bool SingletonExists();
 
 private:
   static gfxPrefs* sInstance;
   static bool sInstanceHasBeenDestroyed;
 
 private:
+  static bool IsPrefsServiceAvailable();
   // Creating these to avoid having to include Preferences.h in the .h
   static void PrefAddVarCache(bool*, const char*, bool);
   static void PrefAddVarCache(int32_t*, const char*, int32_t);
   static void PrefAddVarCache(uint32_t*, const char*, uint32_t);
   static void PrefAddVarCache(float*, const char*, float);
   static bool PrefGet(const char*, bool);
   static int32_t PrefGet(const char*, int32_t);
   static uint32_t PrefGet(const char*, uint32_t);
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -430,16 +430,23 @@ Preferences::GetInstanceForService()
   NS_DispatchToMainThread(runnable);
 
   NS_ADDREF(sPreferences);
   return sPreferences;
 }
 
 // static
 bool
+Preferences::IsServiceAvailable()
+{
+  return !!sPreferences;
+}
+
+// static
+bool
 Preferences::InitStaticMembers()
 {
 #ifndef MOZ_B2G
   MOZ_ASSERT(NS_IsMainThread());
 #endif
 
   if (!sShutdown && !sPreferences) {
     nsCOMPtr<nsIPrefService> prefService =
--- a/modules/libpref/Preferences.h
+++ b/modules/libpref/Preferences.h
@@ -47,16 +47,21 @@ public:
   NS_FORWARD_NSIPREFBRANCH(sRootBranch->)
   NS_DECL_NSIOBSERVER
 
   Preferences();
 
   nsresult Init();
 
   /**
+   * Returns true if the Preferences service is available, false otherwise.
+   */
+  static bool IsServiceAvailable();
+
+  /**
    * Reset loaded user prefs then read them
    */
   static nsresult ResetAndReadUserPrefs();
 
   /**
    * Returns the singleton instance which is addreffed.
    */
   static Preferences* GetInstanceForService();