Bug 1472523: Part 2 - Avoid unnecessary string copies in preference caches. r=njn draft
authorKris Maglione <maglione.k@gmail.com>
Sat, 30 Jun 2018 23:07:30 -0700
changeset 813932 ee25a335773b9afba9125c9092ed95eecc702cd9
parent 813931 628ad9af65cec16fb8be0c8dddc608b5ee5602e2
child 813933 b3cb0ba103fc239e42459e77cd389db0b5ecde18
push id115049
push usermaglione.k@gmail.com
push dateWed, 04 Jul 2018 05:52:30 +0000
reviewersnjn
bugs1472523
milestone63.0a1
Bug 1472523: Part 2 - Avoid unnecessary string copies in preference caches. r=njn MozReview-Commit-ID: 74svGlwMVF1
dom/base/nsObjectLoadingContent.cpp
gfx/thebes/gfxPrefs.cpp
gfx/thebes/gfxPrefs.h
layout/base/PositionedEventTargeting.cpp
layout/style/nsCSSProps.cpp
layout/xul/nsMenuPopupFrame.cpp
layout/xul/nsXULPopupManager.cpp
modules/libpref/Preferences.cpp
modules/libpref/Preferences.h
modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -98,20 +98,20 @@
 // Thanks so much, Microsoft! :(
 #ifdef CreateEvent
 #undef CreateEvent
 #endif
 #endif // XP_WIN
 
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
-static const char *kPrefYoutubeRewrite = "plugins.rewrite_youtube_embeds";
-static const char *kPrefBlockURIs = "browser.safebrowsing.blockedURIs.enabled";
-static const char *kPrefFavorFallbackMode = "plugins.favorfallback.mode";
-static const char *kPrefFavorFallbackRules = "plugins.favorfallback.rules";
+static const char kPrefYoutubeRewrite[] = "plugins.rewrite_youtube_embeds";
+static const char kPrefBlockURIs[] = "browser.safebrowsing.blockedURIs.enabled";
+static const char kPrefFavorFallbackMode[] = "plugins.favorfallback.mode";
+static const char kPrefFavorFallbackRules[] = "plugins.favorfallback.rules";
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::net;
 
 static LogModule*
 GetObjectLog()
 {
--- a/gfx/thebes/gfxPrefs.cpp
+++ b/gfx/thebes/gfxPrefs.cpp
@@ -136,73 +136,73 @@ gfxPrefs::IsPrefsServiceAvailable()
 
 /* static */ bool
 gfxPrefs::IsParentProcess()
 {
   return XRE_IsParentProcess();
 }
 
 void gfxPrefs::PrefAddVarCache(bool* aVariable,
-                               const char* aPref,
+                               const nsACString& aPref,
                                bool aDefault)
 {
   MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddBoolVarCache(aVariable, aPref, aDefault);
 }
 
 void gfxPrefs::PrefAddVarCache(int32_t* aVariable,
-                               const char* aPref,
+                               const nsACString& aPref,
                                int32_t aDefault)
 {
   MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddIntVarCache(aVariable, aPref, aDefault);
 }
 
 void gfxPrefs::PrefAddVarCache(uint32_t* aVariable,
-                               const char* aPref,
+                               const nsACString& aPref,
                                uint32_t aDefault)
 {
   MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddUintVarCache(aVariable, aPref, aDefault);
 }
 
 void gfxPrefs::PrefAddVarCache(float* aVariable,
-                               const char* aPref,
+                               const nsACString& aPref,
                                float aDefault)
 {
   MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddFloatVarCache(aVariable, aPref, aDefault);
 }
 
 void gfxPrefs::PrefAddVarCache(std::string* aVariable,
-                               const char* aPref,
+                               const nsCString& aPref,
                                std::string aDefault)
 {
   MOZ_ASSERT(IsPrefsServiceAvailable());
-  Preferences::SetCString(aPref, aVariable->c_str());
+  Preferences::SetCString(aPref.get(), aVariable->c_str());
 }
 
 void gfxPrefs::PrefAddVarCache(AtomicBool* aVariable,
-                               const char* aPref,
+                               const nsACString& aPref,
                                bool aDefault)
 {
   MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddAtomicBoolVarCache(aVariable, aPref, aDefault);
 }
 
 void gfxPrefs::PrefAddVarCache(AtomicInt32* aVariable,
-                               const char* aPref,
+                               const nsACString& aPref,
                                int32_t aDefault)
 {
   MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddAtomicIntVarCache(aVariable, aPref, aDefault);
 }
 
 void gfxPrefs::PrefAddVarCache(AtomicUint32* aVariable,
-                               const char* aPref,
+                               const nsACString& aPref,
                                uint32_t aDefault)
 {
   MOZ_ASSERT(IsPrefsServiceAvailable());
   Preferences::AddAtomicUintVarCache(aVariable, aPref, aDefault);
 }
 
 bool gfxPrefs::PrefGet(const char* aPref, bool aDefault)
 {
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -8,16 +8,17 @@
 
 #include <cmath>                 // for M_PI
 #include <stdint.h>
 #include <string>
 #include "mozilla/Assertions.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/gfx/LoggingConstants.h"
 #include "nsTArray.h"
+#include "nsString.h"
 
 // First time gfxPrefs::GetSingleton() needs to be called on the main thread,
 // before any of the methods accessing the values are used, but after
 // the Preferences system has been initialized.
 
 // The static methods to access the preference value are safe to call
 // from any thread after that first call.
 
@@ -236,17 +237,21 @@ private:
       AssertMainThread();
       switch (aUpdate) {
         case UpdatePolicy::Skip:
           break;
         case UpdatePolicy::Once:
           this->mValue = PrefGet(aPreference, this->mValue);
           break;
         case UpdatePolicy::Live:
-          PrefAddVarCache(&this->mValue, aPreference, this->mValue);
+          {
+            nsCString pref;
+            pref.AssignLiteral(aPreference, strlen(aPreference));
+            PrefAddVarCache(&this->mValue, pref, this->mValue);
+          }
           break;
         default:
           MOZ_CRASH("Incomplete switch");
       }
     }
     void Set(UpdatePolicy aUpdate, const char* aPref, T aValue)
     {
       AssertMainThread();
@@ -808,24 +813,24 @@ private:
   // The constructor cannot access GetSingleton(), since sInstance (necessarily)
   // has not been assigned yet. Follow-up initialization that needs GetSingleton()
   // must be added to Init().
   void Init();
 
   static bool IsPrefsServiceAvailable();
   static bool IsParentProcess();
   // 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 void PrefAddVarCache(std::string*, const char*, std::string);
-  static void PrefAddVarCache(AtomicBool*, const char*, bool);
-  static void PrefAddVarCache(AtomicInt32*, const char*, int32_t);
-  static void PrefAddVarCache(AtomicUint32*, const char*, uint32_t);
+  static void PrefAddVarCache(bool*, const nsACString&, bool);
+  static void PrefAddVarCache(int32_t*, const nsACString&, int32_t);
+  static void PrefAddVarCache(uint32_t*, const nsACString&, uint32_t);
+  static void PrefAddVarCache(float*, const nsACString&, float);
+  static void PrefAddVarCache(std::string*, const nsCString&, std::string);
+  static void PrefAddVarCache(AtomicBool*, const nsACString&, bool);
+  static void PrefAddVarCache(AtomicInt32*, const nsACString&, int32_t);
+  static void PrefAddVarCache(AtomicUint32*, const nsACString&, uint32_t);
   static bool PrefGet(const char*, bool);
   static int32_t PrefGet(const char*, int32_t);
   static uint32_t PrefGet(const char*, uint32_t);
   static float PrefGet(const char*, float);
   static std::string PrefGet(const char*, std::string);
   static void PrefSet(const char* aPref, bool aValue);
   static void PrefSet(const char* aPref, int32_t aValue);
   static void PrefSet(const char* aPref, uint32_t aValue);
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -107,37 +107,37 @@ GetPrefsFor(EventClassID aEventClassID)
   } else {
     return nullptr;
   }
 
   if (!prefs->mRegistered) {
     prefs->mRegistered = true;
 
     nsPrintfCString enabledPref("ui.%s.radius.enabled", prefBranch);
-    Preferences::AddBoolVarCache(&prefs->mEnabled, enabledPref.get(), false);
+    Preferences::AddBoolVarCache(&prefs->mEnabled, enabledPref, false);
 
     nsPrintfCString visitedWeightPref("ui.%s.radius.visitedWeight", prefBranch);
-    Preferences::AddUintVarCache(&prefs->mVisitedWeight, visitedWeightPref.get(), 100);
+    Preferences::AddUintVarCache(&prefs->mVisitedWeight, visitedWeightPref, 100);
 
     static const char prefNames[4][9] =
       { "topmm", "rightmm", "bottommm", "leftmm" };
     for (int32_t i = 0; i < 4; ++i) {
       nsPrintfCString radiusPref("ui.%s.radius.%s", prefBranch, prefNames[i]);
-      Preferences::AddUintVarCache(&prefs->mSideRadii[i], radiusPref.get(), 0);
+      Preferences::AddUintVarCache(&prefs->mSideRadii[i], radiusPref, 0);
     }
 
     if (aEventClassID == eMouseEventClass) {
       Preferences::AddBoolVarCache(&prefs->mTouchOnly,
           "ui.mouse.radius.inputSource.touchOnly", true);
     } else {
       prefs->mTouchOnly = false;
     }
 
     nsPrintfCString repositionPref("ui.%s.radius.reposition", prefBranch);
-    Preferences::AddBoolVarCache(&prefs->mRepositionEventCoords, repositionPref.get(), false);
+    Preferences::AddBoolVarCache(&prefs->mRepositionEventCoords, repositionPref, false);
 
     // These values were formerly set by ui.zoomedview preferences.
     prefs->mTouchClusterDetectionEnabled = false;
     prefs->mSimplifiedClusterDetection = false;
     prefs->mLimitReadableSize = 8;
     prefs->mKeepLimitSizeForCluster = 16;
   }
 
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -121,18 +121,20 @@ nsCSSProps::AddRefTable(void)
       }
     }
 
     static bool prefObserversInited = false;
     if (!prefObserversInited) {
       prefObserversInited = true;
       for (const PropertyPref* pref = kPropertyPrefTable;
            pref->mPropID != eCSSProperty_UNKNOWN; pref++) {
+        nsCString prefName;
+        prefName.AssignLiteral(pref->mPref, strlen(pref->mPref));
         bool* enabled = &gPropertyEnabled[pref->mPropID];
-        Preferences::AddBoolVarCache(enabled, pref->mPref);
+        Preferences::AddBoolVarCache(enabled, prefName);
       }
     }
   }
 }
 
 #undef  DEBUG_SHORTHANDS_CONTAINING
 
 void
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -66,17 +66,17 @@ int8_t nsMenuPopupFrame::sDefaultLevelIs
 DOMTimeStamp nsMenuPopupFrame::sLastKeyTime = 0;
 
 // XXX, kyle.yuan@sun.com, there are 4 definitions for the same purpose:
 //  nsMenuPopupFrame.h, nsListControlFrame.cpp, listbox.xml, tree.xml
 //  need to find a good place to put them together.
 //  if someone changes one, please also change the other.
 uint32_t nsMenuPopupFrame::sTimeoutOfIncrementalSearch = 1000;
 
