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.

--HG--
extra : rebase_source : 8ca2e5fbad7d4ad537f26508af5aa250483f1f08
This commit is contained in:
Mike Hommey 2017-10-06 11:32:27 +09:00
Родитель aaefadc3a4
Коммит 69e46849e9
1 изменённых файлов: 1 добавлений и 5 удалений

Просмотреть файл

@ -1740,11 +1740,7 @@ AddressRadixTree::Create(unsigned aBits)
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)));