After this change, we have PLDHashTable::ShallowSizeOf{In,Ex}cludingThis(),
which don't do anything to measure children. (They can be combined with
iteration to measure children.)
This patch also removes the PL_DHashTableSizeOf{In,Ex}cludingThis() functions.
They're not necessary because the methods can be used instead.
Finally, the patch deliberately converts some SizeOfExcludingThis() calls to
SizeOfIncludingThis(). These are all done on heap pointers so this change is
valid.
--HG--
extra : rebase_source : b1d51096a8e7dcac29d7efd92e28938836ff5481
The original motivation for the Iterator/RemovingIterator split was that
PLDHashTable Checker class would treat them differently. But that didn't end up
happening (see bug 1131308). So this patch merges them. This is a small code
size win now but it will become bigger when I add iterators to nsTHashTable and
nsBaseHashtable.
The only complication is that PLDHashTable::Iter() is now non-const, which is
a problem if you use it in a const method. So I added PLDHashTable::ConstIter()
which is used in just two places. It's a bit of a hack -- effectively a
const_cast -- but I don't think it's too bad.
- Its move constructor was moving |aOther.mTable| instead of |aOther|. This
meant that |aOther| wasn't being zeroed out appropriately.
- test_pldhash_RemovingIterator() was testing Iterator's move constructor
instead of RemovingIterator's move constructor, due to a copy/paste
mistake.
--HG--
extra : rebase_source : 1f4880893875218ddb155c76d329e84d884c0432
This patch factors out the existing capacity calculation code in HashShift()
into a new function called BestCapacity(), and then reuses it for
post-enumeration shrinking.
BestCapacity() computes capacity with |CeilingLog2(ceil(length * 4 / 3))|,
which ensures a minimum capacity while respecting the "max 75% full" and
"capacity is a power of two" constraints. In contrast, the old post-enumeration
shrink calculation was |CeilingLog2(length + length/2)|, which gives higher
results in some cases. (Both calculations also ensured the capacity wasn't too
small.) E.g. if length is 48, the former calculation will give 64, while the
latter will give 128.
Therefore, post-enumeration shrinking will no longer give a
larger-than-necessary capacity some cases. This feels like the right thing to
do in isolation, and making it consistent with HashShift() -- used during table
construction -- is also good.
--HG--
extra : rebase_source : 55e982b601c345d10da7abd03a13aec3f5b61598
This change splits PLDHashTable::Iterator::NextEntry() into two separate
functions, which allow you to get the current element and advance the iterator
separately, which means you can use a for-loop to iterate instead of a
while-loop.
As part of this change, the internals of PLDHashTable::Iterator were
significantly changed and simplified (and modelled after js::HashTable's
equivalent code). It's no longer duplicating code from PL_DHashTableEnumerator.
The chaos mode code was a casualty of this, but given how unreliable that code
has proven to be (see bug 1173212, bug 1174046) this is for the best. (We can
reimplement chaos mode once PLDHashTable::Iterator is back on more solid
footing again, if we think it's important.)
All these changes will make it much easier to add an alternative Iterator that
removes elements, which was turning out to be difficult with the prior code.
In order to make the for-loop header usually fit on a single line, I
deliberately renamed a bunch of things to have shorter names.
In summary, you used to write this:
PLDHashTable::Iterator iter(&table);
while (iter.HasMoreEntries()) {
auto entry = static_cast<FooEntry*>(iter.NextEntry());
// ... do stuff with |entry| ...
}
// iter's scope extends beyond here
and now you write this:
for (auto iter = table.Iter(); !iter.Done(); iter.Next()) {
auto entry = static_cast<FooEntry*>(iter.Get());
// ... do stuff with |entry| ...
}
// iter's scope doesn't reach here
--HG--
extra : rebase_source : fa5cac2fc50b1ab7624030bced4763131280f4d8
CLOSED TREE
If you use PLDHashTable::Iterator in chaos mode with a table with zero
capacity, a |% 0| operation takes place in randomUint32LessThan. This change
avoids that.
Iterator::NextEntry() miscomputes |entryLimit|. This doesn't matter in
non-chaos mode because we'll always find a live entry before hitting that
limit. But it does matter in chaos mode because it means we don't wrap around
when we should.
It's clear how this mistake was made -- the code from Enumerate() was copied.
In Enumerate() |mEntryStore| and |entryAddr| are the same when |entryLimit| is
computed, so you can use them interchangeably. But in NextEntry() |mEntryAddr|
will have moved past |mEntryStore|, so you have to use |mEntryStore|. I changed
both functions in the same way to keep the correspondence between them obvious.
--HG--
extra : rebase_source : f27558b3179be394526d1c3f82ffbae0fb58b2b9
|mOps| is always non-null now, and there's no longer any distinction between
and uninitialized and initialized table. Yay.
--HG--
extra : rebase_source : 3d1fb72aee4dd21ff20db0ff3166d4e932ade897
This is a temporary sub-class of PLDHashTable that will allow PLDHashTable to
be incrementally transitioned from manual initialization/finalization (via
explicit Init()/Fini() calls) to automatic initialization/finalization (via an
initializing constructor and a destructor). Once all PLDHashTable instances are
converted to PLDHashTable2, it can be folded back into PLDHashTable and the "2"
suffix can be dropped.
--HG--
extra : rebase_source : 674e7bd9320dc1db8879f842df05a7d995069e97
Due to Android startup regressions (bug 1163066) and plugin crashes (bug
1165155).
--HG--
extra : rebase_source : 380f79e67dff4c4eaa2614f286a4d0669666b652
The destructor is "opt-in" -- there's a flag that makes it a no-op unless the
table was initialized with the initializing constructor. This will allow us to
incrementally convert existing tables from manual to automatic
initialization/finalization. This is important because some of the existing
uses are tricky (impossible?) to convert to the automatic style.
This fixes the following problems with PLDHashTable::operator=:
- It doesn't handle self-assigments.
- It leaks the memory used by the assigned-to table.
- It doesn't leave the assigned-from table in a safely destructable state.
--HG--
extra : rebase_source : 433ac3418c00e3bb6d376982e4c679d27e42a377
It's no longer needed now that entry storage isn't allocated there. (The other
possible causes of failures in that function are less interesting and simply
crashing is a reasonable thing to do for them.)
This also makes PL_DNewHashTable() infallible, so I removed some
now-unnecessary checks of its result.
--HG--
extra : rebase_source : 4c6ab0c449bc18e8bace8bf036b5bd78d3a2f1c4
This makes zero-element hash tables, which are common, smaller, and also avoids
unnecessary malloc/free pairs.
I did some measurements during some basic browsing of a few sites. I found that
35% of all live tables were empty with a few tabs open. And cumulatively, for
the whole session, 45% of tables never had an element added to them.
--HG--
extra : rebase_source : 306bb50f250c09aa03a5e4822f41d6f605d76a1d
The use of |new| in PL_NewDHashTable() is necessary to avoid the new
assertions in Init() from failing.
--HG--
extra : rebase_source : 63cf962ce146142b72ffa0d6fcd3d8af1ec88bca
I kept all the existing PL_DHashTableAdd() calls fallible, in order to be
conservative, except for the ones in nsAtomTable.cpp which already were
followed immediately by an abort on failure.
--HG--
extra : rebase_source : 526d96ab65e4d7d71197b90d086d19fbdd79b7b5
I kept all the existing PL_DHashTableAdd() calls fallible, in order to be
conservative, except for the ones in nsAtomTable.cpp which already were
followed immediately by an abort on failure.
--HG--
extra : rebase_source : eeba14d732077ef2e412f4caca852de6b6b85f55
Because they are now just equivalent to |new PLDHashTable()| +
PL_DHashTableInit() and PL_DHashTableFinish(t) + |delete t|, respectively.
They're only used in a handful of places and obscure things more than they
clarify -- I only recently worked out exactly how they different from Init()
and Finish().
--HG--
extra : rebase_source : c958491447523becff3e01de45a5d2d227d1ecd3
Because it's no longer needed now that entry storage isn't allocated there.
(The other possible causes of failures are much less interesting and simply
crashing is a reasonable thing to do for them.)
This also makes PL_DNewHashTable() infallible.
--HG--
extra : rebase_source : 848cc9bbdfe434525857183b8370d309f3acbf49
This makes zero-element hash tables, which are common, smaller, and also avoids
unnecessary malloc/free pairs.
I did some measurements during some basic browsing of a few sites. I found that
35% of all live tables were empty with a few tabs open. And cumulatively, for
the whole session, 45% of tables never had an element added to them.
There is more to be done w.r.t. simplifying initialization, which will occur in
the next patch.
--HG--
extra : rebase_source : b9bfdcd680f39f3c947a49ae8462c04bc5e38805
PL_DHashTableLookup() had the same return protocol as SearchTable(), which
meant that compilers could generate a tail call from the former to the latter.
Bug 1124973 replaced PL_DHashTableLookup() with PL_DHashTableSearch(), which
has a slightly different return protocol, and so the tail call was lost. This
appears to be the cause of the Fennec performance regression.
This patch splits SearchTable() in two (using templates to avoid explicit code
duplication). SearchTable<false>() now has the same return protocol as
PL_DHashTableSearch(), and so the tail call can now be used again.
As well as renaming and privatizing |keyHash|, this patch also:
- renames GetKeyHash() to ComputeKeyHash(), which better indicates it's not
some kind of getter function; and
- makes PLDHashEntryStub inherit from PLDHashEntryHdr, for consistency with
everywhere else.
It feels safer to use a function with a new name, rather than just changing the
behaviour of the existing function.
For most of these cases the PL_DHashTableLookup() result was checked with
PL_DHASH_ENTRY_IS_{FREE,BUSY} so the conversion was easy. A few of them
preceded that check with a useless null check, but the intent of these was
still easy to determine.
I'll do the trickier ones in subsequent patches.
--HG--
extra : rebase_source : ab37a7a30be563861ded8631771181aacf054fd4