@@ -18,6 +18,7 @@ use table::{
1818 SafeHash
1919} ;
2020use internal_entry:: InternalEntry ;
21+ use entry:: VacantEntryState ;
2122use entry:: VacantEntryState :: NeqElem ;
2223use entry:: VacantEntryState :: NoElem ;
2324use HashMap ;
@@ -56,6 +57,7 @@ macro_rules! specialize {
5657 #[ inline]
5758 fn safeguarded_search( & mut self , key: & $key_type, hash: SafeHash )
5859 -> InternalEntryMut <$key_type, V > {
60+
5961 let table_capacity = self . table. capacity( ) ;
6062 let entry = search_hashed( DerefMapToTable ( self ) , hash, |k| k == key) ;
6163 match entry {
@@ -67,43 +69,7 @@ macro_rules! specialize {
6769 InternalEntry :: TableIsEmpty
6870 }
6971 InternalEntry :: Vacant { elem, hash } => {
70- let index = match elem {
71- NeqElem ( ref bucket, _) => bucket. index( ) ,
72- NoElem ( ref bucket) => bucket. index( ) ,
73- } ;
74- // Copied from FullBucket::displacement.
75- let displacement =
76- index. wrapping_sub( hash. inspect( ) as usize ) & ( table_capacity - 1 ) ;
77- if displacement > DISPLACEMENT_THRESHOLD {
78- let map = match elem {
79- NeqElem ( bucket, _) => {
80- bucket. into_table( )
81- }
82- NoElem ( bucket) => {
83- bucket. into_table( )
84- }
85- } ;
86- // Probe sequence is too long.
87- // Adapt to safe hashing if desirable.
88- maybe_adapt_to_safe_hashing( map. 0 ) ;
89- search_hashed( & mut map. 0 . table, hash, |k| k == key)
90- } else {
91- // This should compile down to a no-op.
92- match elem {
93- NeqElem ( bucket, ib) => {
94- InternalEntry :: Vacant {
95- elem: NeqElem ( bucket. convert_table( ) , ib) ,
96- hash: hash,
97- }
98- }
99- NoElem ( bucket) => {
100- InternalEntry :: Vacant {
101- elem: NoElem ( bucket. convert_table( ) ) ,
102- hash: hash,
103- }
104- }
105- }
106- }
72+ safeguard_vacant_entry( elem, key, hash, table_capacity)
10773 }
10874 }
10975 }
@@ -118,10 +84,60 @@ macro_rules! specialize {
11884 )
11985}
12086
87+ #[ inline]
88+ fn safeguard_vacant_entry < ' a , K , V > (
89+ elem : VacantEntryState < K , V , DerefMapToTable < ' a , K , V , AdaptiveState > > ,
90+ key : & K ,
91+ hash : SafeHash ,
92+ table_capacity : usize ,
93+ ) -> InternalEntryMut < ' a , K , V >
94+ where K : Eq + Hash
95+ {
96+ let index = match elem {
97+ NeqElem ( ref bucket, _) => bucket. index ( ) ,
98+ NoElem ( ref bucket) => bucket. index ( ) ,
99+ } ;
100+ // Copied from FullBucket::displacement.
101+ let displacement = index. wrapping_sub ( hash. inspect ( ) as usize ) & ( table_capacity - 1 ) ;
102+ if displacement > DISPLACEMENT_THRESHOLD {
103+ // Probe sequence is too long.
104+ maybe_adapt_to_safe_hashing ( elem, key, hash)
105+ } else {
106+ // This should compile down to a no-op.
107+ match elem {
108+ NeqElem ( bucket, ib) => {
109+ InternalEntry :: Vacant {
110+ elem : NeqElem ( bucket. convert_table ( ) , ib) ,
111+ hash : hash,
112+ }
113+ }
114+ NoElem ( bucket) => {
115+ InternalEntry :: Vacant {
116+ elem : NoElem ( bucket. convert_table ( ) ) ,
117+ hash : hash,
118+ }
119+ }
120+ }
121+ }
122+ }
123+
124+ // Adapt to safe hashing if desirable.
121125#[ cold]
122- fn maybe_adapt_to_safe_hashing < K , V > ( map : & mut HashMap < K , V , AdaptiveState > )
126+ fn maybe_adapt_to_safe_hashing < ' a , K , V > (
127+ elem : VacantEntryState < K , V , DerefMapToTable < ' a , K , V , AdaptiveState > > ,
128+ key : & K ,
129+ hash : SafeHash
130+ ) -> InternalEntryMut < ' a , K , V >
123131 where K : Eq + Hash
124132{
133+ let map = match elem {
134+ NeqElem ( bucket, _) => {
135+ bucket. into_table ( ) . 0
136+ }
137+ NoElem ( bucket) => {
138+ bucket. into_table ( ) . 0
139+ }
140+ } ;
125141 let capacity = map. table . capacity ( ) ;
126142 let load_factor = map. len ( ) as f32 / capacity as f32 ;
127143 if load_factor >= LOAD_FACTOR_THRESHOLD {
@@ -134,6 +150,7 @@ fn maybe_adapt_to_safe_hashing<K, V>(map: &mut HashMap<K, V, AdaptiveState>)
134150 map. insert_hashed_nocheck ( hash, k, v) ;
135151 }
136152 }
153+ search_hashed ( & mut map. table , hash, |k| k == key)
137154}
138155
139156specialize ! { K = u8 ; }
0 commit comments