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
|
"""[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)
|
re.MULTILINE)
|
||||||
FILE = "include/nsGkAtomList.h"
|
FILE = "include/nsGkAtomList.h"
|
||||||
CLASS = "nsGkAtoms"
|
CLASS = "nsGkAtoms"
|
||||||
|
|
@ -52,10 +53,11 @@ def map_atom(ident):
|
||||||
|
|
||||||
|
|
||||||
class Atom:
|
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.ident = "{}_{}".format(CLASS, ident)
|
||||||
self.original_ident = ident
|
self.original_ident = ident
|
||||||
self.value = value
|
self.value = value
|
||||||
|
self.hash = hash
|
||||||
# The Gecko type: "nsStaticAtom", "nsICSSPseudoElement", or "nsIAnonBoxPseudo"
|
# The Gecko type: "nsStaticAtom", "nsICSSPseudoElement", or "nsIAnonBoxPseudo"
|
||||||
self.ty = ty
|
self.ty = ty
|
||||||
# The type of atom: "Atom", "PseudoElement", "NonInheritingAnonBox",
|
# The type of atom: "Atom", "PseudoElement", "NonInheritingAnonBox",
|
||||||
|
|
@ -104,7 +106,8 @@ def collect_atoms(objdir):
|
||||||
with open(path) as f:
|
with open(path) as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
for result in PATTERN.finditer(content):
|
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
|
return atoms
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ class Atom():
|
||||||
self.string = string
|
self.string = string
|
||||||
self.ty = ty
|
self.ty = ty
|
||||||
self.atom_type = self.__class__.__name__
|
self.atom_type = self.__class__.__name__
|
||||||
|
self.hash = hash_string(string)
|
||||||
|
|
||||||
|
|
||||||
class PseudoElementAtom(Atom):
|
class PseudoElementAtom(Atom):
|
||||||
|
|
@ -29,3 +30,25 @@ class NonInheritingAnonBoxAtom(AnonBoxAtom):
|
||||||
class InheritingAnonBoxAtom(AnonBoxAtom):
|
class InheritingAnonBoxAtom(AnonBoxAtom):
|
||||||
def __init__(self, ident, string):
|
def __init__(self, ident, string):
|
||||||
AnonBoxAtom.__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"
|
"#ifdef small\n"
|
||||||
"#undef small\n"
|
"#undef small\n"
|
||||||
"#endif\n\n"
|
"#endif\n\n"
|
||||||
"// GK_ATOM(identifier, string, gecko_type, atom_type)\n" +
|
"// GK_ATOM(identifier, string, hash, gecko_type, atom_type)\n" +
|
||||||
"".join(["GK_ATOM(%s, \"%s\", %s, %s)\n" %
|
"".join(["GK_ATOM(%s, \"%s\", 0x%08x, %s, %s)\n" %
|
||||||
(a.ident, a.string, a.ty, a.atom_type)
|
(a.ident, a.string, a.hash, a.ty, a.atom_type)
|
||||||
for a in STATIC_ATOMS]))
|
for a in STATIC_ATOMS]))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "mozilla/HashFunctions.h"
|
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
@ -104,10 +103,10 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Used by nsStaticAtom.
|
// 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)
|
: mLength(aLength)
|
||||||
, mKind(static_cast<uint32_t>(nsAtom::AtomKind::Static))
|
, mKind(static_cast<uint32_t>(nsAtom::AtomKind::Static))
|
||||||
, mHash(mozilla::HashString(aStr))
|
, mHash(aHash)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Used by nsDynamicAtom.
|
// Used by nsDynamicAtom.
|
||||||
|
|
@ -138,9 +137,14 @@ public:
|
||||||
MozExternalRefCountType AddRef() = delete;
|
MozExternalRefCountType AddRef() = delete;
|
||||||
MozExternalRefCountType Release() = 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,
|
constexpr nsStaticAtom(const char16_t* aStr, uint32_t aLength,
|
||||||
uint32_t aStringOffset)
|
uint32_t aHash, uint32_t aStringOffset)
|
||||||
: nsAtom(aStr, aLength)
|
: nsAtom(aStr, aLength, aHash)
|
||||||
, mStringOffset(aStringOffset)
|
, mStringOffset(aStringOffset)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -647,6 +647,11 @@ nsAtomTable::RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen)
|
||||||
MOZ_ASSERT(nsCRT::IsAscii(atom->String()));
|
MOZ_ASSERT(nsCRT::IsAscii(atom->String()));
|
||||||
MOZ_ASSERT(NS_strlen(atom->String()) == atom->GetLength());
|
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);
|
AtomTableKey key(atom);
|
||||||
nsAtomSubTable& table = SelectSubTable(key);
|
nsAtomSubTable& table = SelectSubTable(key);
|
||||||
MutexAutoLock lock(table.mLock);
|
MutexAutoLock lock(table.mLock);
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,9 @@ NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, size_t aAtomsLen);
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
|
|
||||||
extern constexpr GkAtoms gGkAtoms = {
|
extern constexpr GkAtoms gGkAtoms = {
|
||||||
// The initialization of each atom's string.
|
// 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_,
|
u"" value_,
|
||||||
#include "nsGkAtomList.h"
|
#include "nsGkAtomList.h"
|
||||||
#undef GK_ATOM
|
#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
|
// 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
|
// to the number of chars (including the terminating '\0'). The |u""| prefix
|
||||||
// converts |value_| to a 16-bit string.
|
// 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_, \
|
nsStaticAtom(u"" value_, \
|
||||||
sizeof(value_) - 1, \
|
sizeof(value_) - 1, \
|
||||||
|
hash_, \
|
||||||
offsetof(GkAtoms, \
|
offsetof(GkAtoms, \
|
||||||
mAtoms[static_cast<size_t>(GkAtoms::Atoms::name_)]) - \
|
mAtoms[static_cast<size_t>(GkAtoms::Atoms::name_)]) - \
|
||||||
offsetof(GkAtoms, name_##_string)),
|
offsetof(GkAtoms, name_##_string)),
|
||||||
|
|
@ -36,7 +36,6 @@ extern constexpr GkAtoms gGkAtoms = {
|
||||||
#undef GK_ATOM
|
#undef GK_ATOM
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
@ -44,7 +43,7 @@ MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
|
||||||
const nsStaticAtom* const nsGkAtoms::sAtoms = mozilla::detail::gGkAtoms.mAtoms;
|
const nsStaticAtom* const nsGkAtoms::sAtoms = mozilla::detail::gGkAtoms.mAtoms;
|
||||||
|
|
||||||
// Definition of the pointer to the static atom.
|
// 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_*>( \
|
type_* nsGkAtoms::name_ = const_cast<type_*>(static_cast<const type_*>( \
|
||||||
&mozilla::detail::gGkAtoms.mAtoms[ \
|
&mozilla::detail::gGkAtoms.mAtoms[ \
|
||||||
static_cast<size_t>(mozilla::detail::GkAtoms::Atoms::name_)]));
|
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
|
// nsGkAtomList.h is generated by StaticAtoms.py and has entries that look
|
||||||
// like this:
|
// like this:
|
||||||
//
|
//
|
||||||
// GK_ATOM(one, "one", nsStaticAtom, Atom)
|
// GK_ATOM(one, "one", 0x01234567, nsStaticAtom, Atom)
|
||||||
// GK_ATOM(two, "two", nsICSSPseudoElement, PseudoElementAtom)
|
// GK_ATOM(two, "two", 0x12345678, nsICSSPseudoElement, PseudoElementAtom)
|
||||||
// GK_ATOM(three, "three", nsICSSAnonBoxPseudo, InheritingAnonBoxAtom)
|
// GK_ATOM(three, "three", 0x23456789, nsICSSAnonBoxPseudo, InheritingAnonBoxAtom)
|
||||||
//
|
//
|
||||||
// After macro expansion, the atom definitions look like the following:
|
// After macro expansion, the atom definitions look like the following:
|
||||||
//
|
//
|
||||||
|
|
@ -120,14 +120,17 @@
|
||||||
// // The initialization of the atoms themselves.
|
// // The initialization of the atoms themselves.
|
||||||
// nsStaticAtom(
|
// nsStaticAtom(
|
||||||
// u"one", 3,
|
// u"one", 3,
|
||||||
|
// 0x01234567,
|
||||||
// offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::one)]) -
|
// offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::one)]) -
|
||||||
// offsetof(GkAtoms, one_string)),
|
// offsetof(GkAtoms, one_string)),
|
||||||
// nsStaticAtom(
|
// nsStaticAtom(
|
||||||
// u"two", 3,
|
// u"two", 3,
|
||||||
|
// 0x12345678,
|
||||||
// offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::two)]) -
|
// offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::two)]) -
|
||||||
// offsetof(GkAtoms, two_string)),
|
// offsetof(GkAtoms, two_string)),
|
||||||
// nsStaticAtom(
|
// nsStaticAtom(
|
||||||
// u"three", 3,
|
// u"three", 3,
|
||||||
|
// 0x23456789,
|
||||||
// offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::three)]) -
|
// offsetof(GkAtoms, mAtoms[static_cast<size_t>(GkAtoms::Atoms::three)]) -
|
||||||
// offsetof(GkAtoms, three_string)),
|
// offsetof(GkAtoms, three_string)),
|
||||||
// }
|
// }
|
||||||
|
|
@ -156,12 +159,13 @@
|
||||||
|
|
||||||
// Trivial subclasses of nsStaticAtom so that function signatures can require
|
// Trivial subclasses of nsStaticAtom so that function signatures can require
|
||||||
// an atom from a specific atom list.
|
// an atom from a specific atom list.
|
||||||
#define DEFINE_STATIC_ATOM_SUBCLASS(name_) \
|
#define DEFINE_STATIC_ATOM_SUBCLASS(name_) \
|
||||||
class name_ : public nsStaticAtom \
|
class name_ : public nsStaticAtom \
|
||||||
{ \
|
{ \
|
||||||
public: \
|
public: \
|
||||||
constexpr name_(const char16_t* aStr, uint32_t aLength, uint32_t aOffset) \
|
constexpr name_(const char16_t* aStr, uint32_t aLength, \
|
||||||
: nsStaticAtom(aStr, aLength, aOffset) {} \
|
uint32_t aHash, uint32_t aOffset) \
|
||||||
|
: nsStaticAtom(aStr, aLength, aHash, aOffset) {} \
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STATIC_ATOM_SUBCLASS(nsICSSAnonBoxPseudo)
|
DEFINE_STATIC_ATOM_SUBCLASS(nsICSSAnonBoxPseudo)
|
||||||
|
|
@ -181,14 +185,14 @@ namespace detail {
|
||||||
struct GkAtoms
|
struct GkAtoms
|
||||||
{
|
{
|
||||||
// The declaration of each atom's string.
|
// 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_)];
|
const char16_t name_##_string[sizeof(value_)];
|
||||||
#include "nsGkAtomList.h"
|
#include "nsGkAtomList.h"
|
||||||
#undef GK_ATOM
|
#undef GK_ATOM
|
||||||
|
|
||||||
// The enum value for each atom.
|
// The enum value for each atom.
|
||||||
enum class Atoms {
|
enum class Atoms {
|
||||||
#define GK_ATOM(name_, value_, type_, atom_type_) \
|
#define GK_ATOM(name_, value_, hash_, type_, atom_type_) \
|
||||||
name_,
|
name_,
|
||||||
#include "nsGkAtomList.h"
|
#include "nsGkAtomList.h"
|
||||||
#undef GK_ATOM
|
#undef GK_ATOM
|
||||||
|
|
@ -221,7 +225,7 @@ public:
|
||||||
//
|
//
|
||||||
// XXX: Eventually this should be combined with its definition and the
|
// XXX: Eventually this should be combined with its definition and the
|
||||||
// pointer should be made `constexpr`. See bug 1449787.
|
// 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_;
|
static type_* name_;
|
||||||
#include "nsGkAtomList.h"
|
#include "nsGkAtomList.h"
|
||||||
#undef GK_ATOM
|
#undef GK_ATOM
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue