Skip to content

Commit

Permalink
Optimize ivar access in declare_class!
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Nov 24, 2022
1 parent 8b54663 commit 1d089e2
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 34 deletions.
33 changes: 28 additions & 5 deletions crates/objc2/src/__macro_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#[cfg(all(debug_assertions, feature = "verify"))]
use alloc::vec::Vec;
use core::cell::Cell;
use core::ptr;
#[cfg(all(debug_assertions, feature = "verify"))]
use std::collections::HashSet;

use crate::declare::ClassBuilder;
use crate::declare::MethodImplementation;
use crate::declare::{ClassBuilder, InnerIvarType, IvarType, MethodImplementation};
use crate::encode::Encode;
use crate::message::__TupleExtender;
use crate::rc::{Allocated, Id, Ownership, Shared};
#[cfg(all(debug_assertions, feature = "verify"))]
use crate::runtime::MethodDescription;
use crate::runtime::{Class, Object, Protocol, Sel};
use crate::runtime::{ivar_offset, Class, Object, Protocol, Sel};
use crate::{Message, MessageArguments, MessageReceiver};
use crate::{__sel_data, __sel_inner};

Expand All @@ -24,8 +24,8 @@ pub use core::convert::{AsMut, AsRef};
pub use core::mem::size_of;
pub use core::ops::{Deref, DerefMut};
pub use core::option::Option::{self, None, Some};
pub use core::primitive::{bool, str, u8};
pub use core::ptr::drop_in_place;
pub use core::primitive::{bool, isize, str, u8};
pub use core::ptr::{drop_in_place, NonNull};
pub use core::{compile_error, concat, panic, stringify};
// TODO: Use `core::cell::LazyCell`
pub use std::sync::Once;
Expand Down Expand Up @@ -632,6 +632,29 @@ impl ClassProtocolMethodsBuilder<'_, '_> {
}
}

pub struct IvarStaticHelper {
offset: Cell<isize>,
}

impl IvarStaticHelper {
#[inline]
pub const fn new() -> Self {
Self {
offset: Cell::new(0),
}
}

pub fn set<T: IvarType>(&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()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
24 changes: 24 additions & 0 deletions crates/objc2/src/macros/declare_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,27 @@ macro_rules! declare_class {
__priv: (),
}

impl $ivar {
#[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 }
}
}

unsafe impl $crate::declare::IvarType for $ivar {
type Type = $ivar_ty;
const NAME: &'static str = stringify!($ivar);

#[inline]
unsafe fn __offset(
_ptr: $crate::__macro_helpers::NonNull<$crate::runtime::Object>,
) -> $crate::__macro_helpers::isize {
#[allow(unused_unsafe)]
unsafe { Self::__offset_ptr().get() }
}
}
)*

Expand Down Expand Up @@ -424,6 +442,12 @@ macro_rules! declare_class {
);

let _cls = builder.register();

$(
unsafe {
$ivar::__offset_ptr().set::<$ivar>(_cls);
}
)*
});

// We just registered the class, so it should be available
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,19 @@ LBB9_60:
LBB9_64:
mov rdi, qword ptr [rbp - 168]
call SYM(objc2::declare::ClassBuilder::register::GENERATED_ID, 0)
mov rbx, rax
lea rsi, [rip + l_anon.[ID].16]
lea rcx, [rip + l_anon.[ID].17]
mov edx, 5
mov rdi, rax
call SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0)
mov qword ptr [rip + SYM(<test_declare_class[CRATE_ID]::ivar1>::__offset_ptr::OFFSET, 0)], rax
lea rsi, [rip + l_anon.[ID].18]
lea rcx, [rip + l_anon.[ID].19]
mov edx, 5
mov rdi, rbx
call SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0)
mov qword ptr [rip + SYM(<test_declare_class[CRATE_ID]::ivar2>::__offset_ptr::OFFSET, 0)], rax
add rsp, 184
pop rbx
pop r12
Expand Down Expand Up @@ -1196,29 +1209,12 @@ LBB22_2:
_access:
push rbp
mov rbp, rsp
push r14
push rbx
call _get_obj
mov rbx, rax
mov rdi, rax
call SYM(objc2::runtime::Object::class::GENERATED_ID, 0)
lea rsi, [rip + l_anon.[ID].16]
lea rcx, [rip + l_anon.[ID].17]
mov edx, 5
mov rdi, rax
call SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0)
movzx r14d, byte ptr [rbx + rax]
mov rdi, rbx
call SYM(objc2::runtime::Object::class::GENERATED_ID, 0)
lea rsi, [rip + l_anon.[ID].18]
lea rcx, [rip + l_anon.[ID].19]
mov edx, 5
mov rdi, rax
call SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0)
mov rdx, qword ptr [rbx + rax]
mov eax, r14d
pop rbx
pop r14
mov rcx, qword ptr [rip + SYM(<test_declare_class[CRATE_ID]::ivar1>::__offset_ptr::OFFSET, 0)]
movzx ecx, byte ptr [rax + rcx]
mov rdx, qword ptr [rip + SYM(<test_declare_class[CRATE_ID]::ivar2>::__offset_ptr::OFFSET, 0)]
mov rdx, qword ptr [rax + rdx]
mov eax, ecx
pop rbp
ret

Expand Down Expand Up @@ -1266,13 +1262,8 @@ SYM(<test_declare_class[CRATE_ID]::Custom>::__objc2_dealloc, 0):
push rbx
sub rsp, 72
mov r14, rdi
call SYM(objc2::runtime::Object::class::GENERATED_ID, 0)
lea rsi, [rip + l_anon.[ID].18]
lea rcx, [rip + l_anon.[ID].19]
mov edx, 5
mov rdi, rax
call SYM(objc2::runtime::ivar_offset::GENERATED_ID, 0)
mov rdi, qword ptr [r14 + rax]
mov rax, qword ptr [rip + SYM(<test_declare_class[CRATE_ID]::ivar2>::__offset_ptr::OFFSET, 0)]
mov rdi, qword ptr [rdi + rax]
test rdi, rdi
je LBB25_2
call _objc_release
Expand Down Expand Up @@ -1603,6 +1594,10 @@ L_anon.[ID].49:
l_anon.[ID].50:
.ascii "crates/$DIR/lib.rs"

.globl SYM(<test_declare_class[CRATE_ID]::ivar1>::__offset_ptr::OFFSET, 0)
.zerofill __DATA,__common,SYM(<test_declare_class[CRATE_ID]::ivar1>::__offset_ptr::OFFSET, 0),8,3
.globl SYM(<test_declare_class[CRATE_ID]::ivar2>::__offset_ptr::OFFSET, 0)
.zerofill __DATA,__common,SYM(<test_declare_class[CRATE_ID]::ivar2>::__offset_ptr::OFFSET, 0),8,3
.section __DATA,__const
.p2align 3
l_anon.[ID].51:
Expand Down

0 comments on commit 1d089e2

Please sign in to comment.