Bug 1406303 - Simplify the calculation of AddressRadixTree's height. r?njn
The tree height was defined as:
height = aBits / bits_per_level;
if (height * bits_per_level != aBits) {
height++;
}
What's wanted here is a height that covers all the bits, where the first
level might cover less than bits_per_level.
So aBits / bits_per_level gets us the height covered by levels with
exactly bits_per_level bits. The tree height is one more when there
are remaining bits.
Put differently, we can write aBits as:
aBits = bits_per_level * x + y
with y < bits_per_level.
We have:
aBits / bits_per_level = x.
height = x when y = 0, and x + 1 when y > 0.
We're looking for a number z such that
height = (aBits + z) / bits_per_level.
Or:
height = (bits_per_level * x + y + z) / bits_per_level.
= x + (y + z) / bits_per_level.
So we're looking for a z such that
(y + z) / bits_per_level = 0 when y = 0
= 1 when y > 0
The properties of the integer division are such that the above means:
0 <= y + z < bits_per_level when y = 0
bits_per_level <= y + z < 2 * bits_per_level when y > 0
Which gives us:
0 <= z < bits_per_level
bits_per_level - y <= z < 2 * bits_per_level - y when y > 0
y being < bit_per_level per the constraint further above,
2 * bits_per_level - y > bits_per_level.
So all in all, we want a z such that
bits_per_level - y <= z < bits_per_level with 0 < y < bits_per_level
The largest value where this is true is z = bits_per_level - 1.
In summary,
height = (aBits + bits_per_level - 1) / bits_per_level
is the same as the height as originally defined.
With that formula, it's self evident that height * bits_per_level is
always >= aBits, so we remove the assertion.
--- a/memory/build/mozjemalloc.cpp
+++ b/memory/build/mozjemalloc.cpp
@@ -1735,21 +1735,17 @@ pages_copy(void *dest, const void *src,
AddressRadixTree*
AddressRadixTree::Create(unsigned aBits)
{
AddressRadixTree* ret;
unsigned bits_per_level, height, i;
bits_per_level = AddressRadixTree::kNodeSize2Pow - SIZEOF_PTR_2POW;
- height = aBits / bits_per_level;
- if (height * bits_per_level != aBits) {
- height++;
- }
- MOZ_DIAGNOSTIC_ASSERT(height * bits_per_level >= aBits);
+ height = (aBits + bits_per_level - 1) / bits_per_level;
ret = (AddressRadixTree*)base_calloc(1, sizeof(AddressRadixTree) +
(sizeof(unsigned) * (height - 1)));
if (!ret) {
return nullptr;
}
malloc_spin_init(&ret->mLock);