cranelift_entity/
sparse.rs

1//! Sparse mapping of entity references to larger value types.
2//!
3//! This module provides a `SparseMap` data structure which implements a sparse mapping from an
4//! `EntityRef` key to a value type that may be on the larger side. This implementation is based on
5//! the paper:
6//!
7//! > Briggs, Torczon, *An efficient representation for sparse sets*,
8//!   ACM Letters on Programming Languages and Systems, Volume 2, Issue 1-4, March-Dec. 1993.
9
10use crate::map::SecondaryMap;
11use crate::EntityRef;
12use alloc::vec::Vec;
13use core::mem;
14use core::slice;
15use core::u32;
16
17/// Trait for extracting keys from values stored in a `SparseMap`.
18///
19/// All values stored in a `SparseMap` must keep track of their own key in the map and implement
20/// this trait to provide access to the key.
21pub trait SparseMapValue<K> {
22    /// Get the key of this sparse map value. This key is not allowed to change while the value
23    /// is a member of the map.
24    fn key(&self) -> K;
25}
26
27/// A sparse mapping of entity references.
28///
29/// A `SparseMap<K, V>` map provides:
30///
31/// - Memory usage equivalent to `SecondaryMap<K, u32>` + `Vec<V>`, so much smaller than
32///   `SecondaryMap<K, V>` for sparse mappings of larger `V` types.
33/// - Constant time lookup, slightly slower than `SecondaryMap`.
34/// - A very fast, constant time `clear()` operation.
35/// - Fast insert and erase operations.
36/// - Stable iteration that is as fast as a `Vec<V>`.
37///
38/// # Compared to `SecondaryMap`
39///
40/// When should we use a `SparseMap` instead of a secondary `SecondaryMap`? First of all,
41/// `SparseMap` does not provide the functionality of a `PrimaryMap` which can allocate and assign
42/// entity references to objects as they are pushed onto the map. It is only the secondary entity
43/// maps that can be replaced with a `SparseMap`.
44///
45/// - A secondary entity map assigns a default mapping to all keys. It doesn't distinguish between
46///   an unmapped key and one that maps to the default value. `SparseMap` does not require
47///   `Default` values, and it tracks accurately if a key has been mapped or not.
48/// - Iterating over the contents of an `SecondaryMap` is linear in the size of the *key space*,
49///   while iterating over a `SparseMap` is linear in the number of elements in the mapping. This
50///   is an advantage precisely when the mapping is sparse.
51/// - `SparseMap::clear()` is constant time and super-fast. `SecondaryMap::clear()` is linear in
52///   the size of the key space. (Or, rather the required `resize()` call following the `clear()`
53///   is).
54/// - `SparseMap` requires the values to implement `SparseMapValue<K>` which means that they must
55///   contain their own key.
56pub struct SparseMap<K, V>
57where
58    K: EntityRef,
59    V: SparseMapValue<K>,
60{
61    sparse: SecondaryMap<K, u32>,
62    dense: Vec<V>,
63}
64
65impl<K, V> SparseMap<K, V>
66where
67    K: EntityRef,
68    V: SparseMapValue<K>,
69{
70    /// Create a new empty mapping.
71    pub fn new() -> Self {
72        Self {
73            sparse: SecondaryMap::new(),
74            dense: Vec::new(),
75        }
76    }
77
78    /// Returns the number of elements in the map.
79    pub fn len(&self) -> usize {
80        self.dense.len()
81    }
82
83    /// Returns true is the map contains no elements.
84    pub fn is_empty(&self) -> bool {
85        self.dense.is_empty()
86    }
87
88    /// Remove all elements from the mapping.
89    pub fn clear(&mut self) {
90        self.dense.clear();
91    }
92
93    /// Returns a reference to the value corresponding to the key.
94    pub fn get(&self, key: K) -> Option<&V> {
95        if let Some(idx) = self.sparse.get(key).cloned() {
96            if let Some(entry) = self.dense.get(idx as usize) {
97                if entry.key() == key {
98                    return Some(entry);
99                }
100            }
101        }
102        None
103    }
104
105    /// Returns a mutable reference to the value corresponding to the key.
106    ///
107    /// Note that the returned value must not be mutated in a way that would change its key. This
108    /// would invalidate the sparse set data structure.
109    pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
110        if let Some(idx) = self.sparse.get(key).cloned() {
111            if let Some(entry) = self.dense.get_mut(idx as usize) {
112                if entry.key() == key {
113                    return Some(entry);
114                }
115            }
116        }
117        None
118    }
119
120    /// Return the index into `dense` of the value corresponding to `key`.
121    fn index(&self, key: K) -> Option<usize> {
122        if let Some(idx) = self.sparse.get(key).cloned() {
123            let idx = idx as usize;
124            if let Some(entry) = self.dense.get(idx) {
125                if entry.key() == key {
126                    return Some(idx);
127                }
128            }
129        }
130        None
131    }
132
133    /// Return `true` if the map contains a value corresponding to `key`.
134    pub fn contains_key(&self, key: K) -> bool {
135        self.get(key).is_some()
136    }
137
138    /// Insert a value into the map.
139    ///
140    /// If the map did not have this key present, `None` is returned.
141    ///
142    /// If the map did have this key present, the value is updated, and the old value is returned.
143    ///
144    /// It is not necessary to provide a key since the value knows its own key already.
145    pub fn insert(&mut self, value: V) -> Option<V> {
146        let key = value.key();
147
148        // Replace the existing entry for `key` if there is one.
149        if let Some(entry) = self.get_mut(key) {
150            return Some(mem::replace(entry, value));
151        }
152
153        // There was no previous entry for `key`. Add it to the end of `dense`.
154        let idx = self.dense.len();
155        debug_assert!(idx <= u32::MAX as usize, "SparseMap overflow");
156        self.dense.push(value);
157        self.sparse[key] = idx as u32;
158        None
159    }
160
161    /// Remove a value from the map and return it.
162    pub fn remove(&mut self, key: K) -> Option<V> {
163        if let Some(idx) = self.index(key) {
164            let back = self.dense.pop().unwrap();
165
166            // Are we popping the back of `dense`?
167            if idx == self.dense.len() {
168                return Some(back);
169            }
170
171            // We're removing an element from the middle of `dense`.
172            // Replace the element at `idx` with the back of `dense`.
173            // Repair `sparse` first.
174            self.sparse[back.key()] = idx as u32;
175            return Some(mem::replace(&mut self.dense[idx], back));
176        }
177
178        // Nothing to remove.
179        None
180    }
181
182    /// Remove the last value from the map.
183    pub fn pop(&mut self) -> Option<V> {
184        self.dense.pop()
185    }
186
187    /// Get an iterator over the values in the map.
188    ///
189    /// The iteration order is entirely determined by the preceding sequence of `insert` and
190    /// `remove` operations. In particular, if no elements were removed, this is the insertion
191    /// order.
192    pub fn values(&self) -> slice::Iter<V> {
193        self.dense.iter()
194    }
195
196    /// Get the values as a slice.
197    pub fn as_slice(&self) -> &[V] {
198        self.dense.as_slice()
199    }
200}
201
202/// Iterating over the elements of a set.
203impl<'a, K, V> IntoIterator for &'a SparseMap<K, V>
204where
205    K: EntityRef,
206    V: SparseMapValue<K>,
207{
208    type Item = &'a V;
209    type IntoIter = slice::Iter<'a, V>;
210
211    fn into_iter(self) -> Self::IntoIter {
212        self.values()
213    }
214}
215
216/// Any `EntityRef` can be used as a sparse map value representing itself.
217impl<T> SparseMapValue<T> for T
218where
219    T: EntityRef,
220{
221    fn key(&self) -> Self {
222        *self
223    }
224}
225
226/// A sparse set of entity references.
227///
228/// Any type that implements `EntityRef` can be used as a sparse set value too.
229pub type SparseSet<T> = SparseMap<T, T>;
230
231#[cfg(test)]
232mod tests {
233    use super::*;
234    use crate::EntityRef;
235
236    /// An opaque reference to an instruction in a function.
237    #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
238    pub struct Inst(u32);
239    entity_impl!(Inst, "inst");
240
241    // Mock key-value object for testing.
242    #[derive(PartialEq, Eq, Debug)]
243    struct Obj(Inst, &'static str);
244
245    impl SparseMapValue<Inst> for Obj {
246        fn key(&self) -> Inst {
247            self.0
248        }
249    }
250
251    #[test]
252    fn empty_immutable_map() {
253        let i1 = Inst::new(1);
254        let map: SparseMap<Inst, Obj> = SparseMap::new();
255
256        assert!(map.is_empty());
257        assert_eq!(map.len(), 0);
258        assert_eq!(map.get(i1), None);
259        assert_eq!(map.values().count(), 0);
260    }
261
262    #[test]
263    fn single_entry() {
264        let i0 = Inst::new(0);
265        let i1 = Inst::new(1);
266        let i2 = Inst::new(2);
267        let mut map = SparseMap::new();
268
269        assert!(map.is_empty());
270        assert_eq!(map.len(), 0);
271        assert_eq!(map.get(i1), None);
272        assert_eq!(map.get_mut(i1), None);
273        assert_eq!(map.remove(i1), None);
274
275        assert_eq!(map.insert(Obj(i1, "hi")), None);
276        assert!(!map.is_empty());
277        assert_eq!(map.len(), 1);
278        assert_eq!(map.get(i0), None);
279        assert_eq!(map.get(i1), Some(&Obj(i1, "hi")));
280        assert_eq!(map.get(i2), None);
281        assert_eq!(map.get_mut(i0), None);
282        assert_eq!(map.get_mut(i1), Some(&mut Obj(i1, "hi")));
283        assert_eq!(map.get_mut(i2), None);
284
285        assert_eq!(map.remove(i0), None);
286        assert_eq!(map.remove(i2), None);
287        assert_eq!(map.remove(i1), Some(Obj(i1, "hi")));
288        assert_eq!(map.len(), 0);
289        assert_eq!(map.get(i1), None);
290        assert_eq!(map.get_mut(i1), None);
291        assert_eq!(map.remove(i0), None);
292        assert_eq!(map.remove(i1), None);
293        assert_eq!(map.remove(i2), None);
294    }
295
296    #[test]
297    fn multiple_entries() {
298        let i0 = Inst::new(0);
299        let i1 = Inst::new(1);
300        let i2 = Inst::new(2);
301        let i3 = Inst::new(3);
302        let mut map = SparseMap::new();
303
304        assert_eq!(map.insert(Obj(i2, "foo")), None);
305        assert_eq!(map.insert(Obj(i1, "bar")), None);
306        assert_eq!(map.insert(Obj(i0, "baz")), None);
307
308        // Iteration order = insertion order when nothing has been removed yet.
309        assert_eq!(
310            map.values().map(|obj| obj.1).collect::<Vec<_>>(),
311            ["foo", "bar", "baz"]
312        );
313
314        assert_eq!(map.len(), 3);
315        assert_eq!(map.get(i0), Some(&Obj(i0, "baz")));
316        assert_eq!(map.get(i1), Some(&Obj(i1, "bar")));
317        assert_eq!(map.get(i2), Some(&Obj(i2, "foo")));
318        assert_eq!(map.get(i3), None);
319
320        // Remove front object, causing back to be swapped down.
321        assert_eq!(map.remove(i1), Some(Obj(i1, "bar")));
322        assert_eq!(map.len(), 2);
323        assert_eq!(map.get(i0), Some(&Obj(i0, "baz")));
324        assert_eq!(map.get(i1), None);
325        assert_eq!(map.get(i2), Some(&Obj(i2, "foo")));
326        assert_eq!(map.get(i3), None);
327
328        // Reinsert something at a previously used key.
329        assert_eq!(map.insert(Obj(i1, "barbar")), None);
330        assert_eq!(map.len(), 3);
331        assert_eq!(map.get(i0), Some(&Obj(i0, "baz")));
332        assert_eq!(map.get(i1), Some(&Obj(i1, "barbar")));
333        assert_eq!(map.get(i2), Some(&Obj(i2, "foo")));
334        assert_eq!(map.get(i3), None);
335
336        // Replace an entry.
337        assert_eq!(map.insert(Obj(i0, "bazbaz")), Some(Obj(i0, "baz")));
338        assert_eq!(map.len(), 3);
339        assert_eq!(map.get(i0), Some(&Obj(i0, "bazbaz")));
340        assert_eq!(map.get(i1), Some(&Obj(i1, "barbar")));
341        assert_eq!(map.get(i2), Some(&Obj(i2, "foo")));
342        assert_eq!(map.get(i3), None);
343
344        // Check the reference `IntoIter` impl.
345        let mut v = Vec::new();
346        for i in &map {
347            v.push(i.1);
348        }
349        assert_eq!(v.len(), map.len());
350    }
351
352    #[test]
353    fn entity_set() {
354        let i0 = Inst::new(0);
355        let i1 = Inst::new(1);
356        let mut set = SparseSet::new();
357
358        assert_eq!(set.insert(i0), None);
359        assert_eq!(set.insert(i0), Some(i0));
360        assert_eq!(set.insert(i1), None);
361        assert_eq!(set.get(i0), Some(&i0));
362        assert_eq!(set.get(i1), Some(&i1));
363    }
364}