@@ -27,6 +27,7 @@ use gazebo::prelude::*;
27
27
use crate :: equivalent:: Equivalent ;
28
28
use crate :: hash_value:: StarlarkHashValue ;
29
29
use crate :: hashed:: Hashed ;
30
+ pub ( crate ) use crate :: vec2:: Vec2 ;
30
31
pub ( crate ) use crate :: vec_map:: iter:: IntoIter ;
31
32
pub ( crate ) use crate :: vec_map:: iter:: IntoIterHashed ;
32
33
pub ( crate ) use crate :: vec_map:: iter:: Iter ;
@@ -56,21 +57,21 @@ impl<K: Hash, V: Hash> Hash for Bucket<K, V> {
56
57
57
58
#[ derive( Debug , Clone , Eq , PartialEq , Default_ , Allocative ) ]
58
59
pub ( crate ) struct VecMap < K , V > {
59
- buckets : Vec < Bucket < K , V > > ,
60
+ buckets : Vec2 < ( K , V ) , StarlarkHashValue > ,
60
61
}
61
62
62
63
impl < K , V > VecMap < K , V > {
63
64
#[ inline]
64
65
pub ( crate ) const fn new ( ) -> Self {
65
66
VecMap {
66
- buckets : Vec :: new ( ) ,
67
+ buckets : Vec2 :: new ( ) ,
67
68
}
68
69
}
69
70
70
71
#[ inline]
71
72
pub ( crate ) fn with_capacity ( n : usize ) -> Self {
72
73
VecMap {
73
- buckets : Vec :: with_capacity ( n) ,
74
+ buckets : Vec2 :: with_capacity ( n) ,
74
75
}
75
76
}
76
77
@@ -95,9 +96,9 @@ impl<K, V> VecMap<K, V> {
95
96
) -> Option < ( usize , & K , & V ) > {
96
97
let mut i = 0 ;
97
98
#[ allow( clippy:: explicit_counter_loop) ] // we are paranoid about performance
98
- for b in & self . buckets {
99
- if b . hash == hash && eq ( & b . key ) {
100
- return Some ( ( i, & b . key , & b . value ) ) ;
99
+ for ( ( k , v ) , b_hash ) in & self . buckets {
100
+ if * b_hash == hash && eq ( k ) {
101
+ return Some ( ( i, k , v ) ) ;
101
102
}
102
103
i += 1 ;
103
104
}
@@ -123,30 +124,28 @@ impl<K, V> VecMap<K, V> {
123
124
124
125
#[ inline]
125
126
pub ( crate ) fn get_index ( & self , index : usize ) -> Option < ( & K , & V ) > {
126
- self . buckets . get ( index) . map ( |x| ( & x. key , & x. value ) )
127
+ let ( ( k, v) , _hash) = self . buckets . get ( index) ?;
128
+ Some ( ( k, v) )
127
129
}
128
130
129
131
#[ inline]
130
132
pub ( crate ) unsafe fn get_unchecked ( & self , index : usize ) -> ( Hashed < & K > , & V ) {
131
133
debug_assert ! ( index < self . buckets. len( ) ) ;
132
- let Bucket { hash , key, value } = self . buckets . get_unchecked ( index) ;
134
+ let ( ( key, value) , hash ) = self . buckets . get_unchecked ( index) ;
133
135
( Hashed :: new_unchecked ( * hash, key) , value)
134
136
}
135
137
136
138
#[ inline]
137
139
pub ( crate ) unsafe fn get_unchecked_mut ( & mut self , index : usize ) -> ( Hashed < & K > , & mut V ) {
138
140
debug_assert ! ( index < self . buckets. len( ) ) ;
139
- let Bucket { hash , key, value } = self . buckets . get_unchecked_mut ( index) ;
141
+ let ( ( key, value) , hash ) = self . buckets . get_unchecked_mut ( index) ;
140
142
( Hashed :: new_unchecked ( * hash, key) , value)
141
143
}
142
144
143
145
#[ inline]
144
146
pub ( crate ) fn insert_hashed_unique_unchecked ( & mut self , key : Hashed < K > , value : V ) {
145
- self . buckets . push ( Bucket {
146
- hash : key. hash ( ) ,
147
- key : key. into_key ( ) ,
148
- value,
149
- } ) ;
147
+ let hash = key. hash ( ) ;
148
+ self . buckets . push ( ( key. into_key ( ) , value) , hash) ;
150
149
}
151
150
152
151
pub ( crate ) fn remove_hashed_entry < Q > ( & mut self , key : Hashed < & Q > ) -> Option < ( K , V ) >
@@ -163,13 +162,13 @@ impl<K, V> VecMap<K, V> {
163
162
164
163
#[ inline]
165
164
pub ( crate ) fn remove ( & mut self , index : usize ) -> ( Hashed < K > , V ) {
166
- let Bucket { hash , key, value } = self . buckets . remove ( index) ;
165
+ let ( ( key, value) , hash ) = self . buckets . remove ( index) ;
167
166
( Hashed :: new_unchecked ( hash, key) , value)
168
167
}
169
168
170
169
#[ inline]
171
170
pub ( crate ) fn pop ( & mut self ) -> Option < ( Hashed < K > , V ) > {
172
- let Bucket { hash , key, value } = self . buckets . pop ( ) ?;
171
+ let ( ( key, value) , hash ) = self . buckets . pop ( ) ?;
173
172
Some ( ( Hashed :: new_unchecked ( hash, key) , value) )
174
173
}
175
174
@@ -237,22 +236,22 @@ impl<K, V> VecMap<K, V> {
237
236
#[ inline]
238
237
pub ( crate ) fn iter_mut ( & mut self ) -> IterMut < K , V > {
239
238
IterMut {
240
- iter : self . buckets . iter_mut ( ) ,
239
+ iter : self . buckets . keys_mut ( ) . iter_mut ( ) ,
241
240
}
242
241
}
243
242
244
243
pub ( crate ) fn sort_keys ( & mut self )
245
244
where
246
245
K : Ord ,
247
246
{
248
- self . buckets . sort_unstable_by ( | a, b | a. key . cmp ( & b. key ) ) ;
247
+ self . buckets . sort_by ( | ( a, _ah ) , ( b , _bh ) | a. 0 . cmp ( & b. 0 ) ) ;
249
248
}
250
249
251
250
pub ( crate ) fn is_sorted_by_key ( & self ) -> bool
252
251
where
253
252
K : Ord ,
254
253
{
255
- self . buckets . windows ( 2 ) . all ( |w| w[ 0 ] . key <= w[ 1 ] . key )
254
+ self . buckets . keys ( ) . windows ( 2 ) . all ( |w| w[ 0 ] . 0 <= w[ 1 ] . 0 )
256
255
}
257
256
258
257
/// Equal if entries are equal in the iterator order.
@@ -261,7 +260,10 @@ impl<K, V> VecMap<K, V> {
261
260
K : PartialEq ,
262
261
V : PartialEq ,
263
262
{
264
- self . buckets . eq ( & other. buckets )
263
+ // We compare hashes before comparing keys and values because it is faster
264
+ // (fewer branches, and no comparison of the rest it at lest one hash is different).
265
+ self . buckets . values ( ) == other. buckets . values ( )
266
+ && self . buckets . keys ( ) == other. buckets . keys ( )
265
267
}
266
268
267
269
/// Hash entries in the iterator order.
@@ -272,6 +274,8 @@ impl<K, V> VecMap<K, V> {
272
274
K : Hash ,
273
275
V : Hash ,
274
276
{
275
- self . buckets . hash ( state) ;
277
+ for e in self . iter_hashed ( ) {
278
+ e. hash ( state) ;
279
+ }
276
280
}
277
281
}
0 commit comments