Skip to content

Commit e59f404

Browse files
committed
ZJIT: Add a BitSet type
1 parent 342ada1 commit e59f404

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

zjit/src/bitset.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
type Entry = u128;
2+
3+
const ENTRY_NUM_BITS: usize = Entry::BITS as usize;
4+
5+
// TODO(max): Make a `SmallBitSet` and `LargeBitSet` and switch between them if `num_bits` fits in
6+
// `Entry`.
7+
pub struct BitSet<T: Into<usize> + Copy> {
8+
entries: Vec<Entry>,
9+
num_bits: usize,
10+
phantom: std::marker::PhantomData<T>,
11+
}
12+
13+
impl<T: Into<usize> + Copy> BitSet<T> {
14+
pub fn with_capacity(num_bits: usize) -> Self {
15+
let num_entries = num_bits.div_ceil(ENTRY_NUM_BITS);
16+
Self { entries: vec![0; num_entries], num_bits, phantom: Default::default() }
17+
}
18+
19+
/// Returns whether the value was newly inserted: true if the set did not originally contain
20+
/// the bit, and false otherwise.
21+
pub fn insert(&mut self, idx: T) -> bool {
22+
debug_assert!(idx.into() < self.num_bits);
23+
let entry_idx = idx.into() / ENTRY_NUM_BITS;
24+
let bit_idx = idx.into() % ENTRY_NUM_BITS;
25+
let newly_inserted = (self.entries[entry_idx] & (1 << bit_idx)) == 0;
26+
self.entries[entry_idx] |= 1 << bit_idx;
27+
newly_inserted
28+
}
29+
30+
pub fn get(&self, idx: T) -> bool {
31+
debug_assert!(idx.into() < self.num_bits);
32+
let entry_idx = idx.into() / ENTRY_NUM_BITS;
33+
let bit_idx = idx.into() % ENTRY_NUM_BITS;
34+
(self.entries[entry_idx] & (1 << bit_idx)) != 0
35+
}
36+
}
37+
38+
#[cfg(test)]
39+
mod tests {
40+
use super::BitSet;
41+
42+
#[test]
43+
#[should_panic]
44+
fn get_over_capacity_panics() {
45+
let set = BitSet::with_capacity(0);
46+
assert_eq!(set.get(0usize), false);
47+
}
48+
49+
#[test]
50+
fn with_capacity_defaults_to_zero() {
51+
let set = BitSet::with_capacity(4);
52+
assert_eq!(set.get(0usize), false);
53+
assert_eq!(set.get(1usize), false);
54+
assert_eq!(set.get(2usize), false);
55+
assert_eq!(set.get(3usize), false);
56+
}
57+
58+
#[test]
59+
fn insert_sets_bit() {
60+
let mut set = BitSet::with_capacity(4);
61+
assert_eq!(set.insert(1usize), true);
62+
assert_eq!(set.get(1usize), true);
63+
}
64+
65+
#[test]
66+
fn insert_with_set_bit_returns_false() {
67+
let mut set = BitSet::with_capacity(4);
68+
assert_eq!(set.insert(1usize), true);
69+
assert_eq!(set.insert(1usize), false);
70+
}
71+
}

zjit/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ mod profile;
2323
mod invariants;
2424
#[cfg(test)]
2525
mod assertions;
26+
mod bitset;

0 commit comments

Comments
 (0)