@@ -1245,7 +1245,7 @@ impl RangeAllocator {
12451245 }
12461246 }
12471247
1248- fn base_for ( & mut self , real_addr : RealAddr , byte_len : ByteLen ) -> SyntheticAddr {
1248+ fn get_synthetic_addr ( & mut self , real_addr : RealAddr , byte_len : ByteLen ) -> SyntheticAddr {
12491249 if let Some ( & ( base, capacity) ) = self . bases . get ( & real_addr)
12501250 && byte_len <= capacity
12511251 {
@@ -1258,10 +1258,50 @@ impl RangeAllocator {
12581258 }
12591259}
12601260
1261+ struct PtrRegistry {
1262+ ranges : RangeAllocator ,
1263+ entries : BTreeMap < SyntheticAddr , ( AnyPtr , ByteLen ) > ,
1264+ swept_len : usize ,
1265+ }
1266+
1267+ impl PtrRegistry {
1268+ fn new ( ) -> Self {
1269+ Self {
1270+ ranges : RangeAllocator :: new ( ) ,
1271+ entries : BTreeMap :: new ( ) ,
1272+ swept_len : 0 ,
1273+ }
1274+ }
1275+
1276+ fn put ( & mut self , real_addr : RealAddr , byte_len : ByteLen , ptr : AnyPtr ) -> SyntheticAddr {
1277+ self . evict_dead ( ) ;
1278+ let base = self . ranges . get_synthetic_addr ( real_addr, byte_len) ;
1279+ self . entries . insert ( base, ( ptr, byte_len) ) ;
1280+ base
1281+ }
1282+
1283+ fn get ( & self , addr : SyntheticAddr ) -> Option < ( SyntheticAddr , AnyPtr , ByteLen ) > {
1284+ self . entries
1285+ . range ( ..=addr)
1286+ . next_back ( )
1287+ . map ( |( base, ( any, len) ) | ( * base, any. clone ( ) , * len) )
1288+ }
1289+
1290+ fn evict_dead ( & mut self ) {
1291+ if self . entries . len ( ) < 16 . max ( 2 * self . swept_len ) {
1292+ return ;
1293+ }
1294+ self . entries . retain ( |_, ( any, _) | !any. ptr . is_dangling ( ) ) ;
1295+ let entries = & self . entries ;
1296+ self . ranges
1297+ . bases
1298+ . retain ( |_, & mut ( base, _) | entries. contains_key ( & base) ) ;
1299+ self . swept_len = self . entries . len ( ) ;
1300+ }
1301+ }
1302+
12611303thread_local ! {
1262- static PTR_RANGE_ALLOC : RefCell <RangeAllocator > = RefCell :: new( RangeAllocator :: new( ) ) ;
1263- static PTR_REGISTRY : RefCell <BTreeMap <SyntheticAddr , ( AnyPtr , ByteLen ) >> =
1264- const { RefCell :: new( BTreeMap :: new( ) ) } ;
1304+ static PTR_REGISTRY : RefCell <PtrRegistry > = RefCell :: new( PtrRegistry :: new( ) ) ;
12651305}
12661306
12671307impl < T : ByteRepr > ByteRepr for Ptr < T > {
@@ -1281,13 +1321,13 @@ impl<T: ByteRepr> ByteRepr for Ptr<T> {
12811321 self . len ( ) * T :: byte_size ( ) ,
12821322 ) ,
12831323 } ;
1284- let base = PTR_RANGE_ALLOC . with ( |a| a. borrow_mut ( ) . base_for ( self . kind . address ( ) , byte_len) ) ;
12851324 let rebased = Ptr {
12861325 offset : 0 ,
12871326 kind : self . kind . clone ( ) ,
12881327 } ;
1289- PTR_REGISTRY . with ( |r| {
1290- r. borrow_mut ( ) . insert ( base, ( rebased. to_any ( ) , byte_len) ) ;
1328+ let base = PTR_REGISTRY . with ( |r| {
1329+ r. borrow_mut ( )
1330+ . put ( self . kind . address ( ) , byte_len, rebased. to_any ( ) )
12911331 } ) ;
12921332 base. wrapping_add ( byte_off) . to_bytes ( buf) ;
12931333 }
@@ -1297,12 +1337,7 @@ impl<T: ByteRepr> ByteRepr for Ptr<T> {
12971337 if addr == 0 {
12981338 return Ptr :: null ( ) ;
12991339 }
1300- let entry = PTR_REGISTRY . with ( |r| {
1301- r. borrow ( )
1302- . range ( ..=addr)
1303- . next_back ( )
1304- . map ( |( base, ( any, len) ) | ( * base, any. clone ( ) , * len) )
1305- } ) ;
1340+ let entry = PTR_REGISTRY . with ( |r| r. borrow ( ) . get ( addr) ) ;
13061341 let Some ( ( base, any, byte_len) ) = entry else {
13071342 panic ! ( "ub: cast of invalid address 0x{addr:x} to pointer" ) ;
13081343 } ;
0 commit comments