Merge pull request #16 from Microsoft/Sizeclass

Simplified sizeclass calculations and added tests.
This commit is contained in:
Matthew Parkinson
2019-02-19 13:07:08 +00:00
committed by GitHub
2 changed files with 80 additions and 37 deletions

View File

@@ -378,7 +378,9 @@ namespace snmalloc
* Map large range of strictly positive integers
* into an exponent and mantissa pair.
*
* The reverse mapping is given as:
* The reverse mapping is given by first adding one to the value, and then
* extracting the bottom MANTISSA bits as m, and the rest as e.
* Then each value maps as:
*
* e | m | value
* ---------------------------------
@@ -391,57 +393,44 @@ namespace snmalloc
* smallest exponent and mantissa with a
* reverse mapping not less than the value.
*
* The e and m in the forward mapping and reverse are not the same, and the
* initial increment in from_exp_mant and the decrement in to_exp_mant
* handle the different ways it is calculating and using the split.
* This is due to the rounding of bits below the mantissa in the
* representation, which is confusing but leads to the fastest code.
*
* Does not work for value=0.
***********************************************/
template<size_t MANTISSA_BITS, size_t LOW_BITS = 0>
static size_t to_exp_mant(size_t value)
{
value += ((size_t)1 << (LOW_BITS)) - 1;
value >>= LOW_BITS;
size_t LEADING_BIT = ((size_t)1 << (MANTISSA_BITS + LOW_BITS)) >> 1;
size_t MANTISSA_MASK = ((size_t)1 << MANTISSA_BITS) - 1;
if (MANTISSA_BITS > 0)
{
size_t LEADING_BIT = ((size_t)1 << MANTISSA_BITS) >> 1;
size_t MANTISSA_MASK = ((size_t)1 << MANTISSA_BITS) - 1;
value = value - 1;
value = value - 1;
size_t e =
bits::BITS - MANTISSA_BITS - LOW_BITS - clz(value | LEADING_BIT);
size_t b = (e == 0) ? 0 : 1;
size_t m = (value >> (LOW_BITS + e - b)) & MANTISSA_MASK;
size_t e = (bits::BITS - clz(value | LEADING_BIT)) - MANTISSA_BITS;
size_t shift_e = (e == 0) ? 0 : e - 1;
size_t m = (value >> shift_e) & MANTISSA_MASK;
return (e << MANTISSA_BITS) + m;
}
else
{
return bits::next_pow2_bits(value);
}
return (e << MANTISSA_BITS) + m;
}
template<size_t MANTISSA_BITS, size_t LOW_BITS = 0>
constexpr static size_t to_exp_mant_const(size_t value)
{
value += ((size_t)1 << LOW_BITS) - 1;
value >>= LOW_BITS;
size_t LEADING_BIT = ((size_t)1 << (MANTISSA_BITS + LOW_BITS)) >> 1;
size_t MANTISSA_MASK = ((size_t)1 << MANTISSA_BITS) - 1;
if (MANTISSA_BITS > 0)
{
size_t LEADING_BIT = (size_t)1 << (MANTISSA_BITS - 1);
size_t MANTISSA_MASK = ((size_t)1 << MANTISSA_BITS) - 1;
value = value - 1;
value = value - 1;
size_t e =
bits::BITS - MANTISSA_BITS - LOW_BITS - clz_const(value | LEADING_BIT);
size_t b = (e == 0) ? 0 : 1;
size_t m = (value >> (LOW_BITS + e - b)) & MANTISSA_MASK;
size_t e =
(bits::BITS - clz_const(value | LEADING_BIT)) - MANTISSA_BITS;
size_t shift_e = (e == 0) ? 0 : e - 1;
size_t m = (value >> shift_e) & MANTISSA_MASK;
return (e << MANTISSA_BITS) + m;
}
else
{
return bits::next_pow2_bits_const(value);
}
return (e << MANTISSA_BITS) + m;
}
template<size_t MANTISSA_BITS, size_t LOW_BITS = 0>
@@ -449,12 +438,13 @@ namespace snmalloc
{
if (MANTISSA_BITS > 0)
{
m_e = m_e + 1;
size_t MANTISSA_MASK = ((size_t)1 << MANTISSA_BITS) - 1;
size_t m = m_e & MANTISSA_MASK;
size_t e = m_e >> MANTISSA_BITS;
size_t b = e == 0 ? 0 : 1;
size_t shifted_e = e - b;
size_t extended_m = (m + ((size_t)b << MANTISSA_BITS)) + 1;
size_t extended_m = (m + ((size_t)b << MANTISSA_BITS));
return extended_m << (shifted_e + LOW_BITS);
}
else