|
1 | 1 | #![cfg(feature = "allocator_api")]
|
2 | 2 |
|
3 | 3 | use crate::quickcheck;
|
4 |
| -use crate::quickcheck::arbitrary_layout; |
5 | 4 | use bumpalo::Bump;
|
6 | 5 | use std::alloc::{AllocError, Allocator, Layout};
|
7 | 6 | use std::ptr::NonNull;
|
8 | 7 | use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
|
9 | 8 |
|
| 9 | +/// Map an arbitrary `x` to a power of 2 that is less than or equal to `max`, |
| 10 | +/// but with as little bias as possible (eg rounding `min(x, max)` to the |
| 11 | +/// nearest power of 2 is unacceptable because it would majorly bias `max` for |
| 12 | +/// small values of `max`). |
| 13 | +fn clamp_to_pow2_in_range(x: usize, max: usize) -> usize { |
| 14 | + let log_x = max.ilog2() as usize; |
| 15 | + if log_x == 0 { |
| 16 | + return 1; |
| 17 | + } |
| 18 | + let divisor = usize::MAX / log_x; |
| 19 | + let y = 1_usize << (x / divisor); |
| 20 | + assert!(y.is_power_of_two(), "{y} is not a power of two"); |
| 21 | + assert!(y <= max, "{y} is larger than {max}"); |
| 22 | + y |
| 23 | +} |
| 24 | + |
| 25 | +/// Helper to turn a pair of arbitrary `usize`s into a valid `Layout` of |
| 26 | +/// reasonable size for use with quickchecks. |
| 27 | +pub fn arbitrary_layout(size: usize, align: usize) -> Layout { |
| 28 | + const MAX_ALIGN: usize = 64; |
| 29 | + const MAX_SIZE: usize = 1024; |
| 30 | + |
| 31 | + let align = clamp_to_pow2_in_range(align, MAX_ALIGN); |
| 32 | + |
| 33 | + let size = size % (MAX_SIZE + 1); |
| 34 | + let size = size.next_multiple_of(align); |
| 35 | + |
| 36 | + Layout::from_size_align(size, align).unwrap() |
| 37 | +} |
| 38 | + |
10 | 39 | #[derive(Debug)]
|
11 | 40 | struct AllocatorDebug {
|
12 | 41 | bump: Bump,
|
|
0 commit comments