@@ -414,12 +414,16 @@ impl Cache {
414414 . next ( )
415415 }
416416
417- fn mapping_for_lib < ' a > ( & ' a mut self , lib : usize ) -> Option < ( & ' a mut Context < ' a > , & ' a Stash ) > {
417+ fn mapping_for_lib < ' a > ( & ' a mut self , lib : usize ) -> Option < ( & ' a mut Context < ' a > , & ' a Stash , Option < ( usize , Mapping ) > ) > {
418+ let mut evicted = None ;
418419 let cache_idx = self . mappings . iter ( ) . position ( |( lib_id, _) | * lib_id == lib) ;
419420
420421 let cache_entry = if let Some ( idx) = cache_idx {
421422 self . mappings . move_to_front ( idx)
422423 } else {
424+ if self . mappings . is_full ( ) {
425+ evicted = self . mappings . pop_back ( ) ;
426+ }
423427 // When the mapping is not in the cache, create a new mapping and insert it,
424428 // which will also evict the oldest entry.
425429 create_mapping ( & self . libraries [ lib] )
@@ -434,6 +438,7 @@ impl Cache {
434438 Some ( (
435439 unsafe { mem:: transmute :: < & ' a mut Context < ' static > , & ' a mut Context < ' a > > ( cx) } ,
436440 stash,
441+ evicted
437442 ) )
438443 }
439444}
@@ -456,10 +461,26 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
456461 None => return ,
457462 } ;
458463
464+ // If the cache needs to evict an entry to add a new one, we store
465+ // the evicted entry so we can restore it in case of recursion.
466+ struct CacheGuard < ' a > ( & ' a mut Cache , Option < ( usize , Mapping ) > ) ;
467+ impl Drop for CacheGuard < ' _ > {
468+ fn drop ( & mut self ) {
469+ if let Some ( entry) = self . 1 . take ( ) {
470+ self . 0 . mappings . push_back ( entry) ;
471+ }
472+ }
473+ }
474+ let mut guard = CacheGuard ( cache, None ) ;
475+ let cache = & mut guard. 0 ;
476+
459477 // Finally, get a cached mapping or create a new mapping for this file, and
460478 // evaluate the DWARF info to find the file/line/name for this address.
461479 let ( cx, stash) = match cache. mapping_for_lib ( lib) {
462- Some ( ( cx, stash) ) => ( cx, stash) ,
480+ Some ( ( cx, stash, evicted) ) => {
481+ guard. 1 = evicted;
482+ ( cx, stash)
483+ } ,
463484 None => return ,
464485 } ;
465486 let mut any_frames = false ;
0 commit comments