Skip to content

Commit 304880b

Browse files
committed
Fast metatable check for Lua::push_userdata_ref
1 parent 33c276d commit 304880b

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

src/lua.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ pub(crate) struct ExtraData {
8484

8585
registered_userdata: FxHashMap<TypeId, c_int>,
8686
registered_userdata_mt: FxHashMap<*const c_void, Option<TypeId>>,
87+
last_checked_userdata_mt: (*const c_void, Option<TypeId>),
8788

8889
// When Lua instance dropped, setting `None` would prevent collecting `RegistryKey`s
8990
registry_unref_list: Arc<Mutex<Option<Vec<c_int>>>>,
@@ -553,6 +554,7 @@ impl Lua {
553554
inner: None,
554555
registered_userdata: FxHashMap::default(),
555556
registered_userdata_mt: FxHashMap::default(),
557+
last_checked_userdata_mt: (ptr::null(), None),
556558
registry_unref_list: Arc::new(Mutex::new(Some(Vec::new()))),
557559
app_data: RefCell::new(FxHashMap::default()),
558560
safe: false,
@@ -2615,6 +2617,9 @@ impl Lua {
26152617
#[inline]
26162618
pub(crate) unsafe fn deregister_raw_userdata_metatable(&self, ptr: *const c_void) {
26172619
(*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+
}
26182623
}
26192624

26202625
// Pushes a LuaRef value onto the stack, checking that it's a registered
@@ -2630,11 +2635,20 @@ impl Lua {
26302635
let mt_ptr = ffi::lua_topointer(state, -1);
26312636
ffi::lua_pop(state, 1);
26322637

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+
26332644
match (*self.extra.get()).registered_userdata_mt.get(&mt_ptr) {
26342645
Some(&type_id) if type_id == Some(TypeId::of::<DestructedUserdata>()) => {
26352646
Err(Error::UserDataDestructed)
26362647
}
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+
}
26382652
None => Err(Error::UserDataTypeMismatch),
26392653
}
26402654
}

0 commit comments

Comments
 (0)