@@ -371,9 +371,9 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
371
371
return InternalEntry :: TableIsEmpty ;
372
372
}
373
373
374
- let size = table. size ( ) as isize ;
374
+ let size = table. size ( ) ;
375
375
let mut probe = Bucket :: new ( table, hash) ;
376
- let ib = probe . index ( ) as isize ;
376
+ let mut displacement = 0 ;
377
377
378
378
loop {
379
379
let full = match probe. peek ( ) {
@@ -387,15 +387,15 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
387
387
Full ( bucket) => bucket,
388
388
} ;
389
389
390
- let robin_ib = full. index ( ) as isize - full . displacement ( ) as isize ;
390
+ let probe_displacement = full. displacement ( ) ;
391
391
392
- if ib < robin_ib {
392
+ if probe_displacement < displacement {
393
393
// Found a luckier bucket than me.
394
394
// We can finish the search early if we hit any bucket
395
395
// with a lower distance to initial bucket than we've probed.
396
396
return InternalEntry :: Vacant {
397
397
hash : hash,
398
- elem : NeqElem ( full, robin_ib as usize ) ,
398
+ elem : NeqElem ( full, probe_displacement ) ,
399
399
} ;
400
400
}
401
401
@@ -406,9 +406,9 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
406
406
return InternalEntry :: Occupied { elem : full } ;
407
407
}
408
408
}
409
-
409
+ displacement += 1 ;
410
410
probe = full. next ( ) ;
411
- debug_assert ! ( probe . index ( ) as isize != ib + size + 1 ) ;
411
+ debug_assert ! ( displacement <= size) ;
412
412
}
413
413
}
414
414
@@ -431,12 +431,11 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
431
431
}
432
432
433
433
/// Perform robin hood bucket stealing at the given `bucket`. You must
434
- /// also pass the position of that bucket's initial bucket so we don't have
435
- /// to recalculate it.
434
+ /// also pass that bucket's displacement so we don't have to recalculate it.
436
435
///
437
436
/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable.
438
437
fn robin_hood < ' a , K : ' a , V : ' a > ( bucket : FullBucketMut < ' a , K , V > ,
439
- mut ib : usize ,
438
+ mut displacement : usize ,
440
439
mut hash : SafeHash ,
441
440
mut key : K ,
442
441
mut val : V )
@@ -457,6 +456,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
457
456
val = old_val;
458
457
459
458
loop {
459
+ displacement += 1 ;
460
460
let probe = bucket. next ( ) ;
461
461
debug_assert ! ( probe. index( ) != idx_end) ;
462
462
@@ -476,13 +476,13 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
476
476
Full ( bucket) => bucket,
477
477
} ;
478
478
479
- let probe_ib = full_bucket . index ( ) - full_bucket. displacement ( ) ;
479
+ let probe_displacement = full_bucket. displacement ( ) ;
480
480
481
481
bucket = full_bucket;
482
482
483
483
// Robin hood! Steal the spot.
484
- if ib < probe_ib {
485
- ib = probe_ib ;
484
+ if probe_displacement < displacement {
485
+ displacement = probe_displacement ;
486
486
break ;
487
487
}
488
488
}
@@ -520,13 +520,16 @@ impl<K, V, S> HashMap<K, V, S>
520
520
search_hashed ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) )
521
521
}
522
522
523
- // The caller should ensure that invariants by Robin Hood Hashing hold.
523
+ // The caller should ensure that invariants by Robin Hood Hashing hold
524
+ // and that there's space in the underlying table.
524
525
fn insert_hashed_ordered ( & mut self , hash : SafeHash , k : K , v : V ) {
525
526
let raw_cap = self . raw_capacity ( ) ;
526
527
let mut buckets = Bucket :: new ( & mut self . table , hash) ;
527
- let ib = buckets. index ( ) ;
528
+ // note that buckets.index() keeps increasing
529
+ // even if the pointer wraps back to the first bucket.
530
+ let limit_bucket = buckets. index ( ) + raw_cap;
528
531
529
- while buckets . index ( ) != ib + raw_cap {
532
+ loop {
530
533
// We don't need to compare hashes for value swap.
531
534
// Not even DIBs for Robin Hood.
532
535
buckets = match buckets. peek ( ) {
@@ -537,8 +540,8 @@ impl<K, V, S> HashMap<K, V, S>
537
540
Full ( b) => b. into_bucket ( ) ,
538
541
} ;
539
542
buckets. next ( ) ;
543
+ debug_assert ! ( buckets. index( ) < limit_bucket) ;
540
544
}
541
- panic ! ( "Internal HashMap error: Out of space." ) ;
542
545
}
543
546
}
544
547
@@ -1959,7 +1962,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
1959
1962
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1960
1963
pub fn insert ( self , value : V ) -> & ' a mut V {
1961
1964
match self . elem {
1962
- NeqElem ( bucket, ib ) => robin_hood ( bucket, ib , self . hash , self . key , value) ,
1965
+ NeqElem ( bucket, disp ) => robin_hood ( bucket, disp , self . hash , self . key , value) ,
1963
1966
NoElem ( bucket) => bucket. put ( self . hash , self . key , value) . into_mut_refs ( ) . 1 ,
1964
1967
}
1965
1968
}
0 commit comments