Bug 1561216 - Change `StaticPrefs` from a class to a namespace. r=froydnj
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 25 Jun 2019 10:36:59 +1000
changeset 542955 f6e047701cf4fb248bd6df4c54172277fca6b150
parent 542954 7f8969072f732c9ae3e83d69c09975282a57a001
child 542956 07314de37ce5ffe85657614b2d48e55a02eb5d4d
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1561216
milestone69.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 1561216 - Change `StaticPrefs` from a class to a namespace. r=froydnj This doesn't change the way C++ code uses static prefs. But it does slightly change how Rust code uses static prefs, specifically the name generated by bindgen is slightly different. The commit also improves some comments. Differential Revision: https://phabricator.services.mozilla.com/D35764
layout/style/ServoBindings.toml
modules/libpref/Preferences.cpp
modules/libpref/StaticPrefs.h
servo/components/style/font_face.rs
servo/components/style/gecko/media_queries.rs
servo/components/style/gecko/pseudo_element_definition.mako.rs
servo/components/style/gecko/selector_parser.rs
servo/components/style/media_queries/media_feature_expression.rs
servo/components/style/properties/cascade.rs
servo/components/style/stylesheets/document_rule.rs
servo/components/style/stylesheets/supports_rule.rs
servo/components/style/values/generics/easing.rs
servo/components/style/values/generics/text.rs
servo/components/style/values/specified/basic_shape.rs
servo/components/style/values/specified/box.rs
servo/components/style/values/specified/grid.rs
servo/components/style/values/specified/svg.rs
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -158,16 +158,17 @@ whitelist-vars = [
     "kNameSpaceID_.*",
     "kGenericFont_.*",
     "kPresContext_.*",
     "nsContentUtils_.*",
     "GECKO_IS_NIGHTLY",
     "mozilla::detail::gGkAtoms",
     "mozilla::detail::kGkAtomsArrayOffset",
     "mozilla::profiler::detail::RacyFeatures::sActiveAndFeatures",
+    "mozilla::StaticPrefs::.*",
 ]
 # TODO(emilio): A bunch of types here can go away once we generate bindings and
 # structs together.
 whitelist-types = [
     "RawGecko.*",
     "RawServo.*",
     "ServoCssRules",
     "nsFontFaceRuleContainer",
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -3698,16 +3698,26 @@ void Preferences::DeserializePreferences
   MOZ_ASSERT(p == aStr + aPrefsLen - 1);
 
 #ifdef DEBUG
   MOZ_ASSERT(!gContentProcessPrefsAreInited);
   gContentProcessPrefsAreInited = true;
 #endif
 }
 
