From 92a5268e1df9fe91188f33367df3d53e7a67ea9d Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 1 Sep 2023 19:11:54 +0200 Subject: [PATCH] Optimize ivar access in declare_class! --- .../src/__macro_helpers/declare_class.rs | 23 +++++++++++++++++++ crates/objc2/src/macros/__field_helpers.rs | 18 +++++++++++++++ crates/objc2/src/macros/declare_class.rs | 6 +++++ 3 files changed, 47 insertions(+) diff --git a/crates/objc2/src/__macro_helpers/declare_class.rs b/crates/objc2/src/__macro_helpers/declare_class.rs index 40b7ceaf0..6ce7fe358 100644 --- a/crates/objc2/src/__macro_helpers/declare_class.rs +++ b/crates/objc2/src/__macro_helpers/declare_class.rs @@ -107,6 +107,29 @@ impl MaybeOptionId for Option> { } } +pub struct IvarStaticHelper { + offset: Cell, +} + +impl IvarStaticHelper { + #[inline] + pub const fn new() -> Self { + Self { + offset: Cell::new(0), + } + } + + pub fn set(&self, cls: &Class) { + let offset = ivar_offset(cls, T::NAME, &T::Type::__ENCODING); + self.offset.set(offset); + } + + #[inline] + pub fn get(&self) -> isize { + self.offset.get() + } +} + /// Helper for ensuring that `ClassType::Mutability` is implemented correctly /// for subclasses. pub trait ValidSubclassMutability {} diff --git a/crates/objc2/src/macros/__field_helpers.rs b/crates/objc2/src/macros/__field_helpers.rs index 3a18a3b82..16ccd25c5 100644 --- a/crates/objc2/src/macros/__field_helpers.rs +++ b/crates/objc2/src/macros/__field_helpers.rs @@ -202,6 +202,16 @@ macro_rules! __parse_fields { __priv: (), } + impl $field_name { + #[inline] + unsafe fn __offset_ptr() -> &'static $crate::__macro_helpers::IvarStaticHelper { + static mut OFFSET: $crate::__macro_helpers::IvarStaticHelper + = $crate::__macro_helpers::IvarStaticHelper::new(); + #[allow(unused_unsafe)] + unsafe { &OFFSET } + } + } + // SAFETY: // - The ivars are in a type used as an Objective-C object. // - The ivar is added to the class in `__objc2_declare_ivars`. @@ -209,6 +219,14 @@ macro_rules! __parse_fields { unsafe impl $crate::declare::IvarType for $field_name { type Type = IvarDrop<$ty>; const NAME: &'static $crate::__macro_helpers::str = $ivar_name; + + #[inline] + unsafe fn __offset( + _ptr: $crate::__macro_helpers::NonNull<$crate::runtime::AnyObject>, + ) -> $crate::__macro_helpers::isize { + #[allow(unused_unsafe)] + unsafe { Self::__offset_ptr().get() } + } } ) ($($ivar_type_name)* $field_name) ( diff --git a/crates/objc2/src/macros/declare_class.rs b/crates/objc2/src/macros/declare_class.rs index db70e08b7..5055efaa1 100644 --- a/crates/objc2/src/macros/declare_class.rs +++ b/crates/objc2/src/macros/declare_class.rs @@ -607,6 +607,12 @@ macro_rules! __inner_declare_class { } let _cls = __objc2_builder.register(); + + $( + unsafe { + $ivar::__offset_ptr().set::<$ivar>(_cls); + } + )* }); // We just registered the class, so it should be available