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