+// Forward declarations.
+namespace StaticPrefs {
+
+static void InitAll(bool aIsStartup);
+static void InitOncePrefs();
+static void InitStaticPrefsFromShared();
+static void RegisterOncePrefs(SharedPrefMapBuilder& aBuilder);
+
+}  // namespace StaticPrefs
+
 /* static */
 FileDescriptor Preferences::EnsureSnapshot(size_t* aSize) {
   MOZ_ASSERT(XRE_IsParentProcess());
 
   if (!gSharedMap) {
     SharedPrefMapBuilder builder;
 
     for (auto iter = gHashTable->iter(); !iter.done(); iter.next()) {
@@ -4478,23 +4488,34 @@ Result<Ok, const char*> Preferences::Ini
   // Initialize static prefs before prefs from data files so that the latter
   // will override the former.
   StaticPrefs::InitAll(aIsStartup);
 
   if (!XRE_IsParentProcess()) {
     MOZ_DIAGNOSTIC_ASSERT(gSharedMap);
 
 #ifdef DEBUG
-    // Check that all varcache preferences match their current values. This
-    // can currently fail if the default value of a static varcache preference
-    // is changed in a preference file or at runtime, rather than in
-    // StaticPrefList.h.
-    // StaticPrefs with a Skip policy aren't updated with an overridden value,
-    // and shouldn't be checked.
-
+    // For a VarCache pref like this:
+    //
+    //   VARCACHE_PREF($POLICY, "my.pref", my_pref, int32_t, 99)
+    //
+    // we generate checking code like this:
+    //
+    //   MOZ_ASSERT(StaticPrefs::UpdatePolicy::$POLICY ==
+    //                StaticPrefs::UpdatePolicy::Skip ||
+    //              PreferencesInternalMethods::GetPref<int32_t>(name, value) ==
+    //              StaticPrefs::my_pref(),
+    //              "Incorrect cached value for my.pref");
+    //
+    // This checks that all VarCache preferences match their current values.
+    // This can currently fail if the default value of a static VarCache
+    // preference is changed in a preference file or at runtime, rather than in
+    // StaticPrefList_*.h. StaticPrefs with a Skip policy aren't updated with
+    // an overridden value, and shouldn't be checked.
+    //
 #  define PREF(name, cpp_type, value)
 #  define VARCACHE_PREF(policy, name, id, cpp_type, value)                     \
     MOZ_ASSERT(StaticPrefs::UpdatePolicy::policy ==                            \
                        StaticPrefs::UpdatePolicy::Skip ||                      \
                    PreferencesInternalMethods::GetPref<StripAtomic<cpp_type>>( \
                        name, value) == StaticPrefs::id(),                      \
                "Incorrect cached value for " name);
 #  include "mozilla/StaticPrefList.h"
@@ -5383,18 +5404,19 @@ static void InitVarCachePref(StaticPrefs
       MOZ_LIKELY(aIsStartup)) {
     AddVarCache(aCache, aName, aDefaultValue, true);
   }
 }
 
 static Atomic<bool> sOncePrefRead(false);
 static StaticMutex sOncePrefMutex;
 
-/* static */
-void StaticPrefs::MaybeInitOncePrefs() {
+namespace StaticPrefs {
+
+void MaybeInitOncePrefs() {
   if (MOZ_LIKELY(sOncePrefRead)) {
     // `Once` StaticPrefs have already been initialized to their default value.
     return;
   }
   StaticMutexAutoLock lock(sOncePrefMutex);
   if (NS_IsMainThread()) {
     InitOncePrefs();
   } else {
@@ -5402,129 +5424,122 @@ void StaticPrefs::MaybeInitOncePrefs() {
         "Preferences::MaybeInitOncePrefs", [&]() { InitOncePrefs(); });
     // This logic needs to run on the main thread
     SyncRunnable::DispatchToThread(
         SystemGroup::EventTargetFor(TaskCategory::Other), runnable);
   }
   sOncePrefRead = true;
 }
 
-// For a VarCache pref like this:
+// For a pref like this:
 //
-//   VARCACHE_PREF(Once, "my.varcache", my_varcache, int32_t, 99)
-//
-// we generate a static variable definition and a setter like:
+//   VARCACHE_PREF($POLICY, "my.pref", my_pref, int32_t, 99)
 //
-//   int32_t StaticPrefs::sVarCache_my_varcache(99);
-//   int32_t StaticPrefs::my_varcache() {
-//     if (UpdatePolicy::Skip != UpdatePolicy::Once) {
-//       return sVarCache_myvarcache;
-//     }
-//     MaybeInitOncePrefs();
-//     return sVarCache_myvarcache;
-//   }
-
+// we generate a variable definition like this:
+//
+//   int32_t sVarCache_my_pref(99);
+//
 #define PREF(name, cpp_type, value)
 #define VARCACHE_PREF(policy, name, id, cpp_type, default_value) \
-  cpp_type StaticPrefs::sVarCache_##id(default_value);
+  cpp_type sVarCache_##id(default_value);
 #include "mozilla/StaticPrefList.h"
 #undef PREF
 #undef VARCACHE_PREF
 
-/* static */
-void StaticPrefs::InitAll(bool aIsStartup) {
+static void InitAll(bool aIsStartup) {
+  bool isParent = XRE_IsParentProcess();
+
   // For prefs like these:
   //
   //   PREF("foo.bar.baz", bool, true)
-  //   VARCACHE_PREF(Live, "my.varcache", my_varcache, int32_t, 99)
+  //   VARCACHE_PREF($POLICY, "my.pref", my_pref, int32_t, 99)
   //
-  // we generate registration calls:
+  // we generate registration calls like this:
   //
-  //   if (isParent)
+  //   if (isParent) {
   //     SetPref_bool("foo.bar.baz", true);
-  //   InitVarCachePref(StaticPrefs::UpdatePolicy::Live, "my.varcache",
-  //                    &StaticPrefs::sVarCache_my_varcache, 99, aIsStartup,
-  //                    isParent);
+  //   }
+  //   InitVarCachePref(UpdatePolicy::Live, "my.pref", &sVarCache_my_pref,
+  //                    99, aIsStartup, isParent);
   //
   // 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.
   //
   // In content processes, we rely on the parent to send us the correct initial
   // values via shared memory, so we do not re-initialize them here.
-  bool isParent = XRE_IsParentProcess();
-#define PREF(name, cpp_type, value) \
-  if (isParent) SetPref_##cpp_type(name, value);
-#define VARCACHE_PREF(policy, name, id, cpp_type, value)                   \
-  InitVarCachePref(StaticPrefs::UpdatePolicy::policy,                      \
-                   NS_LITERAL_CSTRING(name), &StaticPrefs::sVarCache_##id, \
-                   value, aIsStartup, isParent);
+#define PREF(name, cpp_type, value)  \
+  if (isParent) {                    \
+    SetPref_##cpp_type(name, value); \
+  }
+#define VARCACHE_PREF(policy, name, id, cpp_type, value)           \
+  InitVarCachePref(UpdatePolicy::policy, NS_LITERAL_CSTRING(name), \
+                   &sVarCache_##id, value, aIsStartup, isParent);
 #include "mozilla/StaticPrefList.h"
 #undef PREF
 #undef VARCACHE_PREF
 }
 
-/* static */
-void StaticPrefs::InitOncePrefs() {
-  // For prefs like these:
+static void InitOncePrefs() {
+  // For a pref like this:
   //
-  //   VARCACHE_PREF(Skip, "my.varcache", my_varcache, int32_t, 99)
+  //   VARCACHE_PREF($POLICY, "my.pref", my_pref, int32_t, 99)
   //
-  // we generate registration calls:
+  // we generate an initialization (in a non-DEBUG build) like this:
   //
-  //   if (UpdatePolicy::Skip == UpdatePolicy::Once) {
-  //     StaticPrefs::sVarCache_my_varcache =
-  //         PreferencesInternalMethods::GetPref("my.varcache",
-  //                                             StripAtomic<int32_t>(99));
+  //   if (UpdatePolicy::$POLICY == UpdatePolicy::Once) {
+  //     sVarCache_my_pref = PreferencesInternalMethods::GetPref("my.pref", 99);
   //   }
   //
   // This is done to get the potentially updated Preference value as we didn't
   // register a callback method for the `Once` policy.
   //
   // On debug build, we also install a mechanism that allows to check if the
   // original Preference is being modified once `Once` StaticPrefs have been
   // initialized as this would indicate a likely misuse of `Once` StaticPrefs
   // and that maybe instead they should have been made `Live`.
+  //
 #define PREF(name, cpp_type, value)
 #ifdef DEBUG
-#  define VARCACHE_PREF(policy, name, id, cpp_type, value)                    \
-    if (UpdatePolicy::policy == UpdatePolicy::Once) {                         \
-      MOZ_ASSERT(gOnceStaticPrefsAntiFootgun);                                \
-      StaticPrefs::sVarCache_##id = PreferencesInternalMethods::GetPref(      \
-          name, StripAtomic<cpp_type>(value));                                \
-      auto checkPref = [&]() {                                                \
-        MOZ_ASSERT(sOncePrefRead);                                            \
-        StripAtomic<cpp_type> staticPrefValue = StaticPrefs::id();            \
-        StripAtomic<cpp_type> preferenceValue =                               \
-            PreferencesInternalMethods::GetPref(                              \
-                StaticPrefs::Get##id##PrefName(),                             \
-                StripAtomic<cpp_type>(value));                                \
-        MOZ_ASSERT(                                                           \
-            staticPrefValue == preferenceValue,                               \
-            "Preference '" name "' got modified since StaticPrefs::" #id      \
-            " got initialized. Consider using a `Live` StaticPrefs instead"); \
-      };                                                                      \
-      gOnceStaticPrefsAntiFootgun->insert(                                    \
-          std::pair<const char*, AntiFootgunCallback>(Get##id##PrefName(),    \
-                                                      std::move(checkPref))); \
+#  define VARCACHE_PREF(policy, name, id, cpp_type, value)                     \
+    if (UpdatePolicy::policy == UpdatePolicy::Once) {                          \
+      MOZ_ASSERT(gOnceStaticPrefsAntiFootgun);                                 \
+      sVarCache_##id = PreferencesInternalMethods::GetPref(                    \
+          name, StripAtomic<cpp_type>(value));                                 \
+      auto checkPref = [&]() {                                                 \
+        MOZ_ASSERT(sOncePrefRead);                                             \
+        StripAtomic<cpp_type> staticPrefValue = id();                          \
+        StripAtomic<cpp_type> preferenceValue =                                \
+            PreferencesInternalMethods::GetPref(Get##id##PrefName(),           \
+                                                StripAtomic<cpp_type>(value)); \
+        MOZ_ASSERT(                                                            \
+            staticPrefValue == preferenceValue,                                \
+            "Preference '" name "' got modified since StaticPrefs::" #id       \
+            " got initialized. Consider using a `Live` StaticPrefs instead");  \
+      };                                                                       \
+      gOnceStaticPrefsAntiFootgun->insert(                                     \
+          std::pair<const char*, AntiFootgunCallback>(Get##id##PrefName(),     \
+                                                      std::move(checkPref)));  \
     }
 #else
-#  define VARCACHE_PREF(policy, name, id, cpp_type, value)               \
-    if (UpdatePolicy::policy == UpdatePolicy::Once) {                    \
-      StaticPrefs::sVarCache_##id = PreferencesInternalMethods::GetPref( \
-          name, StripAtomic<cpp_type>(value));                           \
+#  define VARCACHE_PREF(policy, name, id, cpp_type, value)  \
+    if (UpdatePolicy::policy == UpdatePolicy::Once) {       \
+      sVarCache_##id = PreferencesInternalMethods::GetPref( \
+          name, StripAtomic<cpp_type>(value));              \
     }
 #endif
 
 #include "mozilla/StaticPrefList.h"
 #undef PREF
 #undef VARCACHE_PREF
 }
 
+}  // namespace StaticPrefs
+
 static MOZ_MAYBE_UNUSED void SaveOncePrefToSharedMap(
     SharedPrefMapBuilder& aBuilder, const char* aName, bool aValue) {
   auto oncePref = MakeUnique<Pref>(aName);
   oncePref->SetType(PrefType::Bool);
   oncePref->SetIsSkippedByIteration(true);
   bool valueChanged = false;
   MOZ_ALWAYS_SUCCEEDS(
       oncePref->SetDefaultValue(PrefType::Bool, PrefValue(aValue),
@@ -5566,77 +5581,76 @@ static MOZ_MAYBE_UNUSED void SaveOncePre
       oncePref->SetDefaultValue(PrefType::String, PrefValue(flat.get()),
                                 /* isSticky */ true,
                                 /* isLocked */ true, &valueChanged));
   oncePref->AddToMap(aBuilder);
 }
 
 #define ONCE_PREF_NAME(name) ("$$$" name "$$$")
 
-/* static */
-void StaticPrefs::RegisterOncePrefs(SharedPrefMapBuilder& aBuilder) {
+namespace StaticPrefs {
+
+static void RegisterOncePrefs(SharedPrefMapBuilder& aBuilder) {
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_DIAGNOSTIC_ASSERT(!gSharedMap,
                         "Must be called before gSharedMap has been created");
   MaybeInitOncePrefs();
-  // For prefs like these:
+
+  // For a pref like this:
   //
-  //   VARCACHE_PREF(Once, "my.varcache", my_varcache, int32_t, 99)
-  //   (Other StaticPrefs policies are ignored)
+  //   VARCACHE_PREF($POLICY, "my.pref", my_pref, int32_t, 99)
   //
-  // we generate registration calls:
+  // we generate a save call like this:
   //
-  //   if (UpdatePolicy::Once == UpdatePolicy::Once) {
-  //     SaveOncePrefToSharedMap(aBuilder, ONCE_PREF_NAME(my.varcache),
-  //                             sVarCache_myvarcache);
+  //   if (UpdatePolicy::$POLICY == UpdatePolicy::Once) {
+  //     SaveOncePrefToSharedMap(aBuilder, ONCE_PREF_NAME(my.pref),
+  //                             sVarCache_my_pref);
   //   }
   //
   // `Once` StaticPrefs values will be stored in a hidden and locked preferences
   // in the global SharedPreferenceMap. In order for those preferences to be
   // hidden and not appear in about:config nor ever be stored to disk, we add
   // the "$$$" prefix and suffix to the preference name and set the IsVisible
   // flag to false.
-
+  //
 #define PREF(name, cpp_type, value)
 #define VARCACHE_PREF(policy, name, id, cpp_type, value)            \
   if (UpdatePolicy::policy == UpdatePolicy::Once) {                 \
     SaveOncePrefToSharedMap(aBuilder, ONCE_PREF_NAME(name),         \
                             StripAtomic<cpp_type>(sVarCache_##id)); \
   }
 #include "mozilla/StaticPrefList.h"
 #undef PREF
 #undef VARCACHE_PREF
 }
 
-/* static */
-void StaticPrefs::InitStaticPrefsFromShared() {
+static void InitStaticPrefsFromShared() {
   MOZ_ASSERT(!XRE_IsParentProcess());
   MOZ_DIAGNOSTIC_ASSERT(gSharedMap,
                         "Must be called once gSharedMap has been created");
-  // For prefs like these:
+
+  // For a prefs like this:
   //
-  //   VARCACHE_PREF(Once, "my.varcache", my_varcache, int32_t, 99)
-  //   (Other StaticPrefs policies are ignored).
+  //   VARCACHE_PREF($POLICY, "my.pref", my_pref, int32_t, 99)
   //
-  // we generate registration calls:
+  // we generate an initialization like this:
   //
-  //   if (UpdatePolicy::Once != UpdatePolicy::Skip) {
+  //   if (UpdatePolicy::$POLICY != UpdatePolicy::Skip) {
   //     int32_t val;
   //     nsresult rv;
-  //     if (UpdatePolicy::Once == UpdatePolicy::Once) {
+  //     if (UpdatePolicy::$POLICY == UpdatePolicy::Once) {
   //       rv = PreferencesInternalMethods::GetSharedPrefValue(
-  //           "$$$my.varcache$$$", &val);
+  //              "$$$my.pref$$$", &val);
   //     } else if (UpdatePolicy::Once == UpdatePolicy::Live) {
-  //       rv = PreferencesInternalMethods::GetSharedPrefValue(
-  //           "my.varcache", &val);
+  //       rv = PreferencesInternalMethods::GetSharedPrefValue("my.pref", &val);
   //     }
   //     MOZ_DIAGNOSTIC_ALWAYS_TRUE(NS_SUCCEEDED(rv));
-  //     StaticPrefs::sVarCache_my_varcache = val;
+  //     sVarCache_my_pref = val;
   //   }
-
+  //
 #define PREF(name, cpp_type, value)
 #define VARCACHE_PREF(policy, name, id, cpp_type, value)               \
   if (UpdatePolicy::policy != UpdatePolicy::Skip) {                    \
     StripAtomic<cpp_type> val;                                         \
     nsresult rv;                                                       \
     if (UpdatePolicy::policy == UpdatePolicy::Once) {                  \
       rv = PreferencesInternalMethods::GetSharedPrefValue(             \
           ONCE_PREF_NAME(name), &val);                                 \
@@ -5644,22 +5658,25 @@ void StaticPrefs::InitStaticPrefsFromSha
       rv = PreferencesInternalMethods::GetSharedPrefValue(name, &val); \
     }                                                                  \
     MOZ_DIAGNOSTIC_ALWAYS_TRUE(NS_SUCCEEDED(rv));                      \
     StaticPrefs::sVarCache_##id = val;                                 \
   }
 #include "mozilla/StaticPrefList.h"
 #undef PREF
 #undef VARCACHE_PREF
+
   // `Once` StaticPrefs have been set to their value in the step above and
   // outside the parent process they are immutable. So we set sOncePrefRead
   // so that we can directly skip any lazy initializations.
   sOncePrefRead = true;
 }
 
+}  // namespace StaticPrefs
+
 }  // namespace mozilla
 
 #undef ENSURE_PARENT_PROCESS
 
 //===========================================================================
 // Module and factory stuff
 //===========================================================================
 
--- a/modules/libpref/StaticPrefs.h
+++ b/modules/libpref/StaticPrefs.h
@@ -64,72 +64,67 @@ template <typename T>
 struct IsAtomic : FalseType {};
 
 template <typename T, MemoryOrdering Order>
 struct IsAtomic<Atomic<T, Order>> : TrueType {};
 
 template <typename T>
 struct IsAtomic<std::atomic<T>> : TrueType {};
 
-class StaticPrefs {
-  // For a VarCache pref like this:
-  //
-  //   VARCACHE_PREF("my.varcache", my_varcache, int32_t, 99)
-  //
-  // we generate a static variable declaration, a getter and a setter
-  // definition. A StaticPref can be set by using the corresponding Set method.
-  // For example, if the accessor is Foo() then calling SetFoo(...) will update
-  // the preference and also change the return value of subsequent Foo() calls.
-  // Changing StaticPrefs is only allowed on the parent process' main thread.
-  //
-  //   private:
-  //     static int32_t sVarCache_my_varcache;
-  //   public:
-  //     static int32_t my_varcache();
-  //     static const char* Getmy_varcachePrefName() { return "my.varcache"; }
-  //     static int32_t Getmy_varcachePrefDefault() { return 99; }
-  //
+namespace StaticPrefs {
+
+// 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.
+};
+
+void MaybeInitOncePrefs();
 
- public:
-  // 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.
-  };
-
-#define PREF(str, cpp_type, default_value)
-#define VARCACHE_PREF(policy, str, id, cpp_type, default_value) \
- private:                                                       \
-  static cpp_type sVarCache_##id;                               \
-                                                                \
- public:                                                        \
-  static StripAtomic<cpp_type> id() {                           \
-    if (UpdatePolicy::policy != UpdatePolicy::Once) {           \
-      MOZ_DIAGNOSTIC_ASSERT(                                    \
-          UpdatePolicy::policy == UpdatePolicy::Skip ||         \
-              IsAtomic<cpp_type>::value || NS_IsMainThread(),   \
-          "Non-atomic static pref '" str                        \
-          "' being accessed on background thread by getter");   \
-      return sVarCache_##id;                                    \
-    }                                                           \
-    MaybeInitOncePrefs();                                       \
-    return sVarCache_##id;                                      \
-  }                                                             \
-  static const char* Get##id##PrefName() { return str; }        \
-  static StripAtomic<cpp_type> Get##id##PrefDefault() { return default_value; }
+// For a VarCache pref like this:
+//
+//   VARCACHE_PREF($POLICY, "my.pref", my_pref, int32_t, 99)
+//
+// we generate an extern variable declaration and three getter
+// declarations/definitions.
+//
+//     extern int32_t sVarCache_my_pref;
+//     inline int32_t my_pref() {
+//       if (UpdatePolicy::$POLICY != UpdatePolicy::Once) {
+//         return sVarCache_my_pref;
+//       }
+//       MaybeInitOncePrefs();
+//       return sVarCache_my_pref();
+//     }
+//     inline const char* Getmy_prefPrefName() { return "my.pref"; }
+//     inline int32_t Getmy_prefPrefDefault() { return 99; }
+//
+// The extern declaration of the variable is necessary for bindgen to see it
+// and generate Rust bindings.
+//
+#define PREF(name, cpp_type, default_value)
+#define VARCACHE_PREF(policy, name, id, cpp_type, default_value) \
+  extern cpp_type sVarCache_##id;                                \
+  inline StripAtomic<cpp_type> id() {                            \
+    if (UpdatePolicy::policy != UpdatePolicy::Once) {            \
+      MOZ_DIAGNOSTIC_ASSERT(                                     \
+          UpdatePolicy::policy == UpdatePolicy::Skip ||          \
+              IsAtomic<cpp_type>::value || NS_IsMainThread(),    \
+          "Non-atomic static pref '" name                        \
+          "' being accessed on background thread by getter");    \
+      return sVarCache_##id;                                     \
+    }                                                            \
+    MaybeInitOncePrefs();                                        \
+    return sVarCache_##id;                                       \
+  }                                                              \
+  inline const char* Get##id##PrefName() { return name; }        \
+  inline StripAtomic<cpp_type> Get##id##PrefDefault() { return default_value; }
 
 #include "mozilla/StaticPrefList.h"
 #undef PREF
 #undef VARCACHE_PREF
 
- private:
-  friend class Preferences;
-  static void InitAll(bool aIsStartup);
-  static void MaybeInitOncePrefs();
-  static void InitOncePrefs();
-  static void InitStaticPrefsFromShared();
-  static void RegisterOncePrefs(SharedPrefMapBuilder& aBuilder);
-};
+}  // namespace StaticPrefs
 
 }  // namespace mozilla
 
 #endif  // mozilla_StaticPrefs_h
--- a/servo/components/style/font_face.rs
+++ b/servo/components/style/font_face.rs
@@ -411,23 +411,23 @@ impl Parse for Source {
         }))
     }
 }
 
 macro_rules! is_descriptor_enabled {
     ("font-display") => {
         unsafe {
             use crate::gecko_bindings::structs::mozilla;
-            mozilla::StaticPrefs_sVarCache_layout_css_font_display_enabled
+            mozilla::StaticPrefs::sVarCache_layout_css_font_display_enabled
         }
     };
     ("font-variation-settings") => {
         unsafe {
             use crate::gecko_bindings::structs::mozilla;
-            mozilla::StaticPrefs_sVarCache_layout_css_font_variations_enabled != 0
+            mozilla::StaticPrefs::sVarCache_layout_css_font_variations_enabled != 0
         }
     };
     ($name:tt) => {
         true
     };
 }
 
 macro_rules! font_face_descriptors_common {
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -266,17 +266,17 @@ impl Device {
     /// Returns whether document colors are enabled.
     #[inline]
     pub fn use_document_colors(&self) -> bool {
         let doc = self.document();
         if doc.mIsBeingUsedAsImage() {
             return true;
         }
         let document_color_use =
-            unsafe { structs::StaticPrefs_sVarCache_browser_display_document_color_use };
+            unsafe { structs::StaticPrefs::sVarCache_browser_display_document_color_use };
         let prefs = self.pref_sheet_prefs();
         match document_color_use {
             1 => true,
             2 => prefs.mIsChrome,
             _ => !prefs.mUseAccessibilityTheme,
         }
     }
 
--- a/servo/components/style/gecko/pseudo_element_definition.mako.rs
+++ b/servo/components/style/gecko/pseudo_element_definition.mako.rs
@@ -107,17 +107,17 @@ impl PseudoElement {
 
     /// Gets the flags associated to this pseudo-element, or 0 if it's an
     /// anonymous box.
     pub fn flags(&self) -> u32 {
         match *self {
             % for pseudo in PSEUDOS:
                 ${pseudo_element_variant(pseudo)} =>
                 % if pseudo.is_tree_pseudo_element():
-                    if unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_tree_pseudos_content_enabled } {
+                    if unsafe { structs::StaticPrefs::sVarCache_layout_css_xul_tree_pseudos_content_enabled } {
                         0
                     } else {
                         structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME
                     },
                 % elif pseudo.is_anon_box():
                     structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS,
                 % else:
                     structs::SERVO_CSS_PSEUDO_ELEMENT_FLAGS_${pseudo.pseudo_ident},
@@ -205,17 +205,17 @@ impl PseudoElement {
             "-moz-list-bullet" | "-moz-list-number" => {
                 return Some(PseudoElement::Marker);
             }
             _ => {
                 if starts_with_ignore_ascii_case(name, "-moz-tree-") {
                     return PseudoElement::tree_pseudo_element(name, Box::new([]))
                 }
                 if unsafe {
-                    structs::StaticPrefs_sVarCache_layout_css_unknown_webkit_pseudo_element
+                    structs::StaticPrefs::sVarCache_layout_css_unknown_webkit_pseudo_element
                 } {
                     const WEBKIT_PREFIX: &str = "-webkit-";
                     if starts_with_ignore_ascii_case(name, WEBKIT_PREFIX) {
                         let part = string_as_ascii_lowercase(&name[WEBKIT_PREFIX.len()..]);
                         return Some(PseudoElement::UnknownWebkit(part.into()));
                     }
                 }
             }
--- a/servo/components/style/gecko/selector_parser.rs
+++ b/servo/components/style/gecko/selector_parser.rs
@@ -170,17 +170,17 @@ impl NonTSPseudoClass {
 
     /// Returns whether the pseudo-class is enabled in content sheets.
     fn is_enabled_in_content(&self) -> bool {
         use crate::gecko_bindings::structs::mozilla;
         match *self {
             // For pseudo-classes with pref, the availability in content
             // depends on the pref.
             NonTSPseudoClass::Fullscreen => unsafe {
-                mozilla::StaticPrefs_sVarCache_full_screen_api_unprefix_enabled
+                mozilla::StaticPrefs::sVarCache_full_screen_api_unprefix_enabled
             },
             // Otherwise, a pseudo-class is enabled in content when it
             // doesn't have any enabled flag.
             _ => !self
                 .has_any_flag(NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
         }
     }
 
@@ -350,17 +350,17 @@ impl<'a, 'i> ::selectors::Parser<'i> for
     #[inline]
     fn parse_host(&self) -> bool {
         true
     }
 
     #[inline]
     fn parse_part(&self) -> bool {
         self.chrome_rules_enabled() ||
-            unsafe { structs::StaticPrefs_sVarCache_layout_css_shadow_parts_enabled }
+            unsafe { structs::StaticPrefs::sVarCache_layout_css_shadow_parts_enabled }
     }
 
     fn parse_non_ts_pseudo_class(
         &self,
         location: SourceLocation,
         name: CowRcStr<'i>,
     ) -> Result<NonTSPseudoClass, ParseError<'i>> {
         if let Some(pseudo_class) = NonTSPseudoClass::parse_non_functional(&name) {
--- a/servo/components/style/media_queries/media_feature_expression.rs
+++ b/servo/components/style/media_queries/media_feature_expression.rs
@@ -297,17 +297,17 @@ impl MediaFeatureExpression {
                 let mut feature_name = &**ident;
 
                 #[cfg(feature = "gecko")]
                 {
                     if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
                         feature_name = &feature_name[8..];
                         requirements.insert(ParsingRequirements::WEBKIT_PREFIX);
                         if unsafe {
-                            structs::StaticPrefs_sVarCache_layout_css_prefixes_device_pixel_ratio_webkit
+                            structs::StaticPrefs::sVarCache_layout_css_prefixes_device_pixel_ratio_webkit
                         } {
                             requirements.insert(
                                 ParsingRequirements::WEBKIT_DEVICE_PIXEL_RATIO_PREF_ENABLED,
                             );
                         }
                     }
                 }
 
--- a/servo/components/style/properties/cascade.rs
+++ b/servo/components/style/properties/cascade.rs
@@ -681,17 +681,17 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
         use crate::gecko_bindings::{bindings, structs};
         use crate::values::computed::font::GenericFontFamily;
 
         if !self.seen.contains(LonghandId::XLang) &&
            !self.seen.contains(LonghandId::FontFamily) {
             return;
         }
 
-        let use_document_fonts = unsafe { structs::StaticPrefs_sVarCache_browser_display_use_document_fonts != 0 };
+        let use_document_fonts = unsafe { structs::StaticPrefs::sVarCache_browser_display_use_document_fonts != 0 };
         let builder = &mut self.context.builder;
         let (default_font_type, prioritize_user_fonts) = {
             let font = builder.get_font().gecko();
 
             // System fonts are all right, and should have the default font type
             // set to none already, so bail out early.
             if font.mFont.systemFont {
                 debug_assert_eq!(font.mFont.fontlist.mDefaultFontType, GenericFontFamily::None);
--- a/servo/components/style/stylesheets/document_rule.rs
+++ b/servo/components/style/stylesheets/document_rule.rs
@@ -255,22 +255,22 @@ impl DocumentCondition {
     fn allowed_in(&self, context: &ParserContext) -> bool {
         use crate::gecko_bindings::structs;
         use crate::stylesheets::Origin;
 
         if context.stylesheet_origin != Origin::Author {
             return true;
         }
 
-        if unsafe { structs::StaticPrefs_sVarCache_layout_css_moz_document_content_enabled } {
+        if unsafe { structs::StaticPrefs::sVarCache_layout_css_moz_document_content_enabled } {
             return true;
         }
 
         if !unsafe {
-            structs::StaticPrefs_sVarCache_layout_css_moz_document_url_prefix_hack_enabled
+            structs::StaticPrefs::sVarCache_layout_css_moz_document_url_prefix_hack_enabled
         } {
             return false;
         }
 
         // Allow a single url-prefix() for compatibility.
         //
         // See bug 1446470 and dependencies.
         if self.0.len() != 1 {
--- a/servo/components/style/stylesheets/supports_rule.rs
+++ b/servo/components/style/stylesheets/supports_rule.rs
@@ -319,17 +319,17 @@ impl ToCss for RawSelector {
 }
 
 impl RawSelector {
     /// Tries to evaluate a `selector()` function.
     pub fn eval(&self, context: &ParserContext, namespaces: &Namespaces) -> bool {
         #[cfg(feature = "gecko")]
         {
             if unsafe {
-                !crate::gecko_bindings::structs::StaticPrefs_sVarCache_layout_css_supports_selector_enabled
+                !crate::gecko_bindings::structs::StaticPrefs::sVarCache_layout_css_supports_selector_enabled
             } {
                 return false;
             }
         }
 
         let mut input = ParserInput::new(&self.0);
         let mut input = Parser::new(&mut input);
         input
--- a/servo/components/style/values/generics/easing.rs
+++ b/servo/components/style/values/generics/easing.rs
@@ -65,17 +65,17 @@ pub enum TimingKeyword {
     EaseIn,
     EaseOut,
     EaseInOut,
 }
 
 #[cfg(feature = "gecko")]
 fn step_position_jump_enabled(_context: &ParserContext) -> bool {
     use crate::gecko_bindings::structs;
-    unsafe { structs::StaticPrefs_sVarCache_layout_css_step_position_jump_enabled }
+    unsafe { structs::StaticPrefs::sVarCache_layout_css_step_position_jump_enabled }
 }
 
 #[cfg(feature = "servo")]
 fn step_position_jump_enabled(_context: &ParserContext) -> bool {
     false
 }
 
 #[allow(missing_docs)]
--- a/servo/components/style/values/generics/text.rs
+++ b/servo/components/style/values/generics/text.rs
@@ -70,17 +70,17 @@ impl<Value> Spacing<Value> {
     }
 }
 
 #[cfg(feature = "gecko")]
 fn line_height_moz_block_height_enabled(context: &ParserContext) -> bool {
     use crate::gecko_bindings::structs;
     context.in_ua_sheet() ||
         unsafe {
-            structs::StaticPrefs_sVarCache_layout_css_line_height_moz_block_height_content_enabled
+            structs::StaticPrefs::sVarCache_layout_css_line_height_moz_block_height_content_enabled
         }
 }
 
 /// A generic value for the `line-height` property.
 #[derive(
     Animate,
     Clone,
     ComputeSquaredDistance,
--- a/servo/components/style/values/specified/basic_shape.rs
+++ b/servo/components/style/values/specified/basic_shape.rs
@@ -55,17 +55,17 @@ pub type ShapeRadius = generic::ShapeRad
 
 /// The specified value of `Polygon`
 pub type Polygon = generic::GenericPolygon<LengthPercentage>;
 
 #[cfg(feature = "gecko")]
 fn is_clip_path_path_enabled(context: &ParserContext) -> bool {
     use crate::gecko_bindings::structs::mozilla;
     context.chrome_rules_enabled() ||
-        unsafe { mozilla::StaticPrefs_sVarCache_layout_css_clip_path_path_enabled }
+        unsafe { mozilla::StaticPrefs::sVarCache_layout_css_clip_path_path_enabled }
 }
 #[cfg(feature = "servo")]
 fn is_clip_path_path_enabled(_: &ParserContext) -> bool {
     false
 }
 
 impl Parse for ClippingShape {
     #[inline]
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -20,25 +20,25 @@ use selectors::parser::SelectorParseErro
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
 use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
 
 #[cfg(feature = "gecko")]
 fn moz_display_values_enabled(context: &ParserContext) -> bool {
     use crate::gecko_bindings::structs;
     context.in_ua_or_chrome_sheet() ||
-        unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_display_values_content_enabled }
+        unsafe { structs::StaticPrefs::sVarCache_layout_css_xul_display_values_content_enabled }
 }
 
 #[cfg(feature = "gecko")]
 fn moz_box_display_values_enabled(context: &ParserContext) -> bool {
     use crate::gecko_bindings::structs;
     context.in_ua_or_chrome_sheet() ||
         unsafe {
-            structs::StaticPrefs_sVarCache_layout_css_xul_box_display_values_content_enabled
+            structs::StaticPrefs::sVarCache_layout_css_xul_box_display_values_content_enabled
         }
 }
 
 /// Defines an element’s display type, which consists of
 /// the two basic qualities of how an element generates boxes
 /// <https://drafts.csswg.org/css-display/#propdef-display>
 ///
 ///
--- a/servo/components/style/values/specified/grid.rs
+++ b/servo/components/style/values/specified/grid.rs
@@ -376,17 +376,17 @@ impl ToComputedValue for TrackList<Lengt
         }
     }
 }
 
 #[cfg(feature = "gecko")]
 #[inline]
 fn allow_grid_template_subgrids() -> bool {
     use crate::gecko_bindings::structs::mozilla;
-    unsafe { mozilla::StaticPrefs_sVarCache_layout_css_grid_template_subgrid_value_enabled }
+    unsafe { mozilla::StaticPrefs::sVarCache_layout_css_grid_template_subgrid_value_enabled }
 }
 
 #[cfg(feature = "servo")]
 #[inline]
 fn allow_grid_template_subgrids() -> bool {
     false
 }
 
--- a/servo/components/style/values/specified/svg.rs
+++ b/servo/components/style/values/specified/svg.rs
@@ -31,17 +31,17 @@ pub type SVGWidth = generic::SVGLength<N
 
 /// [ <length> | <percentage> | <number> ]# | context-value
 pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthPercentage>;
 
 /// Whether the `context-value` value is enabled.
 #[cfg(feature = "gecko")]
 pub fn is_context_value_enabled() -> bool {
     use crate::gecko_bindings::structs::mozilla;
-    unsafe { mozilla::StaticPrefs_sVarCache_gfx_font_rendering_opentype_svg_enabled }
+    unsafe { mozilla::StaticPrefs::sVarCache_gfx_font_rendering_opentype_svg_enabled }
 }
 
 /// Whether the `context-value` value is enabled.
 #[cfg(not(feature = "gecko"))]
 pub fn is_context_value_enabled() -> bool {
     false
 }