/rust/registry/src/index.crates.io-1949cf8c6b5b557f/cranelift-codegen-0.128.3/src/constant_hash.rs
Line | Count | Source |
1 | | //! Runtime support for precomputed constant hash tables. |
2 | | //! |
3 | | //! The shared module with the same name can generate constant hash tables using open addressing |
4 | | //! and quadratic probing. |
5 | | //! |
6 | | //! The hash tables are arrays that are guaranteed to: |
7 | | //! |
8 | | //! - Have a power-of-two size. |
9 | | //! - Contain at least one empty slot. |
10 | | //! |
11 | | //! This module provides runtime support for lookups in these tables. |
12 | | |
13 | | // Re-export entities from constant_hash for simplicity of use. |
14 | | pub use cranelift_codegen_shared::constant_hash::*; |
15 | | |
16 | | /// Trait that must be implemented by the entries in a constant hash table. |
17 | | pub trait Table<K: Copy + Eq> { |
18 | | /// Get the number of entries in this table which must be a power of two. |
19 | | fn len(&self) -> usize; |
20 | | |
21 | | /// Get the key corresponding to the entry at `idx`, or `None` if the entry is empty. |
22 | | /// The `idx` must be in range. |
23 | | fn key(&self, idx: usize) -> Option<K>; |
24 | | } |
25 | | |
26 | | /// Look for `key` in `table`. |
27 | | /// |
28 | | /// The provided `hash` value must have been computed from `key` using the same hash function that |
29 | | /// was used to construct the table. |
30 | | /// |
31 | | /// Returns `Ok(idx)` with the table index containing the found entry, or `Err(idx)` with the empty |
32 | | /// sentinel entry if no entry could be found. |
33 | 363k | pub fn probe<K: Copy + Eq, T: Table<K> + ?Sized>( |
34 | 363k | table: &T, |
35 | 363k | key: K, |
36 | 363k | hash: usize, |
37 | 363k | ) -> Result<usize, usize> { |
38 | 363k | debug_assert!(table.len().is_power_of_two()); |
39 | 363k | let mask = table.len() - 1; |
40 | | |
41 | 363k | let mut idx = hash; |
42 | 363k | let mut step = 0; |
43 | | |
44 | | loop { |
45 | 492k | idx &= mask; |
46 | | |
47 | 492k | match table.key(idx) { |
48 | 0 | None => return Err(idx), |
49 | 492k | Some(k) if k == key => return Ok(idx), |
50 | 128k | _ => {} |
51 | | } |
52 | | |
53 | | // Quadratic probing. |
54 | 128k | step += 1; |
55 | | |
56 | | // When `table.len()` is a power of two, it can be proven that `idx` will visit all |
57 | | // entries. This means that this loop will always terminate if the hash table has even |
58 | | // one unused entry. |
59 | 128k | debug_assert!(step < table.len()); |
60 | 128k | idx += step; |
61 | | } |
62 | 363k | } cranelift_codegen::constant_hash::probe::<&str, cranelift_codegen::settings::detail::Template> Line | Count | Source | 33 | 149k | pub fn probe<K: Copy + Eq, T: Table<K> + ?Sized>( | 34 | 149k | table: &T, | 35 | 149k | key: K, | 36 | 149k | hash: usize, | 37 | 149k | ) -> Result<usize, usize> { | 38 | 149k | debug_assert!(table.len().is_power_of_two()); | 39 | 149k | let mask = table.len() - 1; | 40 | | | 41 | 149k | let mut idx = hash; | 42 | 149k | let mut step = 0; | 43 | | | 44 | | loop { | 45 | 202k | idx &= mask; | 46 | | | 47 | 202k | match table.key(idx) { | 48 | 0 | None => return Err(idx), | 49 | 202k | Some(k) if k == key => return Ok(idx), | 50 | 52.8k | _ => {} | 51 | | } | 52 | | | 53 | | // Quadratic probing. | 54 | 52.8k | step += 1; | 55 | | | 56 | | // When `table.len()` is a power of two, it can be proven that `idx` will visit all | 57 | | // entries. This means that this loop will always terminate if the hash table has even | 58 | | // one unused entry. | 59 | 52.8k | debug_assert!(step < table.len()); | 60 | 52.8k | idx += step; | 61 | | } | 62 | 149k | } |
Unexecuted instantiation: cranelift_codegen::constant_hash::probe::<&str, [core::option::Option<cranelift_codegen::ir::instructions::Opcode>]> cranelift_codegen::constant_hash::probe::<&str, cranelift_codegen::settings::detail::Template> Line | Count | Source | 33 | 214k | pub fn probe<K: Copy + Eq, T: Table<K> + ?Sized>( | 34 | 214k | table: &T, | 35 | 214k | key: K, | 36 | 214k | hash: usize, | 37 | 214k | ) -> Result<usize, usize> { | 38 | 214k | debug_assert!(table.len().is_power_of_two()); | 39 | 214k | let mask = table.len() - 1; | 40 | | | 41 | 214k | let mut idx = hash; | 42 | 214k | let mut step = 0; | 43 | | | 44 | | loop { | 45 | 289k | idx &= mask; | 46 | | | 47 | 289k | match table.key(idx) { | 48 | 0 | None => return Err(idx), | 49 | 289k | Some(k) if k == key => return Ok(idx), | 50 | 75.5k | _ => {} | 51 | | } | 52 | | | 53 | | // Quadratic probing. | 54 | 75.5k | step += 1; | 55 | | | 56 | | // When `table.len()` is a power of two, it can be proven that `idx` will visit all | 57 | | // entries. This means that this loop will always terminate if the hash table has even | 58 | | // one unused entry. | 59 | 75.5k | debug_assert!(step < table.len()); | 60 | 75.5k | idx += step; | 61 | | } | 62 | 214k | } |
Unexecuted instantiation: cranelift_codegen::constant_hash::probe::<&str, [core::option::Option<cranelift_codegen::ir::instructions::Opcode>]> |