use crate::constants::{MAX_SMALL_ALLOC_SIZE, MIN_BLOCK_SIZE, NUM_SIZE_CLASSES, PAGE_SIZE};
pub(super) const CLASS_TO_SIZE: [u16; NUM_SIZE_CLASSES] = [
16, 32, 48, 64, 80, 96, 112, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480, 512,
640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920, 2048,
2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192,
9216, 10240, 11264, 12288, 13312, 14336, 15360, 16384,
];
pub(super) const CLASS_TO_MAX_BLOCKS: [u16; NUM_SIZE_CLASSES] = {
let mut arr = [0u16; NUM_SIZE_CLASSES];
let mut i = 0;
while i < NUM_SIZE_CLASSES {
arr[i] = (PAGE_SIZE / CLASS_TO_SIZE[i] as usize) as u16;
i += 1;
}
arr
};
pub(super) const SIZE_TO_CLASS: [u8; MAX_SMALL_ALLOC_SIZE / MIN_BLOCK_SIZE + 1] = {
use super::arithmetic::size_to_class_nonzero_arithmetic;
let mut arr = [u8::MAX; MAX_SMALL_ALLOC_SIZE / MIN_BLOCK_SIZE + 1];
arr[0] = 0;
let mut granule = 1;
while granule <= MAX_SMALL_ALLOC_SIZE / MIN_BLOCK_SIZE {
arr[granule] = match size_to_class_nonzero_arithmetic(granule * MIN_BLOCK_SIZE) {
Some(class) => class as u8,
None => u8::MAX,
};
granule += 1;
}
arr
};
pub const LEMIRE_DIV_SHIFT: u32 = 32;
pub(super) const CLASS_TO_DIV_MULT: [u32; NUM_SIZE_CLASSES] = {
let mut arr = [0u32; NUM_SIZE_CLASSES];
let mut i = 0;
while i < NUM_SIZE_CLASSES {
let n = CLASS_TO_SIZE[i] as u64;
arr[i] = ((1u64 << LEMIRE_DIV_SHIFT) / n + 1) as u32;
i += 1;
}
arr
};
#[inline(always)]
pub const fn class_to_size(class: usize) -> usize {
if class < NUM_SIZE_CLASSES {
CLASS_TO_SIZE[class] as usize
} else {
0
}
}
#[inline(always)]
pub const fn class_to_max_blocks(class: usize) -> usize {
if class < NUM_SIZE_CLASSES {
CLASS_TO_MAX_BLOCKS[class] as usize
} else {
0
}
}
#[inline(always)]
pub const fn block_index_in_page(class: usize, offset: usize) -> usize {
((offset as u64 * CLASS_TO_DIV_MULT[class] as u64) >> LEMIRE_DIV_SHIFT) as usize
}
const _: () = {
assert!(
CLASS_TO_SIZE[0] as usize == MIN_BLOCK_SIZE,
"smallest size class must equal MIN_BLOCK_SIZE"
);
let mut i = 1;
while i < NUM_SIZE_CLASSES {
assert!(
CLASS_TO_SIZE[i] > CLASS_TO_SIZE[i - 1],
"CLASS_TO_SIZE must be strictly increasing"
);
assert!(
(CLASS_TO_SIZE[i] as usize).is_multiple_of(MIN_BLOCK_SIZE),
"every size class must be a multiple of MIN_BLOCK_SIZE"
);
assert!(
CLASS_TO_MAX_BLOCKS[i] >= 1,
"every size class must fit at least one block per page"
);
i += 1;
}
};