1
1
use super :: bitmask:: BitMask ;
2
- use super :: EMPTY ;
2
+ use super :: Tag ;
3
3
use core:: { mem, ptr} ;
4
4
5
5
// Use the native word size as the group size. Using a 64-bit group size on
@@ -24,18 +24,18 @@ cfg_if! {
24
24
pub ( crate ) type BitMaskWord = GroupWord ;
25
25
pub ( crate ) type NonZeroBitMaskWord = NonZeroGroupWord ;
26
26
pub ( crate ) const BITMASK_STRIDE : usize = 8 ;
27
- // We only care about the highest bit of each byte for the mask.
27
+ // We only care about the highest bit of each tag for the mask.
28
28
#[ allow( clippy:: cast_possible_truncation, clippy:: unnecessary_cast) ]
29
- pub ( crate ) const BITMASK_MASK : BitMaskWord = 0x8080_8080_8080_8080_u64 as GroupWord ;
29
+ pub ( crate ) const BITMASK_MASK : BitMaskWord = u64 :: from_ne_bytes ( [ Tag :: DELETED . 0 ; 8 ] ) as GroupWord ;
30
30
pub ( crate ) const BITMASK_ITER_MASK : BitMaskWord = !0 ;
31
31
32
- /// Helper function to replicate a byte across a `GroupWord`.
32
+ /// Helper function to replicate a tag across a `GroupWord`.
33
33
#[ inline]
34
- fn repeat ( byte : u8 ) -> GroupWord {
35
- GroupWord :: from_ne_bytes ( [ byte ; Group :: WIDTH ] )
34
+ fn repeat ( tag : Tag ) -> GroupWord {
35
+ GroupWord :: from_ne_bytes ( [ tag . 0 ; Group :: WIDTH ] )
36
36
}
37
37
38
- /// Abstraction over a group of control bytes which can be scanned in
38
+ /// Abstraction over a group of control tags which can be scanned in
39
39
/// parallel.
40
40
///
41
41
/// This implementation uses a word-sized integer.
@@ -51,94 +51,94 @@ impl Group {
51
51
/// Number of bytes in the group.
52
52
pub ( crate ) const WIDTH : usize = mem:: size_of :: < Self > ( ) ;
53
53
54
- /// Returns a full group of empty bytes , suitable for use as the initial
54
+ /// Returns a full group of empty tags , suitable for use as the initial
55
55
/// value for an empty hash table.
56
56
///
57
57
/// This is guaranteed to be aligned to the group size.
58
58
#[ inline]
59
- pub ( crate ) const fn static_empty ( ) -> & ' static [ u8 ; Group :: WIDTH ] {
59
+ pub ( crate ) const fn static_empty ( ) -> & ' static [ Tag ; Group :: WIDTH ] {
60
60
#[ repr( C ) ]
61
- struct AlignedBytes {
61
+ struct AlignedTags {
62
62
_align : [ Group ; 0 ] ,
63
- bytes : [ u8 ; Group :: WIDTH ] ,
63
+ tags : [ Tag ; Group :: WIDTH ] ,
64
64
}
65
- const ALIGNED_BYTES : AlignedBytes = AlignedBytes {
65
+ const ALIGNED_TAGS : AlignedTags = AlignedTags {
66
66
_align : [ ] ,
67
- bytes : [ EMPTY ; Group :: WIDTH ] ,
67
+ tags : [ Tag :: EMPTY ; Group :: WIDTH ] ,
68
68
} ;
69
- & ALIGNED_BYTES . bytes
69
+ & ALIGNED_TAGS . tags
70
70
}
71
71
72
- /// Loads a group of bytes starting at the given address.
72
+ /// Loads a group of tags starting at the given address.
73
73
#[ inline]
74
74
#[ allow( clippy:: cast_ptr_alignment) ] // unaligned load
75
- pub ( crate ) unsafe fn load ( ptr : * const u8 ) -> Self {
75
+ pub ( crate ) unsafe fn load ( ptr : * const Tag ) -> Self {
76
76
Group ( ptr:: read_unaligned ( ptr. cast ( ) ) )
77
77
}
78
78
79
- /// Loads a group of bytes starting at the given address, which must be
79
+ /// Loads a group of tags starting at the given address, which must be
80
80
/// aligned to `mem::align_of::<Group>()`.
81
81
#[ inline]
82
82
#[ allow( clippy:: cast_ptr_alignment) ]
83
- pub ( crate ) unsafe fn load_aligned ( ptr : * const u8 ) -> Self {
83
+ pub ( crate ) unsafe fn load_aligned ( ptr : * const Tag ) -> Self {
84
84
// FIXME: use align_offset once it stabilizes
85
85
debug_assert_eq ! ( ptr as usize & ( mem:: align_of:: <Self >( ) - 1 ) , 0 ) ;
86
86
Group ( ptr:: read ( ptr. cast ( ) ) )
87
87
}
88
88
89
- /// Stores the group of bytes to the given address, which must be
89
+ /// Stores the group of tags to the given address, which must be
90
90
/// aligned to `mem::align_of::<Group>()`.
91
91
#[ inline]
92
92
#[ allow( clippy:: cast_ptr_alignment) ]
93
- pub ( crate ) unsafe fn store_aligned ( self , ptr : * mut u8 ) {
93
+ pub ( crate ) unsafe fn store_aligned ( self , ptr : * mut Tag ) {
94
94
// FIXME: use align_offset once it stabilizes
95
95
debug_assert_eq ! ( ptr as usize & ( mem:: align_of:: <Self >( ) - 1 ) , 0 ) ;
96
96
ptr:: write ( ptr. cast ( ) , self . 0 ) ;
97
97
}
98
98
99
- /// Returns a `BitMask` indicating all bytes in the group which *may*
99
+ /// Returns a `BitMask` indicating all tags in the group which *may*
100
100
/// have the given value.
101
101
///
102
102
/// This function may return a false positive in certain cases where
103
- /// the byte in the group differs from the searched value only in its
103
+ /// the tag in the group differs from the searched value only in its
104
104
/// lowest bit. This is fine because:
105
105
/// - This never happens for `EMPTY` and `DELETED`, only full entries.
106
106
/// - The check for key equality will catch these.
107
107
/// - This only happens if there is at least 1 true match.
108
108
/// - The chance of this happening is very low (< 1% chance per byte).
109
109
#[ inline]
110
- pub ( crate ) fn match_byte ( self , byte : u8 ) -> BitMask {
110
+ pub ( crate ) fn match_tag ( self , tag : Tag ) -> BitMask {
111
111
// This algorithm is derived from
112
112
// https://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
113
- let cmp = self . 0 ^ repeat ( byte ) ;
114
- BitMask ( ( cmp. wrapping_sub ( repeat ( 0x01 ) ) & !cmp & repeat ( 0x80 ) ) . to_le ( ) )
113
+ let cmp = self . 0 ^ repeat ( tag ) ;
114
+ BitMask ( ( cmp. wrapping_sub ( repeat ( Tag ( 0x01 ) ) ) & !cmp & repeat ( Tag :: DELETED ) ) . to_le ( ) )
115
115
}
116
116
117
- /// Returns a `BitMask` indicating all bytes in the group which are
117
+ /// Returns a `BitMask` indicating all tags in the group which are
118
118
/// `EMPTY`.
119
119
#[ inline]
120
120
pub ( crate ) fn match_empty ( self ) -> BitMask {
121
- // If the high bit is set, then the byte must be either:
121
+ // If the high bit is set, then the tag must be either:
122
122
// 1111_1111 (EMPTY) or 1000_0000 (DELETED).
123
123
// So we can just check if the top two bits are 1 by ANDing them.
124
- BitMask ( ( self . 0 & ( self . 0 << 1 ) & repeat ( 0x80 ) ) . to_le ( ) )
124
+ BitMask ( ( self . 0 & ( self . 0 << 1 ) & repeat ( Tag :: DELETED ) ) . to_le ( ) )
125
125
}
126
126
127
- /// Returns a `BitMask` indicating all bytes in the group which are
127
+ /// Returns a `BitMask` indicating all tags in the group which are
128
128
/// `EMPTY` or `DELETED`.
129
129
#[ inline]
130
130
pub ( crate ) fn match_empty_or_deleted ( self ) -> BitMask {
131
- // A byte is EMPTY or DELETED iff the high bit is set
132
- BitMask ( ( self . 0 & repeat ( 0x80 ) ) . to_le ( ) )
131
+ // A tag is EMPTY or DELETED iff the high bit is set
132
+ BitMask ( ( self . 0 & repeat ( Tag :: DELETED ) ) . to_le ( ) )
133
133
}
134
134
135
- /// Returns a `BitMask` indicating all bytes in the group which are full.
135
+ /// Returns a `BitMask` indicating all tags in the group which are full.
136
136
#[ inline]
137
137
pub ( crate ) fn match_full ( self ) -> BitMask {
138
138
self . match_empty_or_deleted ( ) . invert ( )
139
139
}
140
140
141
- /// Performs the following transformation on all bytes in the group:
141
+ /// Performs the following transformation on all tags in the group:
142
142
/// - `EMPTY => EMPTY`
143
143
/// - `DELETED => EMPTY`
144
144
/// - `FULL => DELETED`
@@ -151,7 +151,7 @@ impl Group {
151
151
// let full = 1000_0000 (true) or 0000_0000 (false)
152
152
// !1000_0000 + 1 = 0111_1111 + 1 = 1000_0000 (no carry)
153
153
// !0000_0000 + 0 = 1111_1111 + 0 = 1111_1111 (no carry)
154
- let full = !self . 0 & repeat ( 0x80 ) ;
154
+ let full = !self . 0 & repeat ( Tag :: DELETED ) ;
155
155
Group ( !full + ( full >> 7 ) )
156
156
}
157
157
}
0 commit comments