2017-10-27 20:33:53 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2006-03-25 08:47:31 +03:00
|
|
|
|
|
|
|
/* atom list for CSS anonymous boxes */
|
|
|
|
|
2002-11-17 18:37:56 +03:00
|
|
|
#ifndef nsCSSAnonBoxes_h___
|
|
|
|
#define nsCSSAnonBoxes_h___
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
#include "nsAtom.h"
|
2017-10-22 00:50:25 +03:00
|
|
|
#include "nsStaticAtom.h"
|
1998-12-11 05:51:05 +03:00
|
|
|
|
Bug 1449395 - Remove nsStaticAtomSetup. r=froydnj
Each nsStaticAtomSetup contains a pointer to a static atom, and also a pointer
to the canonical pointer to that static atom. Which is pretty weird! The
notable thing thing about it is that these structs are in an array, and that
gives us the only way to iterate over all static atoms in a single class, for
registration and lookups.
But thanks to various other recent changes to the implementation of static
atoms, we can now put the static atoms themselves into an array, which can be
iterated over. So this patch does that. With that done, nsStaticAtomSetup is no
longer necessary.
According to the `size` utility, on Linux64 this reduces the size of libxul.so
by the following amounts:
> text: 62008 bytes
> data: 20992 bytes
> bss: 21040 bytes
> total: 104040 bytes
- The bss reduction is one word per atom, because the canonical static atom
pointers (e.g. nsGkAtoms::foo) have moved from .bss to .data, because they're
now initialized at compile time instead of runtime.
- The data reduction is one word per atom, because we remove two words per atom
for the nsStaticAtomSetup removal, but gain one word per atom from the
previous bullet point.
- I'm not sure about the text reduction. It's three words per atom. Maybe
because there is one less relocation per atom?
Other notable things in the patch:
- nsICSSAnonBoxPseudo and nsICSSPseudoElement now inherit from nsStaticAtom,
not nsAtom, because that's more precise.
- Each static atoms array now has an enum associated with it, which is used in
various ways.
- In the big comment about the macros at the top of nsStaticAtom.h, the pre-
and post-expansion forms are now shown interleaved. The interleaving reduces
duplication and makes the comment much easier to read and maintain. The
comment also has an introduction that explains the constraints and goals of
the implementation.
- The SUBCLASS macro variations are gone. There are few enough users of these
macros now that always passing the atom type has become simpler.
MozReview-Commit-ID: 1GmfKidLjaU
--HG--
extra : rebase_source : 2352590101fc6693ba388f885ca4714a42963943
2018-03-29 03:48:18 +03:00
|
|
|
// Trivial subclass of nsStaticAtom so that function signatures can require an
|
|
|
|
// atom from this atom list.
|
|
|
|
class nsICSSAnonBoxPseudo : public nsStaticAtom
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
constexpr nsICSSAnonBoxPseudo(const char16_t* aStr, uint32_t aLength,
|
|
|
|
uint32_t aStringOffset)
|
|
|
|
: nsStaticAtom(aStr, aLength, aStringOffset)
|
|
|
|
{}
|
|
|
|
};
|
1998-12-11 05:51:05 +03:00
|
|
|
|
Bug 1411469 - Statically allocate static atoms. r=froydnj
Currently static atoms are stored on the heap, but their char buffers are
stored in read-only static memory.
This patch changes the representation of nsStaticAtom (thus making it a
non-trivial subclass of nsAtom). Instead of a pointer to the string, it now has
an mStringOffset field which is a 32-bit offset to the string. (This requires
placement of the string and the atom within the same object so that the offset
is known to be small. The docs and macros in nsStaticAtom.h handle that.)
Static and dynamic atoms now store their chars in different ways: nsStaticAtom
stores them inline, nsDynamicAtom has a pointer to separate storage. So
`mString` and GetStringBuffer() move from nsAtom to nsDynamicAtom.
The change to static atoms means they can be made constexpr and stored in
read-only memory instead of on the heap. On 64-bit this reduces the per-process
overhead by 16 bytes; on 32-bit the saving is 12 bytes. (Further reductions
will be possible in follow-up patches.)
The increased use of constexpr required multiple workarounds for MSVC.
- Multiple uses of MOZ_{PUSH,POP}_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING to
disable warnings about (well-defined!) overflow of unsigned integer
arithmetic.
- The use of -Zc:externConstexpr on all files defining static atoms, to make
MSVC follow the C++ standard(!) and let constexpr variables have external
linkage.
- The use of -constexpr:steps300000 to increase the number of operations
allowed in a constexpr value, in order to handle gGkAtoms, which requires
hashing ~2,500 atom strings.
The patch also changes how HTML5 atoms are handled. They are now treated as
dynamic atoms, i.e. we have "dynamic normal" atoms and "dynamic HTML5 atoms",
and "dynamic atoms" covers both cases, and both are represented via
nsDynamicAtom. The main difference between the two kinds is that dynamic HTML5
atoms still aren't allowed to be used in various operations, most notably
AddRef()/Release(). All this also required moving nsDynamicAtom into the header
file.
There is a slight performance cost to all these changes: now that nsStaticAtom
and nsDynamicAtom store their chars in different ways, a conditional branch is
required in the following functions: Equals(), GetUTF16String(),
WeakAtom::as_slice().
Finally, in about:memory the "explicit/atoms/static/atom-objects" value is no
longer needed, because that memory is static instead of heap-allocated.
MozReview-Commit-ID: 4AxPv05ngZy
2018-03-08 04:59:11 +03:00
|
|
|
namespace mozilla {
|
|
|
|
namespace detail {
|
|
|
|
|
|
|
|
struct CSSAnonBoxAtoms
|
|
|
|
{
|
|
|
|
#define CSS_ANON_BOX(name_, value_) NS_STATIC_ATOM_DECL_STRING(name_, value_)
|
|
|
|
#include "nsCSSAnonBoxList.h"
|
|
|
|
#undef CSS_ANON_BOX
|
|
|
|
|
Bug 1449395 - Remove nsStaticAtomSetup. r=froydnj
Each nsStaticAtomSetup contains a pointer to a static atom, and also a pointer
to the canonical pointer to that static atom. Which is pretty weird! The
notable thing thing about it is that these structs are in an array, and that
gives us the only way to iterate over all static atoms in a single class, for
registration and lookups.
But thanks to various other recent changes to the implementation of static
atoms, we can now put the static atoms themselves into an array, which can be
iterated over. So this patch does that. With that done, nsStaticAtomSetup is no
longer necessary.
According to the `size` utility, on Linux64 this reduces the size of libxul.so
by the following amounts:
> text: 62008 bytes
> data: 20992 bytes
> bss: 21040 bytes
> total: 104040 bytes
- The bss reduction is one word per atom, because the canonical static atom
pointers (e.g. nsGkAtoms::foo) have moved from .bss to .data, because they're
now initialized at compile time instead of runtime.
- The data reduction is one word per atom, because we remove two words per atom
for the nsStaticAtomSetup removal, but gain one word per atom from the
previous bullet point.
- I'm not sure about the text reduction. It's three words per atom. Maybe
because there is one less relocation per atom?
Other notable things in the patch:
- nsICSSAnonBoxPseudo and nsICSSPseudoElement now inherit from nsStaticAtom,
not nsAtom, because that's more precise.
- Each static atoms array now has an enum associated with it, which is used in
various ways.
- In the big comment about the macros at the top of nsStaticAtom.h, the pre-
and post-expansion forms are now shown interleaved. The interleaving reduces
duplication and makes the comment much easier to read and maintain. The
comment also has an introduction that explains the constraints and goals of
the implementation.
- The SUBCLASS macro variations are gone. There are few enough users of these
macros now that always passing the atom type has become simpler.
MozReview-Commit-ID: 1GmfKidLjaU
--HG--
extra : rebase_source : 2352590101fc6693ba388f885ca4714a42963943
2018-03-29 03:48:18 +03:00
|
|
|
enum class Atoms {
|
|
|
|
#define CSS_ANON_BOX(name_, value_) \
|
|
|
|
NS_STATIC_ATOM_ENUM(name_)
|
|
|
|
#include "nsCSSAnonBoxList.h"
|
|
|
|
#undef CSS_ANON_BOX
|
|
|
|
AtomsCount
|
|
|
|
};
|
|
|
|
|
|
|
|
const nsICSSAnonBoxPseudo mAtoms[static_cast<size_t>(Atoms::AtomsCount)];
|
Bug 1411469 - Statically allocate static atoms. r=froydnj
Currently static atoms are stored on the heap, but their char buffers are
stored in read-only static memory.
This patch changes the representation of nsStaticAtom (thus making it a
non-trivial subclass of nsAtom). Instead of a pointer to the string, it now has
an mStringOffset field which is a 32-bit offset to the string. (This requires
placement of the string and the atom within the same object so that the offset
is known to be small. The docs and macros in nsStaticAtom.h handle that.)
Static and dynamic atoms now store their chars in different ways: nsStaticAtom
stores them inline, nsDynamicAtom has a pointer to separate storage. So
`mString` and GetStringBuffer() move from nsAtom to nsDynamicAtom.
The change to static atoms means they can be made constexpr and stored in
read-only memory instead of on the heap. On 64-bit this reduces the per-process
overhead by 16 bytes; on 32-bit the saving is 12 bytes. (Further reductions
will be possible in follow-up patches.)
The increased use of constexpr required multiple workarounds for MSVC.
- Multiple uses of MOZ_{PUSH,POP}_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING to
disable warnings about (well-defined!) overflow of unsigned integer
arithmetic.
- The use of -Zc:externConstexpr on all files defining static atoms, to make
MSVC follow the C++ standard(!) and let constexpr variables have external
linkage.
- The use of -constexpr:steps300000 to increase the number of operations
allowed in a constexpr value, in order to handle gGkAtoms, which requires
hashing ~2,500 atom strings.
The patch also changes how HTML5 atoms are handled. They are now treated as
dynamic atoms, i.e. we have "dynamic normal" atoms and "dynamic HTML5 atoms",
and "dynamic atoms" covers both cases, and both are represented via
nsDynamicAtom. The main difference between the two kinds is that dynamic HTML5
atoms still aren't allowed to be used in various operations, most notably
AddRef()/Release(). All this also required moving nsDynamicAtom into the header
file.
There is a slight performance cost to all these changes: now that nsStaticAtom
and nsDynamicAtom store their chars in different ways, a conditional branch is
required in the following functions: Equals(), GetUTF16String(),
WeakAtom::as_slice().
Finally, in about:memory the "explicit/atoms/static/atom-objects" value is no
longer needed, because that memory is static instead of heap-allocated.
MozReview-Commit-ID: 4AxPv05ngZy
2018-03-08 04:59:11 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
extern const CSSAnonBoxAtoms gCSSAnonBoxAtoms;
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
} // namespace mozilla
|
|
|
|
|
2002-11-17 18:37:56 +03:00
|
|
|
class nsCSSAnonBoxes {
|
|
|
|
public:
|
1998-12-11 05:51:05 +03:00
|
|
|
|
2018-03-20 05:01:30 +03:00
|
|
|
static void RegisterStaticAtoms();
|
1998-12-11 05:51:05 +03:00
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
static bool IsAnonBox(nsAtom *aAtom);
|
2009-10-08 07:22:42 +04:00
|
|
|
#ifdef MOZ_XUL
|
2017-10-03 01:05:19 +03:00
|
|
|
static bool IsTreePseudoElement(nsAtom* aPseudo);
|
2009-10-08 07:22:42 +04:00
|
|
|
#endif
|
2017-10-03 01:05:19 +03:00
|
|
|
static bool IsNonElement(nsAtom* aPseudo)
|
2017-03-08 08:18:32 +03:00
|
|
|
{
|
|
|
|
return aPseudo == mozText || aPseudo == oofPlaceholder ||
|
|
|
|
aPseudo == firstLetterContinuation;
|
|
|
|
}
|
1998-12-11 05:51:05 +03:00
|
|
|
|
Bug 1449395 - Remove nsStaticAtomSetup. r=froydnj
Each nsStaticAtomSetup contains a pointer to a static atom, and also a pointer
to the canonical pointer to that static atom. Which is pretty weird! The
notable thing thing about it is that these structs are in an array, and that
gives us the only way to iterate over all static atoms in a single class, for
registration and lookups.
But thanks to various other recent changes to the implementation of static
atoms, we can now put the static atoms themselves into an array, which can be
iterated over. So this patch does that. With that done, nsStaticAtomSetup is no
longer necessary.
According to the `size` utility, on Linux64 this reduces the size of libxul.so
by the following amounts:
> text: 62008 bytes
> data: 20992 bytes
> bss: 21040 bytes
> total: 104040 bytes
- The bss reduction is one word per atom, because the canonical static atom
pointers (e.g. nsGkAtoms::foo) have moved from .bss to .data, because they're
now initialized at compile time instead of runtime.
- The data reduction is one word per atom, because we remove two words per atom
for the nsStaticAtomSetup removal, but gain one word per atom from the
previous bullet point.
- I'm not sure about the text reduction. It's three words per atom. Maybe
because there is one less relocation per atom?
Other notable things in the patch:
- nsICSSAnonBoxPseudo and nsICSSPseudoElement now inherit from nsStaticAtom,
not nsAtom, because that's more precise.
- Each static atoms array now has an enum associated with it, which is used in
various ways.
- In the big comment about the macros at the top of nsStaticAtom.h, the pre-
and post-expansion forms are now shown interleaved. The interleaving reduces
duplication and makes the comment much easier to read and maintain. The
comment also has an introduction that explains the constraints and goals of
the implementation.
- The SUBCLASS macro variations are gone. There are few enough users of these
macros now that always passing the atom type has become simpler.
MozReview-Commit-ID: 1GmfKidLjaU
--HG--
extra : rebase_source : 2352590101fc6693ba388f885ca4714a42963943
2018-03-29 03:48:18 +03:00
|
|
|
private:
|
|
|
|
static const nsStaticAtom* const sAtoms;
|
|
|
|
static constexpr size_t sAtomsLen =
|
|
|
|
mozilla::ArrayLength(mozilla::detail::gCSSAnonBoxAtoms.mAtoms);
|
|
|
|
|
|
|
|
public:
|
|
|
|
#define CSS_ANON_BOX(name_, value_) \
|
|
|
|
NS_STATIC_ATOM_DECL_PTR(nsICSSAnonBoxPseudo, name_)
|
|
|
|
#include "nsCSSAnonBoxList.h"
|
|
|
|
#undef CSS_ANON_BOX
|
2017-03-08 08:18:39 +03:00
|
|
|
|
|
|
|
typedef uint8_t NonInheritingBase;
|
|
|
|
enum class NonInheriting : NonInheritingBase {
|
2017-07-05 09:21:10 +03:00
|
|
|
#define CSS_ANON_BOX(_name, _value) /* nothing */
|
2017-03-08 08:18:39 +03:00
|
|
|
#define CSS_NON_INHERITING_ANON_BOX(_name, _value) _name,
|
|
|
|
#include "nsCSSAnonBoxList.h"
|
|
|
|
#undef CSS_NON_INHERITING_ANON_BOX
|
|
|
|
#undef CSS_ANON_BOX
|
|
|
|
_Count
|
|
|
|
};
|
|
|
|
|
|
|
|
// Be careful using this: if we have a lot of non-inheriting anon box types it
|
|
|
|
// might not be very fast. We may want to think of ways to handle that
|
|
|
|
// (e.g. by moving to an enum instead of an atom, like we did for
|
|
|
|
// pseudo-elements, or by adding a new value of the pseudo-element enum for
|
|
|
|
// non-inheriting anon boxes or something).
|
2017-10-03 01:05:19 +03:00
|
|
|
static bool IsNonInheritingAnonBox(nsAtom* aPseudo)
|
2017-03-08 08:18:39 +03:00
|
|
|
{
|
|
|
|
return
|
2017-07-05 09:21:10 +03:00
|
|
|
#define CSS_ANON_BOX(_name, _value) /* nothing */
|
2017-03-08 08:18:39 +03:00
|
|
|
#define CSS_NON_INHERITING_ANON_BOX(_name, _value) _name == aPseudo ||
|
|
|
|
#include "nsCSSAnonBoxList.h"
|
|
|
|
#undef CSS_NON_INHERITING_ANON_BOX
|
|
|
|
#undef CSS_ANON_BOX
|
2017-03-09 07:39:47 +03:00
|
|
|
false;
|
2017-03-08 08:18:39 +03:00
|
|
|
}
|
|
|
|
|
2017-08-05 00:34:18 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
// NOTE(emilio): DEBUG only because this does a pretty slow linear search. Try
|
|
|
|
// to use IsNonInheritingAnonBox if you know the atom is an anon box already
|
2017-08-11 07:07:12 +03:00
|
|
|
// or, even better, nothing like this. Note that this function returns true
|
|
|
|
// for wrapper anon boxes as well, since they're all inheriting.
|
2017-10-03 01:05:19 +03:00
|
|
|
static bool IsInheritingAnonBox(nsAtom* aPseudo)
|
2017-08-05 00:34:18 +03:00
|
|
|
{
|
|
|
|
return
|
|
|
|
#define CSS_ANON_BOX(_name, _value) _name == aPseudo ||
|
|
|
|
#define CSS_NON_INHERITING_ANON_BOX(_name, _value) /* nothing */
|
|
|
|
#include "nsCSSAnonBoxList.h"
|
|
|
|
#undef CSS_NON_INHERITING_ANON_BOX
|
|
|
|
#undef CSS_ANON_BOX
|
|
|
|
false;
|
|
|
|
}
|
2017-08-11 07:07:12 +03:00
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
// This function is rather slow; you probably don't want to use it outside
|
|
|
|
// asserts unless you have to.
|
2017-10-03 01:05:19 +03:00
|
|
|
static bool IsWrapperAnonBox(nsAtom* aPseudo) {
|
2017-08-11 07:07:12 +03:00
|
|
|
// We commonly get null passed here, and want to quickly return false for
|
|
|
|
// it.
|
|
|
|
return aPseudo &&
|
|
|
|
(
|
|
|
|
#define CSS_ANON_BOX(_name, _value) /* nothing */
|
|
|
|
#define CSS_WRAPPER_ANON_BOX(_name, _value) _name == aPseudo ||
|
|
|
|
#define CSS_NON_INHERITING_ANON_BOX(_name, _value) /* nothing */
|
|
|
|
#include "nsCSSAnonBoxList.h"
|
|
|
|
#undef CSS_NON_INHERITING_ANON_BOX
|
|
|
|
#undef CSS_WRAPPER_ANON_BOX
|
|
|
|
#undef CSS_ANON_BOX
|
|
|
|
false);
|
|
|
|
}
|
2017-08-05 00:34:18 +03:00
|
|
|
|
2017-03-09 07:39:47 +03:00
|
|
|
// Get the NonInheriting type for a given pseudo tag. The pseudo tag must
|
|
|
|
// test true for IsNonInheritingAnonBox.
|
2017-10-03 01:05:19 +03:00
|
|
|
static NonInheriting NonInheritingTypeForPseudoTag(nsAtom* aPseudo);
|
2002-11-17 18:37:56 +03:00
|
|
|
};
|
1998-12-11 05:51:05 +03:00
|
|
|
|
2002-11-17 18:37:56 +03:00
|
|
|
#endif /* nsCSSAnonBoxes_h___ */
|