Bug 1472523: Part 2 - Avoid unnecessary string copies in preference caches. r=njn
authorKris Maglione <maglione.k@gmail.com>
Sat, 30 Jun 2018 23:07:30 -0700
changeset 480245 4e2ddd1d83f11fd222f26a64c6b7c7eea9e6ff93
parent 480244 aedd8cf3e783b0d982ed92d01c6996327a71f1cb
child 480246 506cb0a8e4e278ef54f6e741ca226b8e32d86af9
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1472523
milestone63.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 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();
@@ -807,24 +812,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