From 5dca743b0c050fa0c0119969748fa2b85fdce6e5 Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Mon, 10 Jul 2023 00:01:26 +0100 Subject: [PATCH] Improve performance `AnyUserData::{is_serializable/inspect/serialize}` --- src/userdata.rs | 43 +++++++++++-------------------------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/src/userdata.rs b/src/userdata.rs index 1bed822..0855c9d 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -754,19 +754,6 @@ impl Deref for UserDataVariant { } } -#[cfg(feature = "serialize")] -struct UserDataSerializeError; - -#[cfg(feature = "serialize")] -impl Serialize for UserDataSerializeError { - fn serialize(&self, _serializer: S) -> StdResult - where - S: Serializer, - { - Err(ser::Error::custom("cannot serialize ")) - } -} - /// Handle to an internal Lua userdata for any type that implements [`UserData`]. /// /// Similar to `std::any::Any`, this provides an interface for dynamic type checking via the [`is`] @@ -1155,15 +1142,11 @@ impl<'lua> AnyUserData<'lua> { #[cfg(feature = "serialize")] pub(crate) fn is_serializable(&self) -> bool { let lua = self.0.lua; - let state = lua.state(); let is_serializable = || unsafe { - let _sg = StackGuard::new(state); - check_stack(state, 2)?; - // Userdata can be unregistered or destructed - lua.push_userdata_ref(&self.0)?; + let _ = lua.get_userdata_type_id(&self.0)?; - let ud = &*get_userdata::>(state, -1); + let ud = &*get_userdata::>(lua.ref_thread(), self.0.index); match &*ud.0.try_borrow().map_err(|_| Error::UserDataBorrowError)? { UserDataVariant::Serializable(_) => Result::Ok(true), _ => Result::Ok(false), @@ -1178,15 +1161,12 @@ impl<'lua> AnyUserData<'lua> { F: FnOnce(&'a UserDataCell) -> Result, { let lua = self.0.lua; - let state = lua.state(); unsafe { - let _sg = StackGuard::new(state); - check_stack(state, 2)?; - - let type_id = lua.push_userdata_ref(&self.0)?; + let type_id = lua.get_userdata_type_id(&self.0)?; match type_id { Some(type_id) if type_id == TypeId::of::() => { - func(&*get_userdata::>(state, -1)) + let ref_thread = lua.ref_thread(); + func(&*get_userdata::>(ref_thread, self.0.index)) } _ => Err(Error::UserDataTypeMismatch), } @@ -1329,19 +1309,17 @@ impl<'lua> Serialize for AnyUserData<'lua> { S: Serializer, { let lua = self.0.lua; - let state = lua.state(); let data = unsafe { - let _sg = StackGuard::new(state); - check_stack(state, 3).map_err(ser::Error::custom)?; - - lua.push_userdata_ref(&self.0).map_err(ser::Error::custom)?; - let ud = &*get_userdata::>(state, -1); + let _ = lua + .get_userdata_type_id(&self.0) + .map_err(ser::Error::custom)?; + let ud = &*get_userdata::>(lua.ref_thread(), self.0.index); ud.0.try_borrow() .map_err(|_| ser::Error::custom(Error::UserDataBorrowError))? }; match &*data { UserDataVariant::Serializable(ser) => ser.serialize(serializer), - _ => UserDataSerializeError.serialize(serializer), + _ => Err(ser::Error::custom("cannot serialize ")), } } } @@ -1396,6 +1374,7 @@ impl<'lua, T: 'static> UserDataRefMut<'lua, T> { } } +#[inline] fn try_value_to_userdata(value: Value) -> Result { match value { Value::UserData(ud) => Ok(ud),