@@ -27,9 +27,9 @@ pub type GlobalState = RefCell<GlobalStateInner>;
2727#[ derive( Clone , Debug ) ]
2828pub struct GlobalStateInner {
2929 /// This is used as a map between the address of each allocation and its `AllocId`. It is always
30- /// sorted. We cannot use a `HashMap` since we can be given an address that is offset from the
31- /// base address, and we need to find the `AllocId` it belongs to.
32- /// This is not the *full* inverse of `base_addr`; dead allocations have been removed.
30+ /// sorted by address . We cannot use a `HashMap` since we can be given an address that is offset
31+ /// from the base address, and we need to find the `AllocId` it belongs to. This is not the
32+ /// *full* inverse of `base_addr`; dead allocations have been removed.
3333 int_to_ptr_map : Vec < ( u64 , AllocId ) > ,
3434 /// The base address for each allocation. We cannot put that into
3535 /// `AllocExtra` because function pointers also have a base address, and
@@ -285,7 +285,12 @@ impl GlobalStateInner {
285285 // However, we *can* remove it from `int_to_ptr_map`, since any wildcard pointers that exist
286286 // can no longer actually be accessing that address. This ensures `alloc_id_from_addr` never
287287 // returns a dead allocation.
288- self . int_to_ptr_map . retain ( |& ( _, id) | id != dead_id) ;
288+ // To avoid a linear scan we first look up the address in `base_addr`, and then find it in
289+ // `int_to_ptr_map`.
290+ let addr = * self . base_addr . get ( & dead_id) . unwrap ( ) ;
291+ let pos = self . int_to_ptr_map . binary_search_by_key ( & addr, |( addr, _) | * addr) . unwrap ( ) ;
292+ let removed = self . int_to_ptr_map . remove ( pos) ;
293+ assert_eq ! ( removed, ( addr, dead_id) ) ; // double-check that we removed the right thing
289294 // We can also remove it from `exposed`, since this allocation can anyway not be returned by
290295 // `alloc_id_from_addr` any more.
291296 self . exposed . remove ( & dead_id) ;
0 commit comments