1
Fork 0

use undef for uninitialized bytes in constants

This commit is contained in:
Erik Desjardins 2021-03-31 00:06:01 -04:00
parent 7b0e554ee2
commit 4d635fdf63
7 changed files with 202 additions and 21 deletions

View file

@ -721,20 +721,24 @@ impl InitMask {
}
// FIXME(oli-obk): optimize this for allocations larger than a block.
let idx = (start.bytes()..end.bytes()).map(Size::from_bytes).find(|&i| !self.get(i));
let idx = (start..end).find(|&i| !self.get(i));
match idx {
Some(idx) => {
let uninit_end = (idx.bytes()..end.bytes())
.map(Size::from_bytes)
.find(|&i| self.get(i))
.unwrap_or(end);
let uninit_end = (idx..end).find(|&i| self.get(i)).unwrap_or(end);
Err(idx..uninit_end)
}
None => Ok(()),
}
}
/// Returns an iterator, yielding a range of byte indexes for each contiguous region
/// of initialized or uninitialized bytes inside the range `start..end` (end-exclusive).
#[inline]
pub fn range_as_init_chunks(&self, start: Size, end: Size) -> InitChunkIter<'_> {
InitChunkIter::new(self, start, end)
}
pub fn set_range(&mut self, start: Size, end: Size, new_state: bool) {
let len = self.len;
if end > len {
@ -827,6 +831,49 @@ impl InitMask {
}
}
/// Yields [`InitChunk`]s. See [`InitMask::range_as_init_chunks`].
pub struct InitChunkIter<'a> {
init_mask: &'a InitMask,
/// The current byte index into `init_mask`.
start: Size,
/// The end byte index into `init_mask`.
end: Size,
}
/// A contiguous chunk of initialized or uninitialized memory.
pub enum InitChunk {
Init(Range<Size>),
Uninit(Range<Size>),
}
impl<'a> InitChunkIter<'a> {
fn new(init_mask: &'a InitMask, start: Size, end: Size) -> Self {
assert!(start <= end);
assert!(end <= init_mask.len);
Self { init_mask, start, end }
}
}
impl<'a> Iterator for InitChunkIter<'a> {
type Item = InitChunk;
fn next(&mut self) -> Option<Self::Item> {
if self.start >= self.end {
return None;
}
let is_init = self.init_mask.get(self.start);
// FIXME(oli-obk): optimize this for allocations larger than a block.
let end_of_chunk =
(self.start..self.end).find(|&i| self.init_mask.get(i) != is_init).unwrap_or(self.end);
let range = self.start..end_of_chunk;
self.start = end_of_chunk;
Some(if is_init { InitChunk::Init(range) } else { InitChunk::Uninit(range) })
}
}
#[inline]
fn bit_index(bits: Size) -> (usize, usize) {
let bits = bits.bytes();

View file

@ -125,7 +125,9 @@ pub use self::error::{
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMaybeUninit};
pub use self::allocation::{alloc_range, AllocRange, Allocation, InitMask, Relocations};
pub use self::allocation::{
alloc_range, AllocRange, Allocation, InitChunk, InitChunkIter, InitMask, Relocations,
};
pub use self::pointer::{Pointer, PointerArithmetic, Provenance};