Bug 1482782 - Part 7: Expand out nsStaticAtom.h macros now that we only static atom table. r=njn
authorCameron McCormack <cam@mcc.id.au>
Wed, 15 Aug 2018 15:46:42 +1000
changeset 486779 8d6f6eef3c76805d95cde66f354f150b75fbe9e4
parent 486778 c4b64bd53e9266f0116a27d9a41488149455005d
child 486780 e6a44943b17774c94e3c22e85e5260b0a62121ac
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
bugs1482782
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 1482782 - Part 7: Expand out nsStaticAtom.h macros now that we only static atom table. r=njn Summary: Depends On D3285 Reviewers: njn! Tags: #secure-revision Bug #: 1482782 Differential Revision: https://phabricator.services.mozilla.com/D3286
layout/style/ComputedStyle.h
layout/style/nsCSSAnonBoxes.cpp
layout/style/nsCSSPseudoElements.cpp
xpcom/ds/moz.build
xpcom/ds/nsAtom.h
xpcom/ds/nsAtomTable.cpp
xpcom/ds/nsGkAtoms.cpp
xpcom/ds/nsGkAtoms.h
xpcom/ds/nsStaticAtom.h
xpcom/ds/nsStaticAtomUtils.h
--- a/layout/style/ComputedStyle.h
+++ b/layout/style/ComputedStyle.h
@@ -8,21 +8,22 @@
 
 #ifndef _ComputedStyle_h_
 #define _ComputedStyle_h_
 
 #include "nsIMemoryReporter.h"
 #include <algorithm>
 #include "mozilla/ArenaObjectID.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/CachedInheritingStyles.h"
+#include "mozilla/Maybe.h"
 #include "mozilla/ServoComputedData.h"
 #include "mozilla/ServoTypes.h"
 #include "mozilla/ServoUtils.h"
 #include "mozilla/StyleComplexColor.h"
-#include "mozilla/CachedInheritingStyles.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSPseudoElements.h"
 
 #include "nsStyleStructFwd.h"
 
 class nsAtom;
 enum nsChangeHint : uint32_t;
 class nsIPresShell;
--- a/layout/style/nsCSSAnonBoxes.cpp
+++ b/layout/style/nsCSSAnonBoxes.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* atom list for CSS anonymous boxes */
 
 #include "mozilla/ArrayUtils.h"
 
 #include "nsCSSAnonBoxes.h"
 #include "nsGkAtomConsts.h"
