@@ -27,6 +27,7 @@ use gazebo::prelude::*;
2727use crate :: equivalent:: Equivalent ;
2828use crate :: hash_value:: StarlarkHashValue ;
2929use crate :: hashed:: Hashed ;
30+ pub ( crate ) use crate :: vec2:: Vec2 ;
3031pub ( crate ) use crate :: vec_map:: iter:: IntoIter ;
3132pub ( crate ) use crate :: vec_map:: iter:: IntoIterHashed ;
3233pub ( crate ) use crate :: vec_map:: iter:: Iter ;
@@ -56,21 +57,21 @@ impl<K: Hash, V: Hash> Hash for Bucket<K, V> {
5657
5758#[ derive( Debug , Clone , Eq , PartialEq , Default_ , Allocative ) ]
5859pub ( crate ) struct VecMap < K , V > {
59- buckets : Vec < Bucket < K , V > > ,
60+ buckets : Vec2 < ( K , V ) , StarlarkHashValue > ,
6061}
6162
6263impl < K , V > VecMap < K , V > {
6364 #[ inline]
6465 pub ( crate ) const fn new ( ) -> Self {
6566 VecMap {
66- buckets : Vec :: new ( ) ,
67+ buckets : Vec2 :: new ( ) ,
6768 }
6869 }
6970
7071 #[ inline]
7172 pub ( crate ) fn with_capacity ( n : usize ) -> Self {
7273 VecMap {
73- buckets : Vec :: with_capacity ( n) ,
74+ buckets : Vec2 :: with_capacity ( n) ,
7475 }
7576 }
7677
@@ -95,9 +96,9 @@ impl<K, V> VecMap<K, V> {
9596 ) -> Option < ( usize , & K , & V ) > {
9697 let mut i = 0 ;
9798 #[ 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 ) ) ;
101102 }
102103 i += 1 ;
103104 }
@@ -123,30 +124,28 @@ impl<K, V> VecMap<K, V> {
123124
124125 #[ inline]
125126 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) )
127129 }
128130
129131 #[ inline]
130132 pub ( crate ) unsafe fn get_unchecked ( & self , index : usize ) -> ( Hashed < & K > , & V ) {
131133 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) ;
133135 ( Hashed :: new_unchecked ( * hash, key) , value)
134136 }
135137
136138 #[ inline]
137139 pub ( crate ) unsafe fn get_unchecked_mut ( & mut self , index : usize ) -> ( Hashed < & K > , & mut V ) {
138140 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) ;
140142 ( Hashed :: new_unchecked ( * hash, key) , value)
141143 }
142144
143145 #[ inline]
144146 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) ;
150149 }
151150
152151 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> {
163162
164163 #[ inline]
165164 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) ;
167166 ( Hashed :: new_unchecked ( hash, key) , value)
168167 }
169168
170169 #[ inline]
171170 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 ( ) ?;
173172 Some ( ( Hashed :: new_unchecked ( hash, key) , value) )
174173 }
175174
@@ -237,22 +236,22 @@ impl<K, V> VecMap<K, V> {
237236 #[ inline]
238237 pub ( crate ) fn iter_mut ( & mut self ) -> IterMut < K , V > {
239238 IterMut {
240- iter : self . buckets . iter_mut ( ) ,
239+ iter : self . buckets . keys_mut ( ) . iter_mut ( ) ,
241240 }
242241 }
243242
244243 pub ( crate ) fn sort_keys ( & mut self )
245244 where
246245 K : Ord ,
247246 {
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 ) ) ;
249248 }
250249
251250 pub ( crate ) fn is_sorted_by_key ( & self ) -> bool
252251 where
253252 K : Ord ,
254253 {
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 )
256255 }
257256
258257 /// Equal if entries are equal in the iterator order.
@@ -261,7 +260,10 @@ impl<K, V> VecMap<K, V> {
261260 K : PartialEq ,
262261 V : PartialEq ,
263262 {
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 ( )
265267 }
266268
267269 /// Hash entries in the iterator order.
@@ -272,6 +274,8 @@ impl<K, V> VecMap<K, V> {
272274 K : Hash ,
273275 V : Hash ,
274276 {
275- self . buckets . hash ( state) ;
277+ for e in self . iter_hashed ( ) {
278+ e. hash ( state) ;
279+ }
276280 }
277281}
0 commit comments