/work/obj-fuzz/dist/include/nsGkAtoms.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef nsGkAtoms_h___ |
8 | | #define nsGkAtoms_h___ |
9 | | |
10 | | #include "nsAtom.h" |
11 | | |
12 | | // Static atoms are structured carefully to satisfy a lot of constraints. |
13 | | // |
14 | | // - We have ~2300 static atoms. |
15 | | // |
16 | | // - We want them to be constexpr so they end up in .rodata, and thus shared |
17 | | // between processes, minimizing memory usage. |
18 | | // |
19 | | // - We need them to be in an array, so we can iterate over them (for |
20 | | // registration and lookups). |
21 | | // |
22 | | // - Each static atom has a string literal associated with it. We can't use a |
23 | | // pointer to the string literal because then the atoms won't end up in |
24 | | // .rodata. Therefore the string literals and the atoms must be arranged in a |
25 | | // way such that a numeric index can be used instead. This numeric index |
26 | | // (nsStaticAtom::mStringOffset) must be computable at compile-time to keep |
27 | | // the static atom constexpr. It should also not be too large (a uint32_t is |
28 | | // reasonable). |
29 | | // |
30 | | // - Each static atom stores the hash value of its associated string literal; |
31 | | // it's used in various ways. The hash value must be computed at |
32 | | // compile-time, to keep the static atom constexpr. |
33 | | // |
34 | | // - As well as accessing each static atom via array indexing, we need an |
35 | | // individual pointer, e.g. nsGkAtoms::foo. Ideally this would be constexpr |
36 | | // so it doesn't take up any space in memory. Unfortunately MSVC's constexpr |
37 | | // support is buggy and so this isn't possible yet. See bug 1449787. |
38 | | // |
39 | | // - The array of static atoms can't be in a .h file, because it's a huge |
40 | | // constexpr expression, which would blow out compile times. But the |
41 | | // individual pointers for the static atoms must be in a .h file so they are |
42 | | // public. |
43 | | // |
44 | | // nsGkAtoms below defines static atoms in a way that satisfies these |
45 | | // constraints. It uses nsGkAtomList.h, which defines the names and values of |
46 | | // the atoms. |
47 | | // |
48 | | // nsGkAtomList.h is generated by StaticAtoms.py and has entries that look |
49 | | // like this: |
50 | | // |
51 | | // GK_ATOM(one, "one", 0x01234567, nsStaticAtom, Atom) |
52 | | // GK_ATOM(two, "two", 0x12345678, nsICSSPseudoElement, PseudoElementAtom) |
53 | | // GK_ATOM(three, "three", 0x23456789, nsICSSAnonBoxPseudo, InheritingAnonBoxAtom) |
54 | | // |
55 | | // After macro expansion, the atom definitions look like the following: |
56 | | // |
57 | | // ====> nsGkAtoms.h <==== |
58 | | // |
59 | | // namespace mozilla { |
60 | | // namespace detail { |
61 | | // |
62 | | // struct GkAtoms |
63 | | // { |
64 | | // // The declaration of each atom's string. |
65 | | // const char16_t one_string[sizeof("one")]; |
66 | | // const char16_t two_string[sizeof("two")]; |
67 | | // const char16_t three_string[sizeof("three")]; |
68 | | // |
69 | | // // The enum value for each atom. |
70 | | // enum class Atoms { |
71 | | // one_, |
72 | | // two_, |
73 | | // three_, |
74 | | // AtomsCount |
75 | | // }; |
76 | | // |
77 | | // const nsStaticAtom mAtoms[static_cast<size_t>(Atoms::AtomsCount)]; |
78 | | // }; |
79 | | // |
80 | | // } // namespace detail |
81 | | // } // namespace mozilla |
82 | | // |
83 | | // // This class holds the pointers to the individual atoms. |
84 | | // class nsGkAtoms |
85 | | // { |
86 | | // private: |
87 | | // // This is a useful handle to the array of atoms, used below and also |
88 | | // // possibly by Rust code. |
89 | | // static const nsStaticAtom* const sAtoms; |
90 | | // |
91 | | // // The number of atoms, used below. |
92 | | // static constexpr size_t sAtomsLen = |
93 | | // static_cast<size_t>(detail::MyAtoms::Atoms::AtomsCount); |
94 | | // |
95 | | // public: |
96 | | // // These types are not `nsStaticAtom* const`, etc. -- even though these |
97 | | // // atoms are immutable -- because they are often passed to functions with |
98 | | // // `nsAtom*` parameters, i.e. that can be passed both dynamic and |
99 | | // // static. |
100 | | // static nsStaticAtom* one; |
101 | | // static nsICSSPseudoElement* two; |
102 | | // static nsICSSAnonBoxPseudo* three; |
103 | | // }; |
104 | | // |
105 | | // ====> nsGkAtoms.cpp <==== |
106 | | // |
107 | | // namespace mozilla { |
108 | | // namespace detail { |
109 | | // |
110 | | // // Need to suppress some MSVC warning weirdness with WrappingMultiply(). |
111 | | // MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING |
112 | | // // Because this is `constexpr` it ends up in read-only memory where it can |
113 | | // // be shared between processes. |
114 | | // static constexpr GkAtoms gGkAtoms = { |
115 | | // // The initialization of each atom's string. |
116 | | // u"one", |
117 | | // u"two", |
118 | | // u"three", |
119 | | // { |
120 | | // // The initialization of the atoms themselves. |
121 | | // nsStaticAtom( |
122 | | // u"one", 3, |
123 | | // 0x01234567, |
124 | | // offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::one)]) - |
125 | | // offsetof(GkAtoms, one_string)), |
126 | | // nsStaticAtom( |
127 | | // u"two", 3, |
128 | | // 0x12345678, |
129 | | // offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::two)]) - |
130 | | // offsetof(GkAtoms, two_string)), |
131 | | // nsStaticAtom( |
132 | | // u"three", 3, |
133 | | // 0x23456789, |
134 | | // offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::three)]) - |
135 | | // offsetof(GkAtoms, three_string)), |
136 | | // } |
137 | | // }; |
138 | | // MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING |
139 | | // |
140 | | // } // namespace detail |
141 | | // } // namespace mozilla |
142 | | // |
143 | | // const nsStaticAtom* const nsGkAtoms::sAtoms = |
144 | | // mozilla::detail::gGkAtoms.mAtoms; |
145 | | // |
146 | | // // Definition of the pointer to the static atom. |
147 | | // nsStaticAtom* nsGkAtoms::one = |
148 | | // const_cast<nsStaticAtom*>(static_cast<const nsStaticAtom*>( |
149 | | // &detail::gGkAtoms.mAtoms[ |
150 | | // static_cast<size_t>(detail::GkAtoms::Atoms::one)]); |
151 | | // nsICSSPseudoElement* nsGkAtoms::two = |
152 | | // const_cast<nsICSSPseudoElement*>(static_cast<const nsICSSPseudoElement*>( |
153 | | // &detail::gGkAtoms.mAtoms[ |
154 | | // static_cast<size_t>(detail::GkAtoms::Atoms::two)]); |
155 | | // nsICSSAnonBoxPseudo* nsGkAtoms::three = |
156 | | // const_cast<nsICSSAnonBoxPseudo*>(static_cast<const nsICSSAnonBoxPseudo*>( |
157 | | // &detail::gGkAtoms.mAtoms[ |
158 | | // static_cast<size_t>(detail::GkAtoms::Atoms::three)]); |
159 | | |
160 | | // Trivial subclasses of nsStaticAtom so that function signatures can require |
161 | | // an atom from a specific atom list. |
162 | | #define DEFINE_STATIC_ATOM_SUBCLASS(name_) \ |
163 | | class name_ : public nsStaticAtom \ |
164 | | { \ |
165 | | public: \ |
166 | | constexpr name_(const char16_t* aStr, uint32_t aLength, \ |
167 | | uint32_t aHash, uint32_t aOffset) \ |
168 | 0 | : nsStaticAtom(aStr, aLength, aHash, aOffset) {} \ Unexecuted instantiation: nsICSSAnonBoxPseudo::nsICSSAnonBoxPseudo(char16_t const*, unsigned int, unsigned int, unsigned int) Unexecuted instantiation: nsICSSPseudoElement::nsICSSPseudoElement(char16_t const*, unsigned int, unsigned int, unsigned int) |
169 | | }; |
170 | | |
171 | | DEFINE_STATIC_ATOM_SUBCLASS(nsICSSAnonBoxPseudo) |
172 | | DEFINE_STATIC_ATOM_SUBCLASS(nsICSSPseudoElement) |
173 | | |
174 | | #undef DEFINE_STATIC_ATOM_SUBCLASS |
175 | | |
176 | | namespace mozilla { |
177 | | namespace detail { |
178 | | |
179 | | // This `detail` class contains the atom strings and the atom objects. |
180 | | // Because they are together in a class, the mStringOffset field of the |
181 | | // atoms will be small and can be initialized at compile time. |
182 | | // |
183 | | // A `detail` namespace is used because the things within it aren't directly |
184 | | // referenced by external users of these static atoms. |
185 | | struct GkAtoms |
186 | | { |
187 | | // The declaration of each atom's string. |
188 | | #define GK_ATOM(name_, value_, hash_, type_, atom_type_) \ |
189 | | const char16_t name_##_string[sizeof(value_)]; |
190 | | #include "nsGkAtomList.h" |
191 | | #undef GK_ATOM |
192 | | |
193 | | // The enum value for each atom. |
194 | | enum class Atoms { |
195 | | #define GK_ATOM(name_, value_, hash_, type_, atom_type_) \ |
196 | | name_, |
197 | | #include "nsGkAtomList.h" |
198 | | #undef GK_ATOM |
199 | | AtomsCount |
200 | | }; |
201 | | |
202 | | const nsStaticAtom mAtoms[static_cast<size_t>(Atoms::AtomsCount)]; |
203 | | }; |
204 | | |
205 | | } // namespace detail |
206 | | } // namespace mozilla |
207 | | |
208 | | class nsGkAtoms |
209 | | { |
210 | | private: |
211 | | static const nsStaticAtom* const sAtoms; |
212 | | static constexpr size_t sAtomsLen = |
213 | | static_cast<size_t>(mozilla::detail::GkAtoms::Atoms::AtomsCount); |
214 | | |
215 | | public: |
216 | | static void RegisterStaticAtoms(); |
217 | | |
218 | | static nsStaticAtom* GetAtomByIndex(size_t aIndex) |
219 | 0 | { |
220 | 0 | MOZ_ASSERT(aIndex < sAtomsLen); |
221 | 0 | return const_cast<nsStaticAtom*>(&sAtoms[aIndex]); |
222 | 0 | } |
223 | | |
224 | | // The declaration of the pointer to each static atom. |
225 | | // |
226 | | // XXX: Eventually this should be combined with its definition and the |
227 | | // pointer should be made `constexpr`. See bug 1449787. |
228 | | #define GK_ATOM(name_, value_, hash_, type_, atom_type_) \ |
229 | | static type_* name_; |
230 | | #include "nsGkAtomList.h" |
231 | | #undef GK_ATOM |
232 | | }; |
233 | | |
234 | | #endif /* nsGkAtoms_h___ */ |