@@ -84,6 +84,7 @@ pub(crate) struct ExtraData {
84
84
85
85
registered_userdata : FxHashMap < TypeId , c_int > ,
86
86
registered_userdata_mt : FxHashMap < * const c_void , Option < TypeId > > ,
87
+ last_checked_userdata_mt : ( * const c_void , Option < TypeId > ) ,
87
88
88
89
// When Lua instance dropped, setting `None` would prevent collecting `RegistryKey`s
89
90
registry_unref_list : Arc < Mutex < Option < Vec < c_int > > > > ,
@@ -553,6 +554,7 @@ impl Lua {
553
554
inner : None ,
554
555
registered_userdata : FxHashMap :: default ( ) ,
555
556
registered_userdata_mt : FxHashMap :: default ( ) ,
557
+ last_checked_userdata_mt : ( ptr:: null ( ) , None ) ,
556
558
registry_unref_list : Arc :: new ( Mutex :: new ( Some ( Vec :: new ( ) ) ) ) ,
557
559
app_data : RefCell :: new ( FxHashMap :: default ( ) ) ,
558
560
safe : false ,
@@ -2615,6 +2617,9 @@ impl Lua {
2615
2617
#[ inline]
2616
2618
pub ( crate ) unsafe fn deregister_raw_userdata_metatable ( & self , ptr : * const c_void ) {
2617
2619
( * self . extra . get ( ) ) . registered_userdata_mt . remove ( & ptr) ;
2620
+ if ( * self . extra . get ( ) ) . last_checked_userdata_mt . 0 == ptr {
2621
+ ( * self . extra . get ( ) ) . last_checked_userdata_mt = ( ptr:: null ( ) , None ) ;
2622
+ }
2618
2623
}
2619
2624
2620
2625
// Pushes a LuaRef value onto the stack, checking that it's a registered
@@ -2630,11 +2635,20 @@ impl Lua {
2630
2635
let mt_ptr = ffi:: lua_topointer ( state, -1 ) ;
2631
2636
ffi:: lua_pop ( state, 1 ) ;
2632
2637
2638
+ // Fast path to skip looking up the metatable in the map
2639
+ let ( last_mt, last_type_id) = ( * self . extra . get ( ) ) . last_checked_userdata_mt ;
2640
+ if last_mt == mt_ptr {
2641
+ return Ok ( last_type_id) ;
2642
+ }
2643
+
2633
2644
match ( * self . extra . get ( ) ) . registered_userdata_mt . get ( & mt_ptr) {
2634
2645
Some ( & type_id) if type_id == Some ( TypeId :: of :: < DestructedUserdata > ( ) ) => {
2635
2646
Err ( Error :: UserDataDestructed )
2636
2647
}
2637
- Some ( & type_id) => Ok ( type_id) ,
2648
+ Some ( & type_id) => {
2649
+ ( * self . extra . get ( ) ) . last_checked_userdata_mt = ( mt_ptr, type_id) ;
2650
+ Ok ( type_id)
2651
+ }
2638
2652
None => Err ( Error :: UserDataTypeMismatch ) ,
2639
2653
}
2640
2654
}
0 commit comments