forked from mirrors/gecko-dev
Bug 1483121 - Generate static atom hash in StaticAtoms.py. r=njn,emilio
Summary: Depends On D3286 Reviewers: njn!, emilio! Tags: #secure-revision Bug #: 1483121 Differential Revision: https://phabricator.services.mozilla.com/D3295
This commit is contained in:
parent
426af33a36
commit
be0a66bcfb
7 changed files with 66 additions and 28 deletions
|
|
@ -24,7 +24,8 @@ PRELUDE = """
|
|||
"""[1:] # NOQA: E501
|
||||
|
||||
|
||||
PATTERN = re.compile('^GK_ATOM\(([^,]*),[^"]*"([^"]*)",\s*([^,]*),\s*([^)]*)\)',
|
||||
# Matches lines like `GK_ATOM(foo, "foo", 0x12345678, nsStaticAtom, PseudoElementAtom)`.
|
||||
PATTERN = re.compile('^GK_ATOM\(([^,]*),[^"]*"([^"]*)",\s*(0x[0-9a-f]+),\s*([^,]*),\s*([^)]*)\)',
|
||||
re.MULTILINE)
|
||||
FILE = "include/nsGkAtomList.h"
|
||||
CLASS = "nsGkAtoms"
|
||||
|
|
@ -52,10 +53,11 @@ def map_atom(ident):
|
|||
|
||||
|
||||
class Atom:
|
||||
def __init__(self, ident, value, ty, atom_type):
|
||||
def __init__(self, ident, value, hash, ty, atom_type):
|
||||
self.ident = "{}_{}".format(CLASS, ident)
|
||||
self.original_ident = ident
|
||||
self.value = value
|
||||
self.hash = hash
|
||||
# The Gecko type: "nsStaticAtom", "nsICSSPseudoElement", or "nsIAnonBoxPseudo"
|
||||
self.ty = ty
|
||||
# The type of atom: "Atom", "PseudoElement", "NonInheritingAnonBox",
|
||||
|
|
@ -104,7 +106,8 @@ def collect_atoms(objdir):
|
|||
with open(path) as f:
|
||||
content = f.read()
|
||||
for result in PATTERN.finditer(content):
|
||||
atoms.append(Atom(result.group(1), result.group(2), result.group(3), result.group(4)))
|
||||
atoms.append(Atom(result.group(1), result.group(2), result.group(3),
|
||||
result.group(4), result.group(5)))
|
||||
return atoms
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ class Atom():
|
|||
self.string = string
|
||||
self.ty = ty
|
||||
self.atom_type = self.__class__.__name__
|
||||
self.hash = hash_string(string)
|
||||
|
||||
|
||||
class PseudoElementAtom(Atom):
|
||||
|
|
@ -29,3 +30,25 @@ class NonInheritingAnonBoxAtom(AnonBoxAtom):
|
|||
class InheritingAnonBoxAtom(AnonBoxAtom):
|
||||
def __init__(self, ident, string):
|
||||
AnonBoxAtom.__init__(self, ident, string)
|
||||
|
||||
|
||||
GOLDEN_RATIO_U32 = 0x9E3779B9
|
||||
|
||||
|
||||
def rotate_left_5(value):
|
||||
return ((value << 5) | (value >> 27)) & 0xFFFFFFFF
|
||||
|
||||
|
||||
def wrapping_multiply(x, y):
|
||||
return (x * y) & 0xFFFFFFFF
|
||||
|
||||
|
||||
# Calculate the precomputed hash of the static atom. This is a port of
|
||||
# mozilla::HashString(const char16_t*), which is what we use for atomizing
|
||||
# strings. An assertion in nsAtomTable::RegisterStaticAtoms ensures that
|
||||
# the value we compute here matches what HashString() would produce.
|
||||
def hash_string(s):
|
||||
h = 0
|
||||
for c in s:
|
||||
h = wrapping_multiply(GOLDEN_RATIO_U32, rotate_left_5(h) ^ ord(c))
|
||||
return h
|
||||
|
|
|
|||
|
|
@ -2354,9 +2354,9 @@ def generate_nsgkatomlist_h(output, *ignore):
|
|||
"#ifdef small\n"
|
||||
"#undef small\n"
|
||||
"#endif\n\n"
|
||||
"// GK_ATOM(identifier, string, gecko_type, atom_type)\n" +
|
||||
"".join(["GK_ATOM(%s, \"%s\", %s, %s)\n" %
|
||||
(a.ident, a.string, a.ty, a.atom_type)
|
||||
"// GK_ATOM(identifier, string, hash, gecko_type, atom_type)\n" +
|
||||
"".join(["GK_ATOM(%s, \"%s\", 0x%08x, %s, %s)\n" %
|
||||
(a.ident, a.string, a.hash, a.ty, a.atom_type)
|
||||
for a in STATIC_ATOMS]))
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
|
@ -104,10 +103,10 @@ public:
|
|||
|
||||
protected:
|
||||
// Used by nsStaticAtom.
|
||||
constexpr nsAtom(const char16_t* aStr, uint32_t aLength)
|
||||
constexpr nsAtom(const char16_t* aStr, uint32_t aLength, uint32_t aHash)
|
||||
: mLength(aLength)
|
||||
, mKind(static_cast<uint32_t>(nsAtom::AtomKind::Static))
|
||||
, mHash(mozilla::HashString(aStr))
|
||||
, mHash(aHash)
|
||||
{}
|
||||
|
||||
// Used by nsDynamicAtom.
|
||||
|
|
@ -138,9 +137,14 @@ public:
|
|||
MozExternalRefCountType AddRef() = delete;
|
||||
MozExternalRefCountType Release() = delete;
|
||||
|
||||
// The static atom's precomputed hash value is an argument here, but it
|
||||
// must be the same as would be computed by mozilla::HashString(aStr),
|
||||
// which is what we use when atomizing strings. We compute this hash in
|
||||
// Atom.py and assert in nsAtomTable::RegisterStaticAtoms that the two
|
||||
// hashes match.
|
||||
constexpr nsStaticAtom(const char16_t* aStr, uint32_t aLength,
|
||||
uint32_t aStringOffset)
|
||||
: nsAtom(aStr, aLength)
|
||||
uint32_t aHash, uint32_t aStringOffset)
|
||||
: nsAtom(aStr, aLength, aHash)
|
||||
, mStringOffset(aStringOffset)
|
||||
{}
|
||||
|
||||
|
|
|
|||
|
|
@ -647,6 +647,11 @@ nsAtomTable::RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen)
|
|||
MOZ_ASSERT(nsCRT::IsAscii(atom->String()));
|
||||
MOZ_ASSERT(NS_strlen(atom->String()) == atom->GetLength());
|
||||
|
||||
// This assertion ensures the static atom's precomputed hash value matches
|
||||
// what would be computed by mozilla::HashString(aStr), which is what we use
|
||||
// when atomizing strings. We compute this hash in Atom.py.
|
||||
MOZ_ASSERT(HashString(atom->String()) == atom->hash());
|
||||
|
||||
AtomTableKey key(atom);
|
||||
nsAtomSubTable& table = SelectSubTable(key);
|
||||
MutexAutoLock lock(table.mLock);
|
||||
|
|
|
|||
|
|
@ -13,10 +13,9 @@ NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen);
|
|||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
|
||||
extern constexpr GkAtoms gGkAtoms = {
|
||||
// The initialization of each atom's string.
|
||||
#define GK_ATOM(name_, value_, type_, atom_type_) \
|
||||
#define GK_ATOM(name_, value_, hash_, type_, atom_type_) \
|
||||
u"" value_,
|
||||
#include "nsGkAtomList.h"
|
||||
#undef GK_ATOM
|
||||
|
|
@ -26,9 +25,10 @@ extern constexpr GkAtoms gGkAtoms = {
|
|||
// 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_) \
|
||||
#define GK_ATOM(name_, value_, hash_, type_, atom_type_) \
|
||||
nsStaticAtom(u"" value_, \
|
||||
sizeof(value_) - 1, \
|
||||
hash_, \
|
||||
offsetof(GkAtoms, \
|
||||
mAtoms[static_cast<size_t>(GkAtoms::Atoms::name_)]) - \
|
||||
offsetof(GkAtoms, name_##_string)),
|
||||
|
|
@ -36,7 +36,6 @@ extern constexpr GkAtoms gGkAtoms = {
|
|||
#undef GK_ATOM
|
||||
}
|
||||
};
|
||||
MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mozilla
|
||||
|
|
@ -44,7 +43,7 @@ MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
|
|||
const nsStaticAtom* const nsGkAtoms::sAtoms = mozilla::detail::gGkAtoms.mAtoms;
|
||||
|
||||
// Definition of the pointer to the static atom.
|
||||
#define GK_ATOM(name_, value_, type_, atom_type_) \
|
||||
#define GK_ATOM(name_, value_, hash_, 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_)]));
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@
|
|||
// 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)
|
||||
// GK_ATOM(one, "one", 0x01234567, nsStaticAtom, Atom)
|
||||
// GK_ATOM(two, "two", 0x12345678, nsICSSPseudoElement, PseudoElementAtom)
|
||||
// GK_ATOM(three, "three", 0x23456789, nsICSSAnonBoxPseudo, InheritingAnonBoxAtom)
|
||||
//
|
||||
// After macro expansion, the atom definitions look like the following:
|
||||
//
|
||||
|
|
@ -120,14 +120,17 @@
|
|||
// // The initialization of the atoms themselves.
|
||||
// nsStaticAtom(
|
||||
// u"one", 3,
|
||||
// 0x01234567,
|
||||
// offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::one)]) -
|
||||
// offsetof(GkAtoms, one_string)),
|
||||
// nsStaticAtom(
|
||||
// u"two", 3,
|
||||
// 0x12345678,
|
||||
// offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::two)]) -
|
||||
// offsetof(GkAtoms, two_string)),
|
||||
// nsStaticAtom(
|
||||
// u"three", 3,
|
||||
// 0x23456789,
|
||||
// offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::three)]) -
|
||||
// offsetof(GkAtoms, three_string)),
|
||||
// }
|
||||
|
|
@ -156,12 +159,13 @@
|
|||
|
||||
// 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) \
|
||||
: nsStaticAtom(aStr, aLength, aOffset) {} \
|
||||
#define DEFINE_STATIC_ATOM_SUBCLASS(name_) \
|
||||
class name_ : public nsStaticAtom \
|
||||
{ \
|
||||
public: \
|
||||
constexpr name_(const char16_t* aStr, uint32_t aLength, \
|
||||
uint32_t aHash, uint32_t aOffset) \
|
||||
: nsStaticAtom(aStr, aLength, aHash, aOffset) {} \
|
||||
};
|
||||
|
||||
DEFINE_STATIC_ATOM_SUBCLASS(nsICSSAnonBoxPseudo)
|
||||
|
|
@ -181,14 +185,14 @@ namespace detail {
|
|||
struct GkAtoms
|
||||
{
|
||||
// The declaration of each atom's string.
|
||||
#define GK_ATOM(name_, value_, type_, atom_type_) \
|
||||
#define GK_ATOM(name_, value_, hash_, 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_) \
|
||||
#define GK_ATOM(name_, value_, hash_, type_, atom_type_) \
|
||||
name_,
|
||||
#include "nsGkAtomList.h"
|
||||
#undef GK_ATOM
|
||||
|
|
@ -221,7 +225,7 @@ public:
|
|||
//
|
||||
// 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_) \
|
||||
#define GK_ATOM(name_, value_, hash_, type_, atom_type_) \
|
||||
static type_* name_;
|
||||
#include "nsGkAtomList.h"
|
||||
#undef GK_ATOM
|
||||
|
|
|
|||
Loading…
Reference in a new issue