Skip to content

Commit 3c2b706

Browse files
implement InitMaskCompressed using InitChunkIter, cleanup
1 parent 1eaccab commit 3c2b706

File tree

1 file changed

+33
-23
lines changed

1 file changed

+33
-23
lines changed

compiler/rustc_middle/src/mir/interpret/allocation.rs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -563,22 +563,12 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
563563

564564
let mut ranges = smallvec::SmallVec::<[u64; 1]>::new();
565565
let initial = self.init_mask.get(range.start);
566-
let mut cur_len = 1;
567-
let mut cur = initial;
568566

569-
for i in 1..range.size.bytes() {
570-
// FIXME: optimize to bitshift the current uninitialized block's bits and read the top bit.
571-
if self.init_mask.get(range.start + Size::from_bytes(i)) == cur {
572-
cur_len += 1;
573-
} else {
574-
ranges.push(cur_len);
575-
cur_len = 1;
576-
cur = !cur;
577-
}
567+
for chunk in self.init_mask.range_as_init_chunks(range.start, range.end()) {
568+
let len = chunk.range().end.bytes() - chunk.range().start.bytes();
569+
ranges.push(len);
578570
}
579571

580-
ranges.push(cur_len);
581-
582572
InitMaskCompressed { ranges, initial }
583573
}
584574

@@ -830,45 +820,65 @@ impl InitMask {
830820
}
831821
}
832822

823+
/// A contiguous chunk of initialized or uninitialized memory.
824+
pub enum InitChunk {
825+
Init(Range<Size>),
826+
Uninit(Range<Size>),
827+
}
828+
829+
impl InitChunk {
830+
#[inline]
831+
pub fn range(&self) -> Range<Size> {
832+
match self {
833+
Self::Init(r) => r.clone(),
834+
Self::Uninit(r) => r.clone(),
835+
}
836+
}
837+
}
838+
833839
/// Yields [`InitChunk`]s. See [`InitMask::range_as_init_chunks`].
834840
pub struct InitChunkIter<'a> {
835841
init_mask: &'a InitMask,
842+
/// Whether the last chunk was initialized.
843+
is_init: bool,
836844
/// The current byte index into `init_mask`.
837845
start: Size,
838846
/// The end byte index into `init_mask`.
839847
end: Size,
840848
}
841849

842-
/// A contiguous chunk of initialized or uninitialized memory.
843-
pub enum InitChunk {
844-
Init(Range<Size>),
845-
Uninit(Range<Size>),
846-
}
847-
848850
impl<'a> InitChunkIter<'a> {
851+
#[inline]
849852
fn new(init_mask: &'a InitMask, start: Size, end: Size) -> Self {
850853
assert!(start <= end);
851854
assert!(end <= init_mask.len);
852-
Self { init_mask, start, end }
855+
856+
let is_init = if start < end { init_mask.get(start) } else { false };
857+
858+
Self { init_mask, is_init, start, end }
853859
}
854860
}
855861

856862
impl<'a> Iterator for InitChunkIter<'a> {
857863
type Item = InitChunk;
858864

865+
#[inline]
859866
fn next(&mut self) -> Option<Self::Item> {
860867
if self.start >= self.end {
861868
return None;
862869
}
863870

864-
let is_init = self.init_mask.get(self.start);
865871
let end_of_chunk =
866-
find_bit(&self.init_mask, self.start, self.end, !is_init).unwrap_or(self.end);
872+
find_bit(&self.init_mask, self.start, self.end, !self.is_init).unwrap_or(self.end);
867873
let range = self.start..end_of_chunk;
868874

875+
let ret =
876+
Some(if self.is_init { InitChunk::Init(range) } else { InitChunk::Uninit(range) });
877+
878+
self.is_init = !self.is_init;
869879
self.start = end_of_chunk;
870880

871-
Some(if is_init { InitChunk::Init(range) } else { InitChunk::Uninit(range) })
881+
ret
872882
}
873883
}
874884

0 commit comments

Comments
 (0)