+#include "nsStaticAtomUtils.h"
 
 using namespace mozilla;
 
 static nsStaticAtom*
 GetAtomBase()
 {
   return const_cast<nsStaticAtom*>(
       nsGkAtoms::GetAtomByIndex(kAtomIndex_AnonBoxes));
--- a/layout/style/nsCSSPseudoElements.cpp
+++ b/layout/style/nsCSSPseudoElements.cpp
@@ -8,16 +8,17 @@
 
 #include "nsCSSPseudoElements.h"
 
 #include "mozilla/ArrayUtils.h"
 
 #include "nsCSSAnonBoxes.h"
 #include "nsDOMString.h"
 #include "nsGkAtomConsts.h"
+#include "nsStaticAtomUtils.h"
 
 using namespace mozilla;
 
 // Flags data for each of the pseudo-elements.
 /* static */ const uint32_t
 nsCSSPseudoElements::kPseudoElementFlags[] = {
 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
   flags_,
--- a/xpcom/ds/moz.build
+++ b/xpcom/ds/moz.build
@@ -59,17 +59,17 @@ EXPORTS += [
     'nsHashKeys.h',
     'nsHashPropertyBag.h',
     'nsInterfaceHashtable.h',
     'nsJSThingHashtable.h',
     'nsMathUtils.h',
     'nsPointerHashKeys.h',
     'nsQuickSort.h',
     'nsRefPtrHashtable.h',
-    'nsStaticAtom.h',
+    'nsStaticAtomUtils.h',
     'nsStaticNameTable.h',
     'nsStringEnumerator.h',
     'nsSupportsPrimitives.h',
     'nsTArray-inl.h',
     'nsTArray.h',
     'nsTArrayForwardDeclare.h',
     'nsTHashtable.h',
     'nsTObserverArray.h',
--- a/xpcom/ds/nsAtom.h
+++ b/xpcom/ds/nsAtom.h
@@ -150,17 +150,17 @@ public:
   }
 
   already_AddRefed<nsAtom> ToAddRefed() {
     return already_AddRefed<nsAtom>(static_cast<nsAtom*>(this));
   }
 
 private:
   // This is an offset to the string chars, which must be at a lower address in
-  // memory. This should be achieved by using the macros in nsStaticAtom.h.
+  // memory.
   uint32_t mStringOffset;
 };
 
 class nsDynamicAtom : public nsAtom
 {
 public:
   // We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting
   // of this type is special.
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -16,17 +16,16 @@
 #include "nsAtom.h"
 #include "nsAtomTable.h"
 #include "nsAutoPtr.h"
 #include "nsCRT.h"
 #include "nsDataHashtable.h"
 #include "nsGkAtoms.h"
 #include "nsHashKeys.h"
 #include "nsPrintfCString.h"
-#include "nsStaticAtom.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsUnicharUtils.h"
 #include "PLDHashTable.h"
 #include "prenv.h"
 
 // There are two kinds of atoms handled by this module.
 //
--- a/xpcom/ds/nsGkAtoms.cpp
+++ b/xpcom/ds/nsGkAtoms.cpp
@@ -1,42 +1,58 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsGkAtoms.h"
 
+// Register an array of static atoms with the atom table.
+void
+NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen);
+
 namespace mozilla {
 namespace detail {
 
 MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 extern constexpr GkAtoms gGkAtoms = {
-  #define GK_ATOM(name_, value_, type_, atom_type_) NS_STATIC_ATOM_INIT_STRING(value_)
+  // The initialization of each atom's string.
+  #define GK_ATOM(name_, value_, type_, atom_type_) \
+    u"" value_,
   #include "nsGkAtomList.h"
   #undef GK_ATOM
   {
-    #define GK_ATOM(name_, value_, type_, atom_type_) \
-      NS_STATIC_ATOM_INIT_ATOM(nsStaticAtom, GkAtoms, name_, value_)
+    // The initialization of the atoms themselves.
+    //
+    // Note that |value_| is an 8-bit string, and so |sizeof(value_)| is equal
+    // to the number of chars (including the terminating '\0'). The |u""| prefix
+    // converts |value_| to a 16-bit string.
+    #define GK_ATOM(name_, value_, type_, atom_type_)                     \
+      nsStaticAtom(u"" value_,                                            \
+          sizeof(value_) - 1,                                             \
+          offsetof(GkAtoms,                                               \
+                   mAtoms[static_cast<size_t>(GkAtoms::Atoms::name_)]) -  \
+          offsetof(GkAtoms, name_##_string)),
     #include "nsGkAtomList.h"
     #undef GK_ATOM
   }
 };
 MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
 
 } // namespace detail
 } // namespace mozilla
 
 const nsStaticAtom* const nsGkAtoms::sAtoms = mozilla::detail::gGkAtoms.mAtoms;
 
-#define GK_ATOM(name_, value_, type_, atom_type_) \
-  NS_STATIC_ATOM_DEFN_PTR( \
-    type_, mozilla::detail::GkAtoms, mozilla::detail::gGkAtoms, \
-    nsGkAtoms, name_)
+// Definition of the pointer to the static atom.
+#define GK_ATOM(name_, value_, type_, atom_type_)                          \
+  type_* nsGkAtoms::name_ = const_cast<type_*>(static_cast<const type_*>(  \
+    &mozilla::detail::gGkAtoms.mAtoms[                                     \
+      static_cast<size_t>(mozilla::detail::GkAtoms::Atoms::name_)]));
 #include "nsGkAtomList.h"
 #undef GK_ATOM
 
 void nsGkAtoms::RegisterStaticAtoms()
 {
   NS_RegisterStaticAtoms(sAtoms, sAtomsLen);
 }
 
--- a/xpcom/ds/nsGkAtoms.h
+++ b/xpcom/ds/nsGkAtoms.h
@@ -3,17 +3,161 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsGkAtoms_h___
 #define nsGkAtoms_h___
 
 #include "nsAtom.h"
-#include "nsStaticAtom.h"
+
+// Static atoms are structured carefully to satisfy a lot of constraints.
+//
+// - We have ~2300 static atoms.
+//
+// - We want them to be constexpr so they end up in .rodata, and thus shared
+//   between processes, minimizing memory usage.
+//
+// - We need them to be in an array, so we can iterate over them (for
+//   registration and lookups).
+//
+// - Each static atom has a string literal associated with it. We can't use a
+//   pointer to the string literal because then the atoms won't end up in
+//   .rodata. Therefore the string literals and the atoms must be arranged in a
+//   way such that a numeric index can be used instead. This numeric index
+//   (nsStaticAtom::mStringOffset) must be computable at compile-time to keep
+//   the static atom constexpr. It should also not be too large (a uint32_t is
+//   reasonable).
+//
+// - Each static atom stores the hash value of its associated string literal;
+//   it's used in various ways. The hash value must be computed at
+//   compile-time, to keep the static atom constexpr.
+//
+// - As well as accessing each static atom via array indexing, we need an
+//   individual pointer, e.g. nsGkAtoms::foo. Ideally this would be constexpr
+//   so it doesn't take up any space in memory. Unfortunately MSVC's constexpr
+//   support is buggy and so this isn't possible yet. See bug 1449787.
+//
+// - The array of static atoms can't be in a .h file, because it's a huge
+//   constexpr expression, which would blow out compile times. But the
+//   individual pointers for the static atoms must be in a .h file so they are
+//   public.
+//
+// nsGkAtoms below defines static atoms in a way that satisfies these
+// constraints. It uses nsGkAtomList.h, which defines the names and values of
+// the atoms.
+//
+// nsGkAtomList.h is generated by StaticAtoms.py and has entries that look
+// like this:
+//
+//   GK_ATOM(one, "one", nsStaticAtom, Atom)
+//   GK_ATOM(two, "two", nsICSSPseudoElement, PseudoElementAtom)
+//   GK_ATOM(three, "three", nsICSSAnonBoxPseudo, InheritingAnonBoxAtom)
+//
+// After macro expansion, the atom definitions look like the following:
+//
+//   ====> nsGkAtoms.h <====
+//
+//   namespace mozilla {
+//   namespace detail {
+//
+//   struct GkAtoms
+//   {
+//     // The declaration of each atom's string.
+//     const char16_t one_string[sizeof("one")];
+//     const char16_t two_string[sizeof("two")];
+//     const char16_t three_string[sizeof("three")];
+//
+//     // The enum value for each atom.
+//     enum class Atoms {
+//       one_,
+//       two_,
+//       three_,
+//       AtomsCount
+//     };
+//
+//     const nsStaticAtom mAtoms[static_cast<size_t>(Atoms::AtomsCount)];
+//   };
+//
+//   } // namespace detail
+//   } // namespace mozilla
+//
+//   // This class holds the pointers to the individual atoms.
+//   class nsGkAtoms
+//   {
+//   private:
+//     // This is a useful handle to the array of atoms, used below and also
+//     // possibly by Rust code.
+//     static const nsStaticAtom* const sAtoms;
+//
+//     // The number of atoms, used below.
+//     static constexpr size_t sAtomsLen =
+//       static_cast<size_t>(detail::MyAtoms::Atoms::AtomsCount);
+//
+//   public:
+//     // These types are not `nsStaticAtom* const`, etc. -- even though these
+//     // atoms are immutable -- because they are often passed to functions with
+//     // `nsAtom*` parameters, i.e. that can be passed both dynamic and
+//     // static.
+//     static nsStaticAtom* one;
+//     static nsICSSPseudoElement* two;
+//     static nsICSSAnonBoxPseudo* three;
+//   };
+//
+//   ====> nsGkAtoms.cpp <====
+//
+//   namespace mozilla {
+//   namespace detail {
+//
+//   // Need to suppress some MSVC warning weirdness with WrappingMultiply().
+//   MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
+//   // Because this is `constexpr` it ends up in read-only memory where it can
+//   // be shared between processes.
+//   static constexpr GkAtoms gGkAtoms = {
+//     // The initialization of each atom's string.
+//     u"one",
+//     u"two",
+//     u"three",
+//     {
+//       // The initialization of the atoms themselves.
+//       nsStaticAtom(
+//         u"one", 3,
+//         offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::one)]) -
+//         offsetof(GkAtoms, one_string)),
+//       nsStaticAtom(
+//         u"two", 3,
+//         offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::two)]) -
+//         offsetof(GkAtoms, two_string)),
+//       nsStaticAtom(
+//         u"three", 3,
+//         offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::three)]) -
+//         offsetof(GkAtoms, three_string)),
+//     }
+//   };
+//   MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
+//
+//   } // namespace detail
+//   } // namespace mozilla
+//
+//   const nsStaticAtom* const nsGkAtoms::sAtoms =
+//     mozilla::detail::gGkAtoms.mAtoms;
+//
+//   // Definition of the pointer to the static atom.
+//   nsStaticAtom* nsGkAtoms::one =
+//     const_cast<nsStaticAtom*>(static_cast<const nsStaticAtom*>(
+//       &detail::gGkAtoms.mAtoms[
+//         static_cast<size_t>(detail::GkAtoms::Atoms::one)]);
+//   nsICSSPseudoElement* nsGkAtoms::two =
+//     const_cast<nsICSSPseudoElement*>(static_cast<const nsICSSPseudoElement*>(
+//       &detail::gGkAtoms.mAtoms[
+//         static_cast<size_t>(detail::GkAtoms::Atoms::two)]);
+//   nsICSSAnonBoxPseudo* nsGkAtoms::three =
+//     const_cast<nsICSSAnonBoxPseudo*>(static_cast<const nsICSSAnonBoxPseudo*>(
+//       &detail::gGkAtoms.mAtoms[
+//         static_cast<size_t>(detail::GkAtoms::Atoms::three)]);
 
 // Trivial subclasses of nsStaticAtom so that function signatures can require
 // an atom from a specific atom list.
 #define DEFINE_STATIC_ATOM_SUBCLASS(name_)                                    \
   class name_ : public nsStaticAtom                                           \
   {                                                                           \
   public:                                                                     \
     constexpr name_(const char16_t* aStr, uint32_t aLength, uint32_t aOffset) \
@@ -23,24 +167,34 @@
 DEFINE_STATIC_ATOM_SUBCLASS(nsICSSAnonBoxPseudo)
 DEFINE_STATIC_ATOM_SUBCLASS(nsICSSPseudoElement)
 
 #undef DEFINE_STATIC_ATOM_SUBCLASS
 
 namespace mozilla {
 namespace detail {
 
+// This `detail` class contains the atom strings and the atom objects.
+// Because they are together in a class, the mStringOffset field of the
+// atoms will be small and can be initialized at compile time.
+//
+// A `detail` namespace is used because the things within it aren't directly
+// referenced by external users of these static atoms.
 struct GkAtoms
 {
-  #define GK_ATOM(name_, value_, type_, atom_type_) NS_STATIC_ATOM_DECL_STRING(name_, value_)
+  // The declaration of each atom's string.
+  #define GK_ATOM(name_, value_, type_, atom_type_) \
+    const char16_t name_##_string[sizeof(value_)];
   #include "nsGkAtomList.h"
   #undef GK_ATOM
 
+  // The enum value for each atom.
   enum class Atoms {
-    #define GK_ATOM(name_, value_, type_, atom_type_) NS_STATIC_ATOM_ENUM(name_)
+    #define GK_ATOM(name_, value_, type_, atom_type_) \
+      name_,
     #include "nsGkAtomList.h"
     #undef GK_ATOM
     AtomsCount
   };
 
   const nsStaticAtom mAtoms[static_cast<size_t>(Atoms::AtomsCount)];
 };
 
@@ -58,14 +212,19 @@ public:
   static void RegisterStaticAtoms();
 
   static nsStaticAtom* GetAtomByIndex(size_t aIndex)
   {
     MOZ_ASSERT(aIndex < sAtomsLen);
     return const_cast<nsStaticAtom*>(&sAtoms[aIndex]);
   }
 
-  #define GK_ATOM(name_, value_, type_, atom_type_) NS_STATIC_ATOM_DECL_PTR(type_, name_)
+  // The declaration of the pointer to each static atom.
+  //
+  // XXX: Eventually this should be combined with its definition and the
+  // pointer should be made `constexpr`. See bug 1449787.
+  #define GK_ATOM(name_, value_, type_, atom_type_) \
+    static type_* name_;
   #include "nsGkAtomList.h"
   #undef GK_ATOM
 };
 
 #endif /* nsGkAtoms_h___ */
deleted file mode 100644
--- a/xpcom/ds/nsStaticAtom.h
+++ /dev/null
@@ -1,258 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsStaticAtom_h__
-#define nsStaticAtom_h__
-
-#include <stdint.h>
-#include "nsAtom.h"
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/Maybe.h"
-
-// Static atoms are structured carefully to satisfy a lot of constraints.
-//
-// - We have ~2700 static atoms. They are divided across ~4 classes, with the
-//   majority in nsGkAtoms.
-//
-// - We want them to be constexpr so they end up in .rodata, and thus shared
-//   between processes, minimizing memory usage.
-//
-// - We need them to be in an array, so we can iterate over them (for
-//   registration and lookups).
-//
-// - Each static atom has a string literal associated with it. We can't use a
-//   pointer to the string literal because then the atoms won't end up in
-//   .rodata. Therefore the string literals and the atoms must be arranged in a
-//   way such that a numeric index can be used instead. This numeric index
-//   (nsStaticAtom::mStringOffset) must be computable at compile-time to keep
-//   the static atom constexpr. It should also not be too large (a uint32_t is
-//   reasonable).
-//
-// - Each static atom stores the hash value of its associated string literal;
-//   it's used in various ways. The hash value must be computed at
-//   compile-time, to keep the static atom constexpr.
-//
-// - As well as accessing each static atom via array indexing, we need an
-//   individual pointer, e.g. nsGkAtoms::foo. Ideally this would be constexpr
-//   so it doesn't take up any space in memory. Unfortunately MSVC's constexpr
-//   support is buggy and so this isn't possible yet. See bug 1449787.
-//
-// - The array of static atoms can't be in a .h file, because it's a huge
-//   constexpr expression, which would blow out compile times. But the
-//   individual pointers for the static atoms must be in a .h file so they are
-//   public.
-//
-// The macros below are used to define static atoms in a way that satisfies
-// these constraints. They are used in conjunction with a .h file that defines
-// the names and values of the atoms.
-//
-// For example, the .h file might be called MyAtomList.h and look like this:
-//
-//   MY_ATOM(one, "one")
-//   MY_ATOM(two, "two")
-//   MY_ATOM(three, "three")
-//
-// The code defining the static atoms should look something like the following.
-// ("<<<"/"---"/">>>" markers are used below to indicate what the macros look
-// like before and after expansion.)
-//
-//   ====> MyAtoms.h <====
-//
-//   // A `detail` namespace is used because the things within it aren't
-//   // directly referenced by external users of these static atoms.
-//   namespace detail {
-//
-//   // This `detail` class contains the atom strings and the atom objects.
-//   // Because they are together in a class, the mStringOffset field of the
-//   // atoms will be small and can be initialized at compile time.
-//   struct MyAtoms
-//   {
-//     <<<
-//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DECL_STRING(name_, value_)
-//     #include "MyAtomList.h"
-//     #undef MY_ATOM
-//     ---
-//     const char16_t one_string[4];
-//     const char16_t two_string[4];
-//     const char16_t three_string[6];
-//     >>>
-//
-//     enum class Atoms {
-//       <<<
-//       #define MY_ATOM(name_, value_) NS_STATIC_ATOM_ENUM(name_)
-//       #include "MyAtomList.h"
-//       #undef MY_ATOM
-//       ---
-//       one,
-//       two,
-//       three,
-//       >>>
-//       AtomsCount
-//     };
-//
-//     const nsStaticAtom mAtoms[static_cast<size_t>(Atoms::AtomsCount)];
-//   };
-//
-//   } // namespace detail
-//
-//   // This class holds the pointers to the individual atoms.
-//   class nsMyAtoms
-//   {
-//   private:
-//     // This is a useful handle to the array of atoms, used below and also
-//     // possibly by Rust code.
-//     static const nsStaticAtom* const sAtoms;
-//
-//     // The number of atoms, used below.
-//     static constexpr size_t sAtomsLen =
-//       static_cast<size_t>(detail::MyAtoms::Atoms::AtomsCount);
-//
-//   public:
-//     // The type is not `nsStaticAtom* const` -- even though these atoms are
-//     // immutable -- because they are often passed to functions with
-//     // `nsAtom*` parameters, i.e. that can be passed both dynamic and
-//     // static.
-//     <<<
-//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DECL_PTR(nsStaticAtom, name_)
-//     #include "MyAtomList.h"
-//     #undef MY_ATOM
-//     ---
-//     static nsStaticAtom* one;
-//     static nsStaticAtom* two;
-//     static nsStaticAtom* three;
-//     >>>
-//   };
-//
-//   ====> MyAtoms.cpp <====
-//
-//   namespace detail {
-//
-//   // Need to suppress some MSVC warning weirdness with WrappingMultiply().
-//   MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
-//   // Because this is `constexpr` it ends up in read-only memory where it can
-//   // be shared between processes.
-//   static constexpr MyAtoms gMyAtoms = {
-//     <<<
-//     #define MY_ATOM(name_, value_) NS_STATIC_ATOM_INIT_STRING(value_)
-//     #include "MyAtomList.h"
-//     #undef MY_ATOM
-//     ---
-//     u"one",
-//     u"two",
-//     u"three",
-//     >>>
-//     {
-//       <<<
-//       #define MY_ATOM(name_, value_) NS_STATIC_ATOM_INIT_ATOM(nsStaticAtom, MyAtoms, name_, value_)
-//       #include "MyAtomList.h"
-//       #undef MY_ATOM
-//       ---
-//       nsStaticAtom(
-//         u"one", 3,
-//         offsetof(MyAtoms, mAtoms[static_cast<size_t>(MyAtoms::Atoms::one)]) -
-//         offsetof(MyAtoms, one_string)),
-//       nsStaticAtom(
-//         u"two", 3,
-//         offsetof(MyAtoms, mAtoms[static_cast<size_t>(MyAtoms::Atoms::two)]) -
-//         offsetof(MyAtoms, two_string)),
-//       nsStaticAtom(
-//         u"three", 3,
-//         offsetof(MyAtoms, mAtoms[static_cast<size_t>(MyAtoms::Atoms::three)]) -
-//         offsetof(MyAtoms, three_string)),
-//       >>>
-//     }
-//   };
-//   MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
-//
-//   } // namespace detail
-//
-//   const nsStaticAtom* const nsMyAtoms::sAtoms =
-//     mozilla::detail::gMyAtoms.mAtoms;
-//
-//   <<<
-//   #define MY_ATOM(name_, value_) NS_STATIC_ATOM_DEFN_PTR(nsStaticAtom, detail::MyAtoms, detail::gMyAtoms, nsMyAtoms, name_)
-//   #include "MyAtomList.h"
-//   #undef MY_ATOM
-//   ---
-//   nsStaticAtom* nsMyAtoms::one =
-//     const_cast<nsStaticAtom*>(&detail::gMyAtoms.mAtoms[
-//       static_cast<size_t>(detail::MyAtoms::Atoms::one)]);
-//   nsStaticAtom* nsMyAtoms::two =
-//     const_cast<nsStaticAtom*>(&detail::gMyAtoms.mAtoms[
-//       static_cast<size_t>(detail::MyAtoms::Atoms::two)]);
-//   nsStaticAtom* nsMyAtoms::three =
-//     const_cast<nsStaticAtom*>(&detail::gMyAtoms.mAtoms[
-//       static_cast<size_t>(detail::MyAtoms::Atoms::three)]);
-//   >>>
-//
-// When NS_RegisterStaticAtoms(sAtoms, sAtomsLen) is called it iterates
-// over the atoms, inserting them into the atom table.
-
-// The declaration of the atom's string.
-#define NS_STATIC_ATOM_DECL_STRING(name_, value_) \
-  const char16_t name_##_string[sizeof(value_)];
-
-// The enum value for the atom.
-#define NS_STATIC_ATOM_ENUM(name_) \
-  name_,
-
-// The declaration of the pointer to the static atom. `type_` must be
-// `nsStaticAtom` or a subclass thereof.
-// XXX: Eventually this should be combined with NS_STATIC_ATOM_DEFN_PTR and the
-// pointer should be made `constexpr`. See bug 1449787.
-#define NS_STATIC_ATOM_DECL_PTR(type_, name_) \
-  static type_* name_;
-
-// The initialization of the atom's string.
-#define NS_STATIC_ATOM_INIT_STRING(value_) \
-  u"" value_,
-
-// The initialization of the atom itself. `type_` must be `nsStaticAtom` or a
-// subclass thereof.
-//
-// Note that |value_| is an 8-bit string, and so |sizeof(value_)| is equal
-// to the number of chars (including the terminating '\0'). The |u""| prefix
-// converts |value_| to a 16-bit string.
-#define NS_STATIC_ATOM_INIT_ATOM(type_, detailClass_, name_, value_) \
-  type_(u"" value_, \
-        sizeof(value_) - 1, \
-        offsetof(detailClass_, \
-                 mAtoms[static_cast<size_t>(detailClass_::Atoms::name_)]) - \
-        offsetof(detailClass_, name_##_string)),
-
-// Definition of the pointer to the static atom. `type_` must be `nsStaticAtom`
-// or a subclass thereof.
-#define NS_STATIC_ATOM_DEFN_PTR(type_, detailClass_, detailObj_, class_, name_) \
-  type_* class_::name_ = const_cast<type_*>(static_cast<const type_*>( \
-    &detailObj_.mAtoms[static_cast<size_t>(detailClass_::Atoms::name_)]));
-
-// Register an array of static atoms with the atom table.
-void
-NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen);
-
-// This class holds basic operations on arrays of static atoms.
-class nsStaticAtomUtils {
-public:
-  static mozilla::Maybe<uint32_t> Lookup(nsAtom* aAtom,
-                                         const nsStaticAtom* aAtoms,
-                                         uint32_t aCount)
-  {
-    for (uint32_t i = 0; i < aCount; i++) {
-      if (aAtom == &aAtoms[i]) {
-        return mozilla::Some(i);
-      }
-    }
-    return mozilla::Nothing();
-  }
-
-  static bool IsMember(nsAtom* aAtom, const nsStaticAtom* aAtoms,
-                       uint32_t aCount)
-  {
-    return Lookup(aAtom, aAtoms, aCount).isSome();
-  }
-};
-
-#endif
new file mode 100644
--- /dev/null
+++ b/xpcom/ds/nsStaticAtomUtils.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsStaticAtomUtils_h
+#define nsStaticAtomUtils_h
+
+#include <stdint.h>
+#include "nsAtom.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/Maybe.h"
+
+// This class holds basic operations on arrays of static atoms.
+class nsStaticAtomUtils {
+public:
+  static mozilla::Maybe<uint32_t> Lookup(nsAtom* aAtom,
+                                         const nsStaticAtom* aAtoms,
+                                         uint32_t aCount)
+  {
+    for (uint32_t i = 0; i < aCount; i++) {
+      if (aAtom == &aAtoms[i]) {
+        return mozilla::Some(i);
+      }
+    }
+    return mozilla::Nothing();
+  }
+
+  static bool IsMember(nsAtom* aAtom, const nsStaticAtom* aAtoms,
+                       uint32_t aCount)
+  {
+    return Lookup(aAtom, aAtoms, aCount).isSome();
+  }
+};
+
+#endif // nsStaticAtomUtils_h