@@ -1286,7 +1286,7 @@ impl RangeAllocator {
12861286 }
12871287 }
12881288
1289- fn base_for ( & mut self , real_addr : RealAddr , byte_len : ByteLen ) -> SyntheticAddr {
1289+ fn get_synthetic_addr ( & mut self , real_addr : RealAddr , byte_len : ByteLen ) -> SyntheticAddr {
12901290 if let Some ( & ( base, capacity) ) = self . bases . get ( & real_addr)
12911291 && byte_len <= capacity
12921292 {
@@ -1299,10 +1299,50 @@ impl RangeAllocator {
12991299 }
13001300}
13011301
1302+ struct PtrRegistry {
1303+ ranges : RangeAllocator ,
1304+ entries : BTreeMap < SyntheticAddr , ( AnyPtr , ByteLen ) > ,
1305+ swept_len : usize ,
1306+ }
1307+
1308+ impl PtrRegistry {
1309+ fn new ( ) -> Self {
1310+ Self {
1311+ ranges : RangeAllocator :: new ( ) ,
1312+ entries : BTreeMap :: new ( ) ,
1313+ swept_len : 0 ,
1314+ }
1315+ }
1316+
1317+ fn put ( & mut self , real_addr : RealAddr , byte_len : ByteLen , ptr : AnyPtr ) -> SyntheticAddr {
1318+ self . evict_dead ( ) ;
1319+ let base = self . ranges . get_synthetic_addr ( real_addr, byte_len) ;
1320+ self . entries . insert ( base, ( ptr, byte_len) ) ;
1321+ base
1322+ }
1323+
1324+ fn get ( & self , addr : SyntheticAddr ) -> Option < ( SyntheticAddr , AnyPtr , ByteLen ) > {
1325+ self . entries
1326+ . range ( ..=addr)
1327+ . next_back ( )
1328+ . map ( |( base, ( any, len) ) | ( * base, any. clone ( ) , * len) )
1329+ }
1330+
1331+ fn evict_dead ( & mut self ) {
1332+ if self . entries . len ( ) < 16 . max ( 2 * self . swept_len ) {
1333+ return ;
1334+ }
1335+ self . entries . retain ( |_, ( any, _) | !any. ptr . is_dangling ( ) ) ;
1336+ let entries = & self . entries ;
1337+ self . ranges
1338+ . bases
1339+ . retain ( |_, & mut ( base, _) | entries. contains_key ( & base) ) ;
1340+ self . swept_len = self . entries . len ( ) ;
1341+ }
1342+ }
1343+
13021344thread_local ! {
1303- static PTR_RANGE_ALLOC : RefCell <RangeAllocator > = RefCell :: new( RangeAllocator :: new( ) ) ;
1304- static PTR_REGISTRY : RefCell <BTreeMap <SyntheticAddr , ( AnyPtr , ByteLen ) >> =
1305- const { RefCell :: new( BTreeMap :: new( ) ) } ;
1345+ static PTR_REGISTRY : RefCell <PtrRegistry > = RefCell :: new( PtrRegistry :: new( ) ) ;
13061346}
13071347
13081348impl < T : ByteRepr > ByteRepr for Ptr < T > {
@@ -1322,13 +1362,13 @@ impl<T: ByteRepr> ByteRepr for Ptr<T> {
13221362 self . len ( ) * T :: byte_size ( ) ,
13231363 ) ,
13241364 } ;
1325- let base = PTR_RANGE_ALLOC . with ( |a| a. borrow_mut ( ) . base_for ( self . kind . address ( ) , byte_len) ) ;
13261365 let rebased = Ptr {
13271366 offset : 0 ,
13281367 kind : self . kind . clone ( ) ,
13291368 } ;
1330- PTR_REGISTRY . with ( |r| {
1331- r. borrow_mut ( ) . insert ( base, ( rebased. to_any ( ) , byte_len) ) ;
1369+ let base = PTR_REGISTRY . with ( |r| {
1370+ r. borrow_mut ( )
1371+ . put ( self . kind . address ( ) , byte_len, rebased. to_any ( ) )
13321372 } ) ;
13331373 base. wrapping_add ( byte_off) . to_bytes ( buf) ;
13341374 }
@@ -1338,12 +1378,7 @@ impl<T: ByteRepr> ByteRepr for Ptr<T> {
13381378 if addr == 0 {
13391379 return Ptr :: null ( ) ;
13401380 }
1341- let entry = PTR_REGISTRY . with ( |r| {
1342- r. borrow ( )
1343- . range ( ..=addr)
1344- . next_back ( )
1345- . map ( |( base, ( any, len) ) | ( * base, any. clone ( ) , * len) )
1346- } ) ;
1381+ let entry = PTR_REGISTRY . with ( |r| r. borrow ( ) . get ( addr) ) ;
13471382 let Some ( ( base, any, byte_len) ) = entry else {
13481383 panic ! ( "ub: cast of invalid address 0x{addr:x} to pointer" ) ;
13491384 } ;
0 commit comments