-const char* kPrefIncrementalSearchTimeout =
+const char kPrefIncrementalSearchTimeout[] =
   "ui.menu.incremental_search.timeout";
 
 // NS_NewMenuPopupFrame
 //
 // Wrapper for creating a new menu popup container
 //
 nsIFrame*
 NS_NewMenuPopupFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle)
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -128,17 +128,17 @@ nsMenuChainItem::CheckForAnchorChange()
 {
   if (mFollowAnchor) {
     mFrame->CheckForAnchorChange(mCurrentRect);
   }
 }
 
 bool nsXULPopupManager::sDevtoolsDisableAutoHide = false;
 
-const char* kPrefDevtoolsDisableAutoHide =
+const char kPrefDevtoolsDisableAutoHide[] =
   "ui.popup.disable_autohide";
 
 NS_IMPL_ISUPPORTS(nsXULPopupManager,
                   nsIDOMEventListener,
                   nsIObserver)
 
 nsXULPopupManager::nsXULPopupManager() :
   mRangeOffset(0),
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -2891,16 +2891,24 @@ AssertNotAlreadyCached(const char* aPref
       aPref,
       aPtr);
     MOZ_ASSERT(false,
                "Should not have an existing pref cache for this address");
   }
 #endif
 }
 
+static void
+AssertNotAlreadyCached(const char* aPrefType,
+                       const nsACString& aPref,
+                       void* aPtr)
+{
+  AssertNotAlreadyCached(aPrefType, PromiseFlatCString(aPref).get(), aPtr);
+}
+
 // Although this is a member of Preferences, it measures sPreferences and
 // several other global structures.
 /* static */ void
 Preferences::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
                                     PrefsSizes& aSizes)
 {
   if (!sPreferences) {
     return;
@@ -4732,23 +4740,23 @@ BoolVarChanged(const char* aPref, void* 
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<bool*>(cache->mCacheLocation) =
     Preferences::GetBool(aPref, cache->mDefaultValueBool);
 }
 
 /* static */ nsresult
 Preferences::AddBoolVarCache(bool* aCache,
-                             const char* aPref,
+                             const nsACString& aPref,
                              bool aDefault,
                              bool aSkipAssignment)
 {
   AssertNotAlreadyCached("bool", aPref, aCache);
   if (!aSkipAssignment) {
-    *aCache = GetBool(aPref, aDefault);
+    *aCache = GetBool(PromiseFlatCString(aPref).get(), aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueBool = aDefault;
   CacheDataAppendElement(data);
   Preferences::RegisterCallback(BoolVarChanged,
                                 aPref,
                                 data,
@@ -4764,23 +4772,23 @@ AtomicBoolVarChanged(const char* aPref, 
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<Atomic<bool, Order>*>(cache->mCacheLocation) =
     Preferences::GetBool(aPref, cache->mDefaultValueBool);
 }
 
 template<MemoryOrdering Order>
 /* static */ nsresult
 Preferences::AddAtomicBoolVarCache(Atomic<bool, Order>* aCache,
-                                   const char* aPref,
+                                   const nsACString& aPref,
                                    bool aDefault,
                                    bool aSkipAssignment)
 {
   AssertNotAlreadyCached("bool", aPref, aCache);
   if (!aSkipAssignment) {
-    *aCache = GetBool(aPref, aDefault);
+    *aCache = GetBool(PromiseFlatCString(aPref).get(), aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueBool = aDefault;
   CacheDataAppendElement(data);
   Preferences::RegisterCallback(AtomicBoolVarChanged<Order>,
                                 aPref,
                                 data,
@@ -4794,23 +4802,23 @@ IntVarChanged(const char* aPref, void* a
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<int32_t*>(cache->mCacheLocation) =
     Preferences::GetInt(aPref, cache->mDefaultValueInt);
 }
 
 /* static */ nsresult
 Preferences::AddIntVarCache(int32_t* aCache,
-                            const char* aPref,
+                            const nsACString& aPref,
                             int32_t aDefault,
                             bool aSkipAssignment)
 {
   AssertNotAlreadyCached("int", aPref, aCache);
   if (!aSkipAssignment) {
-    *aCache = GetInt(aPref, aDefault);
+    *aCache = GetInt(PromiseFlatCString(aPref).get(), aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueInt = aDefault;
   CacheDataAppendElement(data);
   Preferences::RegisterCallback(
     IntVarChanged, aPref, data, Preferences::ExactMatch, /* isPriority */ true);
   return NS_OK;
@@ -4823,23 +4831,23 @@ AtomicIntVarChanged(const char* aPref, v
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<Atomic<int32_t, Order>*>(cache->mCacheLocation) =
     Preferences::GetInt(aPref, cache->mDefaultValueUint);
 }
 
 template<MemoryOrdering Order>
 /* static */ nsresult
 Preferences::AddAtomicIntVarCache(Atomic<int32_t, Order>* aCache,
-                                  const char* aPref,
+                                  const nsACString& aPref,
                                   int32_t aDefault,
                                   bool aSkipAssignment)
 {
   AssertNotAlreadyCached("int", aPref, aCache);
   if (!aSkipAssignment) {
-    *aCache = GetInt(aPref, aDefault);
+    *aCache = GetInt(PromiseFlatCString(aPref).get(), aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueUint = aDefault;
   CacheDataAppendElement(data);
   Preferences::RegisterCallback(AtomicIntVarChanged<Order>,
                                 aPref,
                                 data,
@@ -4853,23 +4861,23 @@ UintVarChanged(const char* aPref, void* 
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<uint32_t*>(cache->mCacheLocation) =
     Preferences::GetUint(aPref, cache->mDefaultValueUint);
 }
 
 /* static */ nsresult
 Preferences::AddUintVarCache(uint32_t* aCache,
-                             const char* aPref,
+                             const nsACString& aPref,
                              uint32_t aDefault,
                              bool aSkipAssignment)
 {
   AssertNotAlreadyCached("uint", aPref, aCache);
   if (!aSkipAssignment) {
-    *aCache = GetUint(aPref, aDefault);
+    *aCache = GetUint(PromiseFlatCString(aPref).get(), aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueUint = aDefault;
   CacheDataAppendElement(data);
   Preferences::RegisterCallback(UintVarChanged,
                                 aPref,
                                 data,
@@ -4885,23 +4893,23 @@ AtomicUintVarChanged(const char* aPref, 
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<Atomic<uint32_t, Order>*>(cache->mCacheLocation) =
     Preferences::GetUint(aPref, cache->mDefaultValueUint);
 }
 
 template<MemoryOrdering Order>
 /* static */ nsresult
 Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Order>* aCache,
-                                   const char* aPref,
+                                   const nsACString& aPref,
                                    uint32_t aDefault,
                                    bool aSkipAssignment)
 {
   AssertNotAlreadyCached("uint", aPref, aCache);
   if (!aSkipAssignment) {
-    *aCache = GetUint(aPref, aDefault);
+    *aCache = GetUint(PromiseFlatCString(aPref).get(), aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueUint = aDefault;
   CacheDataAppendElement(data);
   Preferences::RegisterCallback(AtomicUintVarChanged<Order>,
                                 aPref,
                                 data,
@@ -4910,73 +4918,73 @@ Preferences::AddAtomicUintVarCache(Atomi
   return NS_OK;
 }
 
 // Since the definition of template functions is not in a header file, we
 // need to explicitly specify the instantiations that are required. Currently
 // limited orders are needed and therefore implemented.
 template nsresult
 Preferences::AddAtomicBoolVarCache(Atomic<bool, Relaxed>*,
-                                   const char*,
+                                   const nsACString&,
                                    bool,
                                    bool);
 
 template nsresult
 Preferences::AddAtomicBoolVarCache(Atomic<bool, ReleaseAcquire>*,
-                                   const char*,
+                                   const nsACString&,
                                    bool,
                                    bool);
 
 template nsresult
 Preferences::AddAtomicBoolVarCache(Atomic<bool, SequentiallyConsistent>*,
-                                   const char*,
+                                   const nsACString&,
                                    bool,
                                    bool);
 
 template nsresult
 Preferences::AddAtomicIntVarCache(Atomic<int32_t, Relaxed>*,
-                                  const char*,
+                                  const nsACString&,
                                   int32_t,
                                   bool);
 
 template nsresult
 Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Relaxed>*,
-                                   const char*,
+                                   const nsACString&,
                                    uint32_t,
                                    bool);
 
 template nsresult
 Preferences::AddAtomicUintVarCache(Atomic<uint32_t, ReleaseAcquire>*,
-                                   const char*,
+                                   const nsACString&,
                                    uint32_t,
                                    bool);
 
 template nsresult
 Preferences::AddAtomicUintVarCache(Atomic<uint32_t, SequentiallyConsistent>*,
-                                   const char*,
+                                   const nsACString&,
                                    uint32_t,
                                    bool);
 
 static void
 FloatVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<float*>(cache->mCacheLocation) =
     Preferences::GetFloat(aPref, cache->mDefaultValueFloat);
 }
 
 /* static */ nsresult
 Preferences::AddFloatVarCache(float* aCache,
-                              const char* aPref,
+                              const nsACString& aPref,
                               float aDefault,
                               bool aSkipAssignment)
 {
   AssertNotAlreadyCached("float", aPref, aCache);
   if (!aSkipAssignment) {
-    *aCache = GetFloat(aPref, aDefault);
+    *aCache = GetFloat(PromiseFlatCString(aPref).get(), aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueFloat = aDefault;
   CacheDataAppendElement(data);
   Preferences::RegisterCallback(FloatVarChanged,
                                 aPref,
                                 data,
@@ -5057,105 +5065,107 @@ SetPref_String(const char* aName, const 
                PrefValueKind::Default,
                value,
                /* isSticky */ false,
                /* isLocked */ false,
                /* fromInit */ true);
 }
 
 static void
-InitVarCachePref(const char* aName,
+InitVarCachePref(const nsACString& aName,
                  bool* aCache,
                  bool aDefaultValue,
                  bool aIsStartup)
 {
-  SetPref_bool(aName, aDefaultValue);
+  SetPref_bool(PromiseFlatCString(aName).get(), aDefaultValue);
   *aCache = aDefaultValue;
   if (aIsStartup) {
     Preferences::AddBoolVarCache(aCache, aName, aDefaultValue, true);
   }
 }
 
 template<MemoryOrdering Order>
 static void
-InitVarCachePref(const char* aName,
+InitVarCachePref(const nsACString& aName,
                  Atomic<bool, Order>* aCache,
                  bool aDefaultValue,
                  bool aIsStartup)
 {
-  SetPref_bool(aName, aDefaultValue);
+  SetPref_bool(PromiseFlatCString(aName).get(), aDefaultValue);
   *aCache = aDefaultValue;
   if (aIsStartup) {
     Preferences::AddAtomicBoolVarCache(aCache, aName, aDefaultValue, true);
   }
 }
 
 // XXX: this will eventually become used
 MOZ_MAYBE_UNUSED static void
-InitVarCachePref(const char* aName,
+InitVarCachePref(const nsACString& aName,
                  int32_t* aCache,
                  int32_t aDefaultValue,
                  bool aIsStartup)
 {
-  SetPref_int32_t(aName, aDefaultValue);
+  SetPref_int32_t(PromiseFlatCString(aName).get(), aDefaultValue);
   *aCache = aDefaultValue;
   if (aIsStartup) {
     Preferences::AddIntVarCache(aCache, aName, aDefaultValue, true);
   }
 }
 
 template<MemoryOrdering Order>
 static void
-InitVarCachePref(const char* aName,
+InitVarCachePref(const nsACString& aName,
                  Atomic<int32_t, Order>* aCache,
                  int32_t aDefaultValue,
                  bool aIsStartup)
 {
-  SetPref_int32_t(aName, aDefaultValue);
+  SetPref_int32_t(PromiseFlatCString(aName).get(), aDefaultValue);
   *aCache = aDefaultValue;
   if (aIsStartup) {
     Preferences::AddAtomicIntVarCache(aCache, aName, aDefaultValue, true);
   }
 }
 
 static void
-InitVarCachePref(const char* aName,
+InitVarCachePref(const nsACString& aName,
                  uint32_t* aCache,
                  uint32_t aDefaultValue,
                  bool aIsStartup)
 {
-  SetPref_int32_t(aName, static_cast<int32_t>(aDefaultValue));
+  SetPref_int32_t(PromiseFlatCString(aName).get(),
+                  static_cast<int32_t>(aDefaultValue));
   *aCache = aDefaultValue;
   if (aIsStartup) {
     Preferences::AddUintVarCache(aCache, aName, aDefaultValue, true);
   }
 }
 
 template<MemoryOrdering Order>
 static void
-InitVarCachePref(const char* aName,
+InitVarCachePref(const nsACString& aName,
                  Atomic<uint32_t, Order>* aCache,
                  uint32_t aDefaultValue,
                  bool aIsStartup)
 {
-  SetPref_int32_t(aName, static_cast<int32_t>(aDefaultValue));
+  SetPref_int32_t(PromiseFlatCString(aName).get(),
+                  static_cast<int32_t>(aDefaultValue));
   *aCache = aDefaultValue;
   if (aIsStartup) {
     Preferences::AddAtomicUintVarCache(aCache, aName, aDefaultValue, true);
   }
 }
 
 // XXX: this will eventually become used
 MOZ_MAYBE_UNUSED static void
-InitVarCachePref(const char* aName,
+InitVarCachePref(const nsACString& aName,
                  float* aCache,
                  float aDefaultValue,
                  bool aIsStartup)
 {
-  SetPref_float(aName, aDefaultValue);
+  SetPref_float(PromiseFlatCString(aName).get(), aDefaultValue);
   *aCache = aDefaultValue;
   if (aIsStartup) {
     Preferences::AddFloatVarCache(aCache, aName, aDefaultValue, true);
   }
 }
 
 /* static */ void
 StaticPrefs::InitAll(bool aIsStartup)
@@ -5172,17 +5182,20 @@ StaticPrefs::InitAll(bool aIsStartup)
 //                    aIsStartup);
 //
 // The SetPref_*() functions have a type suffix to avoid ambiguity between
 // prefs having int32_t and float default values. That suffix is not needed for
 // the InitVarCachePref() functions because they take a pointer parameter,
 // which prevents automatic int-to-float coercion.
 #define PREF(name, cpp_type, value) SetPref_##cpp_type(name, value);
 #define VARCACHE_PREF(name, id, cpp_type, value)                               \
-  InitVarCachePref(name, &StaticPrefs::sVarCache_##id, value, aIsStartup);
+  InitVarCachePref(NS_LITERAL_CSTRING(name),                                   \
+                   &StaticPrefs::sVarCache_##id,                               \
+                   value,                                                      \
+                   aIsStartup);
 #include "mozilla/StaticPrefList.h"
 #undef PREF
 #undef VARCACHE_PREF
 }
 
 } // namespace mozilla
 
 #undef ENSURE_PARENT_PROCESS
--- a/modules/libpref/Preferences.h
+++ b/modules/libpref/Preferences.h
@@ -353,47 +353,111 @@ public:
       aCallback, nsLiteralCString(aPref), aClosure, PrefixMatch);
   }
 
   // Adds the aVariable to cache table. |aVariable| must be a pointer for a
   // static variable. The value will be modified when the pref value is changed
   // but note that even if you modified it, the value isn't assigned to the
   // pref.
   static nsresult AddBoolVarCache(bool* aVariable,
-                                  const char* aPref,
+                                  const nsACString& aPref,
                                   bool aDefault = false,
                                   bool aSkipAssignment = false);
   template<MemoryOrdering Order>
   static nsresult AddAtomicBoolVarCache(Atomic<bool, Order>* aVariable,
-                                        const char* aPref,
+                                        const nsACString& aPref,
                                         bool aDefault = false,
                                         bool aSkipAssignment = false);
   static nsresult AddIntVarCache(int32_t* aVariable,
-                                 const char* aPref,
+                                 const nsACString& aPref,
                                  int32_t aDefault = 0,
                                  bool aSkipAssignment = false);
   template<MemoryOrdering Order>
   static nsresult AddAtomicIntVarCache(Atomic<int32_t, Order>* aVariable,
-                                       const char* aPref,
+                                       const nsACString& aPref,
                                        int32_t aDefault = 0,
                                        bool aSkipAssignment = false);
   static nsresult AddUintVarCache(uint32_t* aVariable,
-                                  const char* aPref,
+                                  const nsACString& aPref,
                                   uint32_t aDefault = 0,
                                   bool aSkipAssignment = false);
   template<MemoryOrdering Order>
   static nsresult AddAtomicUintVarCache(Atomic<uint32_t, Order>* aVariable,
-                                        const char* aPref,
+                                        const nsACString& aPref,
                                         uint32_t aDefault = 0,
                                         bool aSkipAssignment = false);
   static nsresult AddFloatVarCache(float* aVariable,
-                                   const char* aPref,
+                                   const nsACString& aPref,
                                    float aDefault = 0.0f,
                                    bool aSkipAssignment = false);
 
+  template<int N>
+  static nsresult AddBoolVarCache(bool* aVariable,
+                                  const char (&aPref)[N],
+                                  bool aDefault = false,
+                                  bool aSkipAssignment = false)
+  {
+    return AddBoolVarCache(
+      aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment);
+  }
+  template<MemoryOrdering Order, int N>
+  static nsresult AddAtomicBoolVarCache(Atomic<bool, Order>* aVariable,
+                                        const char (&aPref)[N],
+                                        bool aDefault = false,
+                                        bool aSkipAssignment = false)
+  {
+    return AddAtomicBoolVarCache<Order>(
+      aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment);
+  }
+  template<int N>
+  static nsresult AddIntVarCache(int32_t* aVariable,
+                                 const char (&aPref)[N],
+                                 int32_t aDefault = 0,
+                                 bool aSkipAssignment = false)
+  {
+    return AddIntVarCache(
+      aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment);
+  }
+  template<MemoryOrdering Order, int N>
+  static nsresult AddAtomicIntVarCache(Atomic<int32_t, Order>* aVariable,
+                                       const char (&aPref)[N],
+                                       int32_t aDefault = 0,
+                                       bool aSkipAssignment = false)
+  {
+    return AddAtomicIntVarCache<Order>(
+      aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment);
+  }
+  template<int N>
+  static nsresult AddUintVarCache(uint32_t* aVariable,
+                                  const char (&aPref)[N],
+                                  uint32_t aDefault = 0,
+                                  bool aSkipAssignment = false)
+  {
+    return AddUintVarCache(
+      aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment);
+  }
+  template<MemoryOrdering Order, int N>
+  static nsresult AddAtomicUintVarCache(Atomic<uint32_t, Order>* aVariable,
+                                        const char (&aPref)[N],
+                                        uint32_t aDefault = 0,
+                                        bool aSkipAssignment = false)
+  {
+    return AddAtomicUintVarCache<Order>(
+      aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment);
+  }
+  template<int N>
+  static nsresult AddFloatVarCache(float* aVariable,
+                                   const char (&aPref)[N],
+                                   float aDefault = 0.0f,
+                                   bool aSkipAssignment = false)
+  {
+    return AddFloatVarCache(
+      aVariable, nsLiteralCString(aPref), aDefault, aSkipAssignment);
+  }
+
   // When a content process is created these methods are used to pass changed
   // prefs in bulk from the parent process, via shared memory.
   static void SerializePreferences(nsCString& aStr);
   static void DeserializePreferences(char* aStr, size_t aPrefsLen);
 
   // When a single pref is changed in the parent process, these methods are
   // used to pass the update to content processes.
   static void GetPreference(dom::Pref* aPref);
--- a/modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
+++ b/modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
@@ -25,115 +25,119 @@ VarChanged(const char* aPrefName, void* 
 {
   auto closure = static_cast<Closure<T, U>*>(aData);
   ASSERT_EQ(*closure->mLocation, closure->mExpected);
   ASSERT_FALSE(closure->mCalled);
   closure->mCalled = true;
 }
 
 void
-SetFunc(const char* aPrefName, bool aValue)
+SetFunc(const nsCString& aPrefName, bool aValue)
 {
-  nsresult rv = Preferences::SetBool(aPrefName, aValue);
+  nsresult rv = Preferences::SetBool(aPrefName.get(), aValue);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-SetFunc(const char* aPrefName, int32_t aValue)
+SetFunc(const nsCString& aPrefName, int32_t aValue)
 {
-  nsresult rv = Preferences::SetInt(aPrefName, aValue);
+  nsresult rv = Preferences::SetInt(aPrefName.get(), aValue);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-SetFunc(const char* aPrefName, uint32_t aValue)
+SetFunc(const nsCString& aPrefName, uint32_t aValue)
 {
-  nsresult rv = Preferences::SetUint(aPrefName, aValue);
+  nsresult rv = Preferences::SetUint(aPrefName.get(), aValue);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-SetFunc(const char* aPrefName, float aValue)
+SetFunc(const nsCString& aPrefName, float aValue)
 {
-  nsresult rv = Preferences::SetFloat(aPrefName, aValue);
+  nsresult rv = Preferences::SetFloat(aPrefName.get(), aValue);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-AddVarCacheFunc(bool* aVar, const char* aPrefName)
+AddVarCacheFunc(bool* aVar, const nsCString& aPrefName)
 {
   nsresult rv = Preferences::AddBoolVarCache(aVar, aPrefName);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-AddVarCacheFunc(Atomic<bool, Relaxed>* aVar, const char* aPrefName)
+AddVarCacheFunc(Atomic<bool, Relaxed>* aVar, const nsCString& aPrefName)
 {
   nsresult rv = Preferences::AddAtomicBoolVarCache(aVar, aPrefName);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-AddVarCacheFunc(Atomic<bool, ReleaseAcquire>* aVar, const char* aPrefName)
+AddVarCacheFunc(Atomic<bool, ReleaseAcquire>* aVar, const nsCString& aPrefName)
 {
   nsresult rv = Preferences::AddAtomicBoolVarCache(aVar, aPrefName);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-AddVarCacheFunc(int32_t* aVar, const char* aPrefName)
+AddVarCacheFunc(int32_t* aVar, const nsCString& aPrefName)
 {
   nsresult rv = Preferences::AddIntVarCache(aVar, aPrefName);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-AddVarCacheFunc(Atomic<int32_t, Relaxed>* aVar, const char* aPrefName)
+AddVarCacheFunc(Atomic<int32_t, Relaxed>* aVar, const nsCString& aPrefName)
 {
   nsresult rv = Preferences::AddAtomicIntVarCache(aVar, aPrefName);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-AddVarCacheFunc(uint32_t* aVar, const char* aPrefName)
+AddVarCacheFunc(uint32_t* aVar, const nsCString& aPrefName)
 {
   nsresult rv = Preferences::AddUintVarCache(aVar, aPrefName);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-AddVarCacheFunc(Atomic<uint32_t, Relaxed>* aVar, const char* aPrefName)
+AddVarCacheFunc(Atomic<uint32_t, Relaxed>* aVar, const nsCString& aPrefName)
 {
   nsresult rv = Preferences::AddAtomicUintVarCache(aVar, aPrefName);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-AddVarCacheFunc(Atomic<uint32_t, ReleaseAcquire>* aVar, const char* aPrefName)
+AddVarCacheFunc(Atomic<uint32_t, ReleaseAcquire>* aVar,
+                const nsCString& aPrefName)
 {
   nsresult rv = Preferences::AddAtomicUintVarCache(aVar, aPrefName);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 void
-AddVarCacheFunc(float* aVar, const char* aPrefName)
+AddVarCacheFunc(float* aVar, const nsCString& aPrefName)
 {
   nsresult rv = Preferences::AddFloatVarCache(aVar, aPrefName);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 }
 
 template<typename T, typename U = T>
 void
-RunTest(const char* aPrefName1, const char* aPrefName2, T aValue1, T aValue2)
+RunTest(const nsCString& aPrefName1,
+        const nsCString& aPrefName2,
+        T aValue1,
+        T aValue2)
 {
   static U var1, var2;
   static Closure<T, U> closure1, closure2;
   nsresult rv;
 
-  ASSERT_STRNE(aPrefName1, aPrefName2);
+  ASSERT_STRNE(aPrefName1.get(), aPrefName2.get());
   ASSERT_NE(aValue1, aValue2);
 
   // Call Add*VarCache first.
 
   SetFunc(aPrefName1, aValue1);
 
   AddVarCacheFunc(&var1, aPrefName1);
   ASSERT_EQ(var1, aValue1);
@@ -161,57 +165,84 @@ RunTest(const char* aPrefName1, const ch
   ASSERT_FALSE(closure2.mCalled);
   SetFunc(aPrefName2, aValue2);
   ASSERT_EQ(var2, aValue2);
   ASSERT_TRUE(closure2.mCalled);
 }
 
 TEST(CallbackAndVarCacheOrder, Bool)
 {
-  RunTest<bool>("test_pref.bool.1", "test_pref.bool.2", false, true);
+  RunTest<bool>(NS_LITERAL_CSTRING("test_pref.bool.1"),
+                NS_LITERAL_CSTRING("test_pref.bool.2"),
+                false,
+                true);
 }
 
 TEST(CallbackAndVarCacheOrder, AtomicBoolRelaxed)
 {
   RunTest<bool, Atomic<bool, Relaxed>>(
-    "test_pref.atomic_bool.1", "test_pref.atomic_bool.2", false, true);
+    NS_LITERAL_CSTRING("test_pref.atomic_bool.1"),
+    NS_LITERAL_CSTRING("test_pref.atomic_bool.2"),
+    false,
+    true);
 }
 
 TEST(CallbackAndVarCacheOrder, AtomicBoolReleaseAcquire)
 {
   RunTest<bool, Atomic<bool, ReleaseAcquire>>(
-    "test_pref.atomic_bool.3", "test_pref.atomic_bool.4", false, true);
+    NS_LITERAL_CSTRING("test_pref.atomic_bool.3"),
+    NS_LITERAL_CSTRING("test_pref.atomic_bool.4"),
+    false,
+    true);
 }
 
 TEST(CallbackAndVarCacheOrder, Int)
 {
-  RunTest<int32_t>("test_pref.int.1", "test_pref.int.2", -2, 3);
+  RunTest<int32_t>(NS_LITERAL_CSTRING("test_pref.int.1"),
+                   NS_LITERAL_CSTRING("test_pref.int.2"),
+                   -2,
+                   3);
 }
 
 TEST(CallbackAndVarCacheOrder, AtomicInt)
 {
   RunTest<int32_t, Atomic<int32_t, Relaxed>>(
-    "test_pref.atomic_int.1", "test_pref.atomic_int.2", -3, 4);
+    NS_LITERAL_CSTRING("test_pref.atomic_int.1"),
+    NS_LITERAL_CSTRING("test_pref.atomic_int.2"),
+    -3,
+    4);
 }
 
 TEST(CallbackAndVarCacheOrder, Uint)
 {
-  RunTest<uint32_t>("test_pref.uint.1", "test_pref.uint.2", 4u, 5u);
+  RunTest<uint32_t>(NS_LITERAL_CSTRING("test_pref.uint.1"),
+                    NS_LITERAL_CSTRING("test_pref.uint.2"),
+                    4u,
+                    5u);
 }
 
 TEST(CallbackAndVarCacheOrder, AtomicUintRelaxed)
 {
   RunTest<uint32_t, Atomic<uint32_t, Relaxed>>(
-    "test_pref.atomic_uint.1", "test_pref.atomic_uint.2", 6u, 7u);
+    NS_LITERAL_CSTRING("test_pref.atomic_uint.1"),
+    NS_LITERAL_CSTRING("test_pref.atomic_uint.2"),
+    6u,
+    7u);
 }
 
 TEST(CallbackAndVarCacheOrder, AtomicUintReleaseAcquire)
 {
   RunTest<uint32_t, Atomic<uint32_t, ReleaseAcquire>>(
-    "test_pref.atomic_uint.3", "test_pref.atomic_uint.4", 8u, 9u);
+    NS_LITERAL_CSTRING("test_pref.atomic_uint.3"),
+    NS_LITERAL_CSTRING("test_pref.atomic_uint.4"),
+    8u,
+    9u);
 }
 
 TEST(CallbackAndVarCacheOrder, Float)
 {
-  RunTest<float>("test_pref.float.1", "test_pref.float.2", -10.0f, 11.0f);
+  RunTest<float>(NS_LITERAL_CSTRING("test_pref.float.1"),
+                 NS_LITERAL_CSTRING("test_pref.float.2"),
+                 -10.0f,
+                 11.0f);
 }
 
 } // namespace mozilla