diff --git a/src/ds/bits.h b/src/ds/bits.h index 208df18..3f0283c 100644 --- a/src/ds/bits.h +++ b/src/ds/bits.h @@ -85,6 +85,16 @@ namespace snmalloc return BITS == 64; } + /** + * Returns a value of type T that has a single bit set, + */ + template + constexpr T one_at_bit(size_t shift) + { + static_assert(std::is_integral_v, "Type must be integral"); + return (static_cast(1)) << shift; + } + static constexpr size_t ADDRESS_BITS = is64() ? 48 : 32; inline void pause() @@ -225,7 +235,7 @@ namespace snmalloc for (int i = BITS - 1; i >= 0; i--) { - size_t mask = static_cast(1) << i; + size_t mask = one_at_bit(i); if ((x & mask) == mask) return n; @@ -255,7 +265,7 @@ namespace snmalloc for (size_t i = 0; i < BITS; i++) { - size_t mask = static_cast(1) << i; + size_t mask = one_at_bit(i); if ((x & mask) == mask) return n; @@ -296,7 +306,7 @@ namespace snmalloc if (x <= 2) return x; - return static_cast(1) << (BITS - clz(x - 1)); + return one_at_bit(BITS - clz(x - 1)); } inline size_t next_pow2_bits(size_t x) @@ -311,7 +321,7 @@ namespace snmalloc if (x <= 2) return x; - return static_cast(1) << (BITS - clz_const(x - 1)); + return one_at_bit(BITS - clz_const(x - 1)); } constexpr size_t next_pow2_bits_const(size_t x) @@ -419,9 +429,8 @@ namespace snmalloc template static size_t to_exp_mant(size_t value) { - size_t LEADING_BIT = - (static_cast(1) << (MANTISSA_BITS + LOW_BITS)) >> 1; - size_t MANTISSA_MASK = (static_cast(1) << MANTISSA_BITS) - 1; + size_t LEADING_BIT = one_at_bit(MANTISSA_BITS + LOW_BITS) >> 1; + size_t MANTISSA_MASK = one_at_bit(MANTISSA_BITS) - 1; value = value - 1; @@ -436,9 +445,8 @@ namespace snmalloc template constexpr static size_t to_exp_mant_const(size_t value) { - size_t LEADING_BIT = - (static_cast(1) << (MANTISSA_BITS + LOW_BITS)) >> 1; - size_t MANTISSA_MASK = (static_cast(1) << MANTISSA_BITS) - 1; + size_t LEADING_BIT = one_at_bit(MANTISSA_BITS + LOW_BITS) >> 1; + size_t MANTISSA_MASK = one_at_bit(MANTISSA_BITS) - 1; value = value - 1; @@ -456,7 +464,7 @@ namespace snmalloc if (MANTISSA_BITS > 0) { m_e = m_e + 1; - size_t MANTISSA_MASK = (static_cast(1) << MANTISSA_BITS) - 1; + size_t MANTISSA_MASK = one_at_bit(MANTISSA_BITS) - 1; size_t m = m_e & MANTISSA_MASK; size_t e = m_e >> MANTISSA_BITS; size_t b = e == 0 ? 0 : 1; @@ -465,7 +473,7 @@ namespace snmalloc return extended_m << (shifted_e + LOW_BITS); } - return static_cast(1) << (m_e + LOW_BITS); + return one_at_bit(m_e + LOW_BITS); } /** diff --git a/src/mem/alloc.h b/src/mem/alloc.h index bb8ed61..9b6857c 100644 --- a/src/mem/alloc.h +++ b/src/mem/alloc.h @@ -1211,7 +1211,7 @@ namespace snmalloc MEASURE_TIME(large_dealloc, 4, 16); size_t size_bits = bits::next_pow2_bits(size); - size_t rsize = static_cast(1) << size_bits; + size_t rsize = bits::one_at_bit(size_bits); assert(rsize >= SUPERSLAB_SIZE); size_t large_class = size_bits - SUPERSLAB_BITS; diff --git a/src/mem/allocstats.h b/src/mem/allocstats.h index b4871b9..710dadb 100644 --- a/src/mem/allocstats.h +++ b/src/mem/allocstats.h @@ -117,7 +117,7 @@ namespace snmalloc static constexpr size_t BUCKETS = 1 << BUCKETS_BITS; static constexpr size_t TOTAL_BUCKETS = bits::to_exp_mant_const( - (static_cast(1) << (bits::ADDRESS_BITS - 1))); + bits::one_at_bit(bits::ADDRESS_BITS - 1)); Stats sizeclass[N]; Stats large[LARGE_N]; diff --git a/src/mem/largealloc.h b/src/mem/largealloc.h index d80a30c..fdcacf9 100644 --- a/src/mem/largealloc.h +++ b/src/mem/largealloc.h @@ -98,8 +98,7 @@ namespace snmalloc { break; } - size_t rsize = (static_cast(1) << SUPERSLAB_BITS) - << large_class; + size_t rsize = bits::one_at_bit(SUPERSLAB_BITS) << large_class; size_t decommit_size = rsize - OS_PAGE_SIZE; // Grab all of the chunks of this size class. auto* slab = large_stack[large_class].pop_all(); @@ -321,7 +320,7 @@ namespace snmalloc template void* alloc(size_t large_class, size_t size) { - size_t rsize = (static_cast(1) << SUPERSLAB_BITS) << large_class; + size_t rsize = bits::one_at_bit(SUPERSLAB_BITS) << large_class; if (size == 0) size = rsize; diff --git a/src/mem/metaslab.h b/src/mem/metaslab.h index 641378a..845896f 100644 --- a/src/mem/metaslab.h +++ b/src/mem/metaslab.h @@ -102,10 +102,13 @@ namespace snmalloc { size_t size = sizeclass_to_size(sizeclass); size_t offset = get_slab_offset(sizeclass, is_short); + size_t all_ones = std::numeric_limits::is_signed ? + size_t(-1) : + std::numeric_limits::max(); size_t head_start = - remove_cache_friendly_offset(head & ~static_cast(1), sizeclass); - size_t slab_start = offset & ~static_cast(1); + remove_cache_friendly_offset(head & all_ones, sizeclass); + size_t slab_start = offset & all_ones; return ((head_start - slab_start) % size) == 0; } diff --git a/src/mem/sizeclass.h b/src/mem/sizeclass.h index ecaf682..77ce364 100644 --- a/src/mem/sizeclass.h +++ b/src/mem/sizeclass.h @@ -30,12 +30,12 @@ namespace snmalloc constexpr static inline size_t large_sizeclass_to_size(uint8_t large_class) { - return static_cast(1) << (large_class + SUPERSLAB_BITS); + return bits::one_at_bit(large_class + SUPERSLAB_BITS); } // Small classes range from [MIN, SLAB], i.e. inclusive. static constexpr size_t NUM_SMALL_CLASSES = - size_to_sizeclass_const(static_cast(1) << SLAB_BITS) + 1; + size_to_sizeclass_const(bits::one_at_bit(SLAB_BITS)) + 1; static constexpr size_t NUM_SIZECLASSES = size_to_sizeclass_const(SUPERSLAB_SIZE); diff --git a/src/mem/sizeclasstable.h b/src/mem/sizeclasstable.h index 97afa26..a9a80c6 100644 --- a/src/mem/sizeclasstable.h +++ b/src/mem/sizeclasstable.h @@ -30,8 +30,7 @@ namespace snmalloc bits::from_exp_mant(sizeclass); size_t alignment = bits::min( - static_cast(1) << bits::ctz_const(size[sizeclass]), - OS_PAGE_SIZE); + bits::one_at_bit(bits::ctz_const(size[sizeclass])), OS_PAGE_SIZE); cache_friendly_mask[sizeclass] = (alignment - 1); inverse_cache_friendly_mask[sizeclass] = ~(alignment - 1); }