From 6396261dbbfe7d64ddfa8b503680165ac0289f80 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Sun, 2 Oct 2022 16:46:20 -0500 Subject: [PATCH 1/2] Don't heap-allocate block descriptors --- src/lib.rs | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f05eee6..ab687bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,7 +52,6 @@ use std::marker::PhantomData; use std::mem; use std::ops::{Deref, DerefMut}; use std::os::raw::{c_int, c_ulong, c_void}; -use std::ptr; enum Class { } @@ -236,7 +235,7 @@ concrete_block_impl!(concrete_block_invoke_args12, a: A, b: B, c: C, d: D, e: E, #[repr(C)] pub struct ConcreteBlock { base: BlockBase, - descriptor: Box>>, + descriptor: &'static BlockDescriptor, closure: F, } @@ -264,7 +263,7 @@ impl ConcreteBlock { _reserved: 0, invoke: mem::transmute(invoke), }, - descriptor: Box::new(BlockDescriptor::new()), + descriptor: &BlockDescriptorImpl::>::DESCRIPTOR, closure: closure, } } @@ -308,32 +307,32 @@ impl DerefMut for ConcreteBlock { } } -unsafe extern fn block_context_dispose(block: &mut B) { +unsafe extern fn block_context_dispose(block: *mut c_void) { // Read the block onto the stack and let it drop - ptr::read(block); + block.cast::().read(); } -unsafe extern fn block_context_copy(_dst: &mut B, _src: &B) { +unsafe extern fn block_context_copy(_dst: *mut c_void, _src: *const c_void) { // The runtime memmoves the src block into the dst block, nothing to do } #[repr(C)] -struct BlockDescriptor { +struct BlockDescriptor { _reserved: c_ulong, block_size: c_ulong, - copy_helper: unsafe extern fn(&mut B, &B), - dispose_helper: unsafe extern fn(&mut B), + copy_helper: unsafe extern fn(*mut c_void, *const c_void), + dispose_helper: unsafe extern fn(*mut c_void), } -impl BlockDescriptor { - fn new() -> BlockDescriptor { - BlockDescriptor { - _reserved: 0, - block_size: mem::size_of::() as c_ulong, - copy_helper: block_context_copy::, - dispose_helper: block_context_dispose::, - } - } +struct BlockDescriptorImpl(PhantomData); + +impl BlockDescriptorImpl { + const DESCRIPTOR: BlockDescriptor = BlockDescriptor { + _reserved: 0, + block_size: mem::size_of::() as c_ulong, + copy_helper: block_context_copy, + dispose_helper: block_context_dispose::, + }; } #[cfg(test)] From 3d715d246cbfb974303f48e978d35f82e85b8694 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Sun, 2 Oct 2022 17:52:12 -0500 Subject: [PATCH 2/2] Only add BLOCK_HAS_COPY_DISPOSE when needed --- src/lib.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ab687bd..eca877b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -255,15 +255,16 @@ impl ConcreteBlock { /// correct arguments. unsafe fn with_invoke(invoke: unsafe extern fn(*mut Self, ...) -> R, closure: F) -> Self { + let descriptor = &BlockDescriptorImpl::>::DESCRIPTOR; + const BLOCK_HAS_COPY_DISPOSE: c_int = 1 << 25; ConcreteBlock { base: BlockBase { isa: &_NSConcreteStackBlock, - // 1 << 25 = BLOCK_HAS_COPY_DISPOSE - flags: 1 << 25, + flags: if descriptor.dispose_helper.is_some() { BLOCK_HAS_COPY_DISPOSE } else { 0 }, _reserved: 0, invoke: mem::transmute(invoke), }, - descriptor: &BlockDescriptorImpl::>::DESCRIPTOR, + descriptor: descriptor, closure: closure, } } @@ -320,8 +321,8 @@ unsafe extern fn block_context_copy(_dst: *mut c_void, _src: *const c_void) { struct BlockDescriptor { _reserved: c_ulong, block_size: c_ulong, - copy_helper: unsafe extern fn(*mut c_void, *const c_void), - dispose_helper: unsafe extern fn(*mut c_void), + copy_helper: Option, + dispose_helper: Option, } struct BlockDescriptorImpl(PhantomData); @@ -330,8 +331,8 @@ impl BlockDescriptorImpl { const DESCRIPTOR: BlockDescriptor = BlockDescriptor { _reserved: 0, block_size: mem::size_of::() as c_ulong, - copy_helper: block_context_copy, - dispose_helper: block_context_dispose::, + copy_helper: if std::mem::needs_drop::() { Some(block_context_copy) } else { None }, + dispose_helper: if std::mem::needs_drop::() { Some(block_context_dispose::) } else { None }, }; }