2012-05-29 15:52:43 +00: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/. */
|
2009-09-18 15:13:10 +00:00
|
|
|
|
2013-08-23 15:07:10 +00:00
|
|
|
#ifndef nsHtml5AtomTable_h
|
|
|
|
#define nsHtml5AtomTable_h
|
2009-09-18 15:13:10 +00:00
|
|
|
|
|
|
|
#include "nsHashKeys.h"
|
|
|
|
#include "nsTHashtable.h"
|
2017-10-02 22:05:19 +00:00
|
|
|
#include "nsAtom.h"
|
2017-06-07 23:23:29 +00:00
|
|
|
#include "nsISerialEventTarget.h"
|
2009-09-18 15:13:10 +00:00
|
|
|
|
2017-04-03 10:12:05 +00:00
|
|
|
#define RECENTLY_USED_PARSER_ATOMS_SIZE 31
|
|
|
|
|
2009-09-18 15:13:10 +00:00
|
|
|
class nsHtml5AtomEntry : public nsStringHashKey
|
|
|
|
{
|
2018-03-16 15:26:06 +00:00
|
|
|
public:
|
|
|
|
explicit nsHtml5AtomEntry(KeyTypePointer aStr);
|
Bug 1415980 - make hash keys movable and not copyable; r=erahm
Everything that goes in a PLDHashtable (and its derivatives, like
nsTHashtable) needs to inherit from PLDHashEntryHdr. But through a lack
of enforcement, copy constructors for these derived classes didn't
explicitly invoke the copy constructor for PLDHashEntryHdr (and the
compiler didn't invoke the copy constructor for us). Instead,
PLDHashTable explicitly copied around the bits that the copy constructor
would have.
The current setup has two problems:
1) Derived classes should be using move construction, not copy
construction, since anything that's shuffling hash table keys/entries
around will be using move construction.
2) Derived classes should take responsibility for transferring bits of
superclass state around, and not rely on something else to handle that.
The second point is not a huge problem for PLDHashTable (PLDHashTable
only has to copy PLDHashEntryHdr's bits in a single place), but future
hash table implementations that might move entries around more
aggressively would have to insert compensation code all over the
place. Additionally, if moving entries is implemented via memcpy (which
is quite common), PLDHashTable copying around bits *again* is
inefficient.
Let's fix all these problems in one go, by:
1) Explicitly declaring the set of constructors that PLDHashEntryHdr
implements (and does not implement). In particular, the copy
constructor is deleted, so any derived classes that attempt to make
themselves copyable will be detected at compile time: the compiler
will complain that the superclass type is not copyable.
This change on its own will result in many compiler errors, so...
2) Change any derived classes to implement move constructors instead of
copy constructors. Note that some of these move constructors are,
strictly speaking, unnecessary, since the relevant classes are moved
via memcpy in nsTHashtable and its derivatives.
2018-09-20 15:20:36 +00:00
|
|
|
nsHtml5AtomEntry(nsHtml5AtomEntry&& aOther);
|
2018-03-16 15:26:06 +00:00
|
|
|
~nsHtml5AtomEntry();
|
|
|
|
inline nsAtom* GetAtom() { return mAtom; }
|
|
|
|
|
|
|
|
private:
|
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 01:59:11 +00:00
|
|
|
nsDynamicAtom* mAtom;
|
2009-09-18 15:13:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2018-03-16 15:26:06 +00:00
|
|
|
* nsHtml5AtomTable provides non-locking lookup and creation of atoms for
|
2009-09-18 15:13:10 +00:00
|
|
|
* nsHtml5Parser or nsHtml5StreamParser.
|
|
|
|
*
|
2018-03-16 15:26:06 +00:00
|
|
|
* The hashtable holds dynamically allocated atoms that are private to an
|
|
|
|
* instance of nsHtml5Parser or nsHtml5StreamParser. (Static atoms are used on
|
|
|
|
* interned nsHtml5ElementNames and interned nsHtml5AttributeNames. Also, when
|
|
|
|
* the doctype name is 'html', that identifier needs to be represented as a
|
2009-09-18 15:13:10 +00:00
|
|
|
* static atom.)
|
|
|
|
*
|
2018-03-16 15:26:06 +00:00
|
|
|
* Each instance of nsHtml5Parser has a single instance of nsHtml5AtomTable,
|
|
|
|
* and each instance of nsHtml5StreamParser has a single instance of
|
|
|
|
* nsHtml5AtomTable. Dynamic atoms obtained from an nsHtml5AtomTable are valid
|
|
|
|
* for == comparison with each other or with atoms declared in nsHtml5Atoms
|
|
|
|
* within the nsHtml5Tokenizer and the nsHtml5TreeBuilder instances owned by
|
|
|
|
* the same nsHtml5Parser/nsHtml5StreamParser instance that owns the
|
2009-09-18 15:13:10 +00:00
|
|
|
* nsHtml5AtomTable instance.
|
2018-03-16 15:26:06 +00:00
|
|
|
*
|
|
|
|
* Dynamic atoms (atoms whose IsStatic() returns false) obtained from
|
|
|
|
* nsHtml5AtomTable must be re-obtained from another atom table when there's a
|
|
|
|
* need to migrate atoms from an nsHtml5Parser to its nsHtml5StreamParser
|
|
|
|
* (re-obtain from the other nsHtml5AtomTable), from an nsHtml5Parser to its
|
|
|
|
* owner nsHtml5Parser (re-obtain from the other nsHtml5AtomTable) or from the
|
|
|
|
* parser to the DOM (re-obtain from the application-wide atom table). To
|
|
|
|
* re-obtain an atom from another atom table, obtain a string from the atom
|
|
|
|
* using ToString(nsAString&) and look up an atom in the other table using that
|
2009-09-18 15:13:10 +00:00
|
|
|
* string.
|
|
|
|
*
|
2018-03-16 15:26:06 +00:00
|
|
|
* An instance of nsHtml5AtomTable that belongs to an nsHtml5Parser is only
|
|
|
|
* accessed from the main thread. An instance of nsHtml5AtomTable that belongs
|
|
|
|
* to an nsHtml5StreamParser is accessed both from the main thread and from the
|
|
|
|
* thread that executes the runnables of the nsHtml5StreamParser instance.
|
|
|
|
* However, the threads never access the nsHtml5AtomTable instance concurrently
|
2009-09-18 15:13:10 +00:00
|
|
|
* in the nsHtml5StreamParser case.
|
|
|
|
*
|
2018-03-16 15:26:06 +00:00
|
|
|
* Methods on the atoms obtained from nsHtml5AtomTable may be called on any
|
|
|
|
* thread, although they only need to be called on the main thread or on the
|
|
|
|
* thread working for the nsHtml5StreamParser when nsHtml5AtomTable belongs to
|
2009-09-18 15:13:10 +00:00
|
|
|
* an nsHtml5StreamParser.
|
|
|
|
*
|
2018-03-16 15:26:06 +00:00
|
|
|
* Dynamic atoms obtained from nsHtml5AtomTable are deleted when the
|
|
|
|
* nsHtml5AtomTable itself is destructed, which happens when the owner
|
2009-09-18 15:13:10 +00:00
|
|
|
* nsHtml5Parser or nsHtml5StreamParser is destructed.
|
|
|
|
*/
|
|
|
|
class nsHtml5AtomTable
|
|
|
|
{
|
2018-03-16 15:26:06 +00:00
|
|
|
public:
|
|
|
|
nsHtml5AtomTable();
|
|
|
|
~nsHtml5AtomTable();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Obtains the atom for the given string in the scope of this atom table.
|
|
|
|
*/
|
|
|
|
nsAtom* GetAtom(const nsAString& aKey);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Empties the table.
|
|
|
|
*/
|
|
|
|
void Clear()
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < RECENTLY_USED_PARSER_ATOMS_SIZE; ++i) {
|
|
|
|
mRecentlyUsedParserAtoms[i] = nullptr;
|
2009-09-18 15:13:10 +00:00
|
|
|
}
|
2018-03-16 15:26:06 +00:00
|
|
|
mTable.Clear();
|
|
|
|
}
|
|
|
|
|
2009-09-18 15:13:10 +00:00
|
|
|
#ifdef DEBUG
|
2018-03-16 15:26:06 +00:00
|
|
|
void SetPermittedLookupEventTarget(nsISerialEventTarget* aEventTarget)
|
|
|
|
{
|
|
|
|
mPermittedLookupEventTarget = aEventTarget;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsTHashtable<nsHtml5AtomEntry> mTable;
|
|
|
|
nsAtom* mRecentlyUsedParserAtoms[RECENTLY_USED_PARSER_ATOMS_SIZE];
|
2009-09-18 15:13:10 +00:00
|
|
|
#ifdef DEBUG
|
2018-03-16 15:26:06 +00:00
|
|
|
nsCOMPtr<nsISerialEventTarget> mPermittedLookupEventTarget;
|
2009-09-18 15:13:10 +00:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2013-08-23 15:07:10 +00:00
|
|
|
#endif // nsHtml5AtomTable_h
|