Path: blob/main/cranelift/entity/src/sparse.rs
1692 views
//! Sparse mapping of entity references to larger value types.1//!2//! This module provides a `SparseMap` data structure which implements a sparse mapping from an3//! `EntityRef` key to a value type that may be on the larger side. This implementation is based on4//! the paper:5//!6//! > Briggs, Torczon, *An efficient representation for sparse sets*,7//! > ACM Letters on Programming Languages and Systems, Volume 2, Issue 1-4, March-Dec. 1993.89use crate::EntityRef;10use crate::map::SecondaryMap;11use alloc::vec::Vec;12use core::fmt;13use core::mem;14use core::slice;15use core::u32;1617#[cfg(feature = "enable-serde")]18use serde_derive::{Deserialize, Serialize};1920/// Trait for extracting keys from values stored in a `SparseMap`.21///22/// All values stored in a `SparseMap` must keep track of their own key in the map and implement23/// this trait to provide access to the key.24pub trait SparseMapValue<K> {25/// Get the key of this sparse map value. This key is not allowed to change while the value26/// is a member of the map.27fn key(&self) -> K;28}2930/// A sparse mapping of entity references.31///32/// A `SparseMap<K, V>` map provides:33///34/// - Memory usage equivalent to `SecondaryMap<K, u32>` + `Vec<V>`, so much smaller than35/// `SecondaryMap<K, V>` for sparse mappings of larger `V` types.36/// - Constant time lookup, slightly slower than `SecondaryMap`.37/// - A very fast, constant time `clear()` operation.38/// - Fast insert and erase operations.39/// - Stable iteration that is as fast as a `Vec<V>`.40///41/// # Compared to `SecondaryMap`42///43/// When should we use a `SparseMap` instead of a secondary `SecondaryMap`? First of all,44/// `SparseMap` does not provide the functionality of a `PrimaryMap` which can allocate and assign45/// entity references to objects as they are pushed onto the map. It is only the secondary entity46/// maps that can be replaced with a `SparseMap`.47///48/// - A secondary entity map assigns a default mapping to all keys. It doesn't distinguish between49/// an unmapped key and one that maps to the default value. `SparseMap` does not require50/// `Default` values, and it tracks accurately if a key has been mapped or not.51/// - Iterating over the contents of an `SecondaryMap` is linear in the size of the *key space*,52/// while iterating over a `SparseMap` is linear in the number of elements in the mapping. This53/// is an advantage precisely when the mapping is sparse.54/// - `SparseMap::clear()` is constant time and super-fast. `SecondaryMap::clear()` is linear in55/// the size of the key space. (Or, rather the required `resize()` call following the `clear()`56/// is).57/// - `SparseMap` requires the values to implement `SparseMapValue<K>` which means that they must58/// contain their own key.59#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]60pub struct SparseMap<K, V>61where62K: EntityRef,63V: SparseMapValue<K>,64{65sparse: SecondaryMap<K, u32>,66dense: Vec<V>,67}6869impl<K, V> SparseMap<K, V>70where71K: EntityRef,72V: SparseMapValue<K>,73{74/// Create a new empty mapping.75pub fn new() -> Self {76Self {77sparse: SecondaryMap::new(),78dense: Vec::new(),79}80}8182/// Returns the number of elements in the map.83pub fn len(&self) -> usize {84self.dense.len()85}8687/// Returns true is the map contains no elements.88pub fn is_empty(&self) -> bool {89self.dense.is_empty()90}9192/// Remove all elements from the mapping.93pub fn clear(&mut self) {94self.dense.clear();95}9697/// Returns a reference to the value corresponding to the key.98pub fn get(&self, key: K) -> Option<&V> {99if let Some(idx) = self.sparse.get(key).cloned() {100if let Some(entry) = self.dense.get(idx as usize) {101if entry.key() == key {102return Some(entry);103}104}105}106None107}108109/// Returns a mutable reference to the value corresponding to the key.110///111/// Note that the returned value must not be mutated in a way that would change its key. This112/// would invalidate the sparse set data structure.113pub fn get_mut(&mut self, key: K) -> Option<&mut V> {114if let Some(idx) = self.sparse.get(key).cloned() {115if let Some(entry) = self.dense.get_mut(idx as usize) {116if entry.key() == key {117return Some(entry);118}119}120}121None122}123124/// Return the index into `dense` of the value corresponding to `key`.125fn index(&self, key: K) -> Option<usize> {126if let Some(idx) = self.sparse.get(key).cloned() {127let idx = idx as usize;128if let Some(entry) = self.dense.get(idx) {129if entry.key() == key {130return Some(idx);131}132}133}134None135}136137/// Return `true` if the map contains a value corresponding to `key`.138pub fn contains_key(&self, key: K) -> bool {139self.get(key).is_some()140}141142/// Insert a value into the map.143///144/// If the map did not have this key present, `None` is returned.145///146/// If the map did have this key present, the value is updated, and the old value is returned.147///148/// It is not necessary to provide a key since the value knows its own key already.149pub fn insert(&mut self, value: V) -> Option<V> {150let key = value.key();151152// Replace the existing entry for `key` if there is one.153if let Some(entry) = self.get_mut(key) {154return Some(mem::replace(entry, value));155}156157// There was no previous entry for `key`. Add it to the end of `dense`.158let idx = self.dense.len();159debug_assert!(idx <= u32::MAX as usize, "SparseMap overflow");160self.dense.push(value);161self.sparse[key] = idx as u32;162None163}164165/// Remove a value from the map and return it.166pub fn remove(&mut self, key: K) -> Option<V> {167if let Some(idx) = self.index(key) {168let back = self.dense.pop().unwrap();169170// Are we popping the back of `dense`?171if idx == self.dense.len() {172return Some(back);173}174175// We're removing an element from the middle of `dense`.176// Replace the element at `idx` with the back of `dense`.177// Repair `sparse` first.178self.sparse[back.key()] = idx as u32;179return Some(mem::replace(&mut self.dense[idx], back));180}181182// Nothing to remove.183None184}185186/// Remove the last value from the map.187pub fn pop(&mut self) -> Option<V> {188self.dense.pop()189}190191/// Get an iterator over the values in the map.192///193/// The iteration order is entirely determined by the preceding sequence of `insert` and194/// `remove` operations. In particular, if no elements were removed, this is the insertion195/// order.196pub fn values(&self) -> slice::Iter<'_, V> {197self.dense.iter()198}199200/// Get the values as a slice.201pub fn as_slice(&self) -> &[V] {202self.dense.as_slice()203}204}205206impl<K, V> Default for SparseMap<K, V>207where208K: EntityRef,209V: SparseMapValue<K>,210{211fn default() -> SparseMap<K, V> {212SparseMap::new()213}214}215216impl<K, V> fmt::Debug for SparseMap<K, V>217where218K: EntityRef + fmt::Debug,219V: SparseMapValue<K> + fmt::Debug,220{221fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {222f.debug_map()223.entries(self.values().map(|v| (v.key(), v)))224.finish()225}226}227228/// Iterating over the elements of a set.229impl<'a, K, V> IntoIterator for &'a SparseMap<K, V>230where231K: EntityRef,232V: SparseMapValue<K>,233{234type Item = &'a V;235type IntoIter = slice::Iter<'a, V>;236237fn into_iter(self) -> Self::IntoIter {238self.values()239}240}241242/// Any `EntityRef` can be used as a sparse map value representing itself.243impl<T> SparseMapValue<T> for T244where245T: EntityRef,246{247fn key(&self) -> Self {248*self249}250}251252/// A sparse set of entity references.253///254/// Any type that implements `EntityRef` can be used as a sparse set value too.255pub type SparseSet<T> = SparseMap<T, T>;256257#[cfg(test)]258mod tests {259use alloc::format;260261use super::*;262263/// An opaque reference to an instruction in a function.264#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]265pub struct Inst(u32);266entity_impl!(Inst, "inst");267268// Mock key-value object for testing.269#[derive(PartialEq, Eq, Debug)]270struct Obj(Inst, &'static str);271272impl SparseMapValue<Inst> for Obj {273fn key(&self) -> Inst {274self.0275}276}277278#[test]279fn empty_immutable_map() {280let i1 = Inst::new(1);281let map: SparseMap<Inst, Obj> = SparseMap::new();282283assert!(map.is_empty());284assert_eq!(map.len(), 0);285assert_eq!(map.get(i1), None);286assert_eq!(map.values().count(), 0);287}288289#[test]290fn single_entry() {291let i0 = Inst::new(0);292let i1 = Inst::new(1);293let i2 = Inst::new(2);294let mut map = SparseMap::new();295296assert!(map.is_empty());297assert_eq!(map.len(), 0);298assert_eq!(map.get(i1), None);299assert_eq!(map.get_mut(i1), None);300assert_eq!(map.remove(i1), None);301302assert_eq!(map.insert(Obj(i1, "hi")), None);303assert!(!map.is_empty());304assert_eq!(map.len(), 1);305assert_eq!(map.get(i0), None);306assert_eq!(map.get(i1), Some(&Obj(i1, "hi")));307assert_eq!(map.get(i2), None);308assert_eq!(map.get_mut(i0), None);309assert_eq!(map.get_mut(i1), Some(&mut Obj(i1, "hi")));310assert_eq!(map.get_mut(i2), None);311312assert_eq!(map.remove(i0), None);313assert_eq!(map.remove(i2), None);314assert_eq!(map.remove(i1), Some(Obj(i1, "hi")));315assert_eq!(map.len(), 0);316assert_eq!(map.get(i1), None);317assert_eq!(map.get_mut(i1), None);318assert_eq!(map.remove(i0), None);319assert_eq!(map.remove(i1), None);320assert_eq!(map.remove(i2), None);321}322323#[test]324fn multiple_entries() {325let i0 = Inst::new(0);326let i1 = Inst::new(1);327let i2 = Inst::new(2);328let i3 = Inst::new(3);329let mut map = SparseMap::new();330331assert_eq!(map.insert(Obj(i2, "foo")), None);332assert_eq!(map.insert(Obj(i1, "bar")), None);333assert_eq!(map.insert(Obj(i0, "baz")), None);334335// Iteration order = insertion order when nothing has been removed yet.336assert_eq!(337map.values().map(|obj| obj.1).collect::<Vec<_>>(),338["foo", "bar", "baz"]339);340341assert_eq!(map.len(), 3);342assert_eq!(map.get(i0), Some(&Obj(i0, "baz")));343assert_eq!(map.get(i1), Some(&Obj(i1, "bar")));344assert_eq!(map.get(i2), Some(&Obj(i2, "foo")));345assert_eq!(map.get(i3), None);346347// Remove front object, causing back to be swapped down.348assert_eq!(map.remove(i1), Some(Obj(i1, "bar")));349assert_eq!(map.len(), 2);350assert_eq!(map.get(i0), Some(&Obj(i0, "baz")));351assert_eq!(map.get(i1), None);352assert_eq!(map.get(i2), Some(&Obj(i2, "foo")));353assert_eq!(map.get(i3), None);354355// Reinsert something at a previously used key.356assert_eq!(map.insert(Obj(i1, "barbar")), None);357assert_eq!(map.len(), 3);358assert_eq!(map.get(i0), Some(&Obj(i0, "baz")));359assert_eq!(map.get(i1), Some(&Obj(i1, "barbar")));360assert_eq!(map.get(i2), Some(&Obj(i2, "foo")));361assert_eq!(map.get(i3), None);362363// Replace an entry.364assert_eq!(map.insert(Obj(i0, "bazbaz")), Some(Obj(i0, "baz")));365assert_eq!(map.len(), 3);366assert_eq!(map.get(i0), Some(&Obj(i0, "bazbaz")));367assert_eq!(map.get(i1), Some(&Obj(i1, "barbar")));368assert_eq!(map.get(i2), Some(&Obj(i2, "foo")));369assert_eq!(map.get(i3), None);370371// Check the reference `IntoIter` impl.372let mut v = Vec::new();373for i in &map {374v.push(i.1);375}376assert_eq!(v.len(), map.len());377}378379#[test]380fn entity_set() {381let i0 = Inst::new(0);382let i1 = Inst::new(1);383let mut set = SparseSet::new();384385assert_eq!(set.insert(i0), None);386assert_eq!(set.insert(i0), Some(i0));387assert_eq!(set.insert(i1), None);388assert_eq!(set.get(i0), Some(&i0));389assert_eq!(set.get(i1), Some(&i1));390}391392#[test]393fn default_impl() {394let map: SparseMap<Inst, Obj> = SparseMap::default();395396assert!(map.is_empty());397assert_eq!(map.len(), 0);398}399400#[test]401fn debug_impl() {402let i1 = Inst::new(1);403let mut map = SparseMap::new();404assert_eq!(map.insert(Obj(i1, "hi")), None);405406let debug = format!("{map:?}");407let expected = "{inst1: Obj(inst1, \"hi\")}";408assert_eq!(debug, expected);409}410}411412413