diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs index a362c720a2161c3325227891572f43bc3425d114..c99f09d29f46e33117698cfc8ffbacaa239c9e9e 100644 --- a/crates/gpui2/src/arena.rs +++ b/crates/gpui2/src/arena.rs @@ -12,6 +12,7 @@ struct ArenaElement { } impl Drop for ArenaElement { + #[inline(always)] fn drop(&mut self) { unsafe { (self.drop)(self.value); @@ -48,15 +49,23 @@ impl Arena { } #[inline(always)] - pub fn alloc(&mut self, value: T) -> ArenaRef { + pub fn alloc(&mut self, f: impl FnOnce() -> T) -> ArenaRef { + #[inline(always)] + unsafe fn inner_writer(ptr: *mut T, f: F) + where + F: FnOnce() -> T, + { + ptr::write(ptr, f()); + } + unsafe fn drop(ptr: NonNull) { std::ptr::drop_in_place(ptr.cast::().as_ptr()); } unsafe { - let layout = alloc::Layout::for_value(&value).pad_to_align(); + let layout = alloc::Layout::new::().pad_to_align(); let ptr = NonNull::new_unchecked(self.start.as_ptr().add(self.offset).cast::()); - ptr::write(ptr.as_ptr(), value); + inner_writer(ptr.as_ptr(), f); self.elements.push(ArenaElement { value: ptr.cast(), @@ -92,6 +101,7 @@ impl Clone for ArenaRef { } impl ArenaRef { + #[inline(always)] pub fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef { ArenaRef { ptr: unsafe { NonNull::new_unchecked(f(&mut *self)) }, @@ -110,6 +120,7 @@ impl ArenaRef { impl Deref for ArenaRef { type Target = T; + #[inline(always)] fn deref(&self) -> &Self::Target { self.validate(); unsafe { self.ptr.as_ref() } @@ -117,6 +128,7 @@ impl Deref for ArenaRef { } impl DerefMut for ArenaRef { + #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { self.validate(); unsafe { self.ptr.as_mut() } @@ -132,20 +144,20 @@ mod tests { #[test] fn test_arena() { let mut arena = Arena::new(1024); - let a = arena.alloc(1u64); - let b = arena.alloc(2u32); - let c = arena.alloc(3u16); - let d = arena.alloc(4u8); + let a = arena.alloc(|| 1u64); + let b = arena.alloc(|| 2u32); + let c = arena.alloc(|| 3u16); + let d = arena.alloc(|| 4u8); assert_eq!(*a, 1); assert_eq!(*b, 2); assert_eq!(*c, 3); assert_eq!(*d, 4); arena.clear(); - let a = arena.alloc(5u64); - let b = arena.alloc(6u32); - let c = arena.alloc(7u16); - let d = arena.alloc(8u8); + let a = arena.alloc(|| 5u64); + let b = arena.alloc(|| 6u32); + let c = arena.alloc(|| 7u16); + let d = arena.alloc(|| 8u8); assert_eq!(*a, 5); assert_eq!(*b, 6); assert_eq!(*c, 7); @@ -159,7 +171,7 @@ mod tests { self.0.set(true); } } - arena.alloc(DropGuard(dropped.clone())); + arena.alloc(|| DropGuard(dropped.clone())); arena.clear(); assert!(dropped.get()); } diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index d54d1c245da61fb9c2d03044a305a67587baea46..6f739d8e33ac93972401508039a8d9e9db3e5c52 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -1,6 +1,6 @@ use crate::{ - arena::ArenaRef, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, - Size, ViewContext, WindowContext, FRAME_ARENA, + frame_alloc, ArenaRef, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, + Point, Size, ViewContext, WindowContext, }; use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; @@ -413,9 +413,8 @@ impl AnyElement { E: 'static + Element, E::State: Any, { - let element = - FRAME_ARENA.with_borrow_mut(|arena| arena.alloc(Some(DrawableElement::new(element)))); - let element = element.map(|element| element as &mut dyn ElementObject); + let element = frame_alloc(|| Some(DrawableElement::new(element))) + .map(|element| element as &mut dyn ElementObject); AnyElement(element) } diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 322ca206081af8c58f17fa2b3cdcaf90ffb7ba4b..6af274ef5d8998cbca7e5b1880188d44cff7dbbc 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -39,6 +39,7 @@ mod private { pub use action::*; pub use anyhow::Result; pub use app::*; +pub(crate) use arena::*; pub use assets::*; pub use color::*; pub use ctor::ctor; diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 56c5466b6380e73891625a53d67ec01f154dc47a..337f61272f12e351aeb98e832692f117f2ea2310 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -102,6 +102,11 @@ thread_local! { pub static FRAME_ARENA: RefCell = RefCell::new(Arena::new(16 * 1024 * 1024)); } +#[inline(always)] +pub(crate) fn frame_alloc(f: impl FnOnce() -> T) -> ArenaRef { + FRAME_ARENA.with_borrow_mut(|arena| arena.alloc(f)) +} + impl FocusId { /// Obtains whether the element associated with this handle is currently focused. pub fn is_focused(&self, cx: &WindowContext) -> bool { @@ -829,15 +834,12 @@ impl<'a> WindowContext<'a> { mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { let order = self.window.next_frame.z_index_stack.clone(); - let handler = FRAME_ARENA - .with_borrow_mut(|arena| { - arena.alloc( - move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { - handler(event.downcast_ref().unwrap(), phase, cx) - }, - ) - }) - .map(|handler| handler as _); + let handler = frame_alloc(|| { + move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { + handler(event.downcast_ref().unwrap(), phase, cx) + } + }) + .map(|handler| handler as _); self.window .next_frame .mouse_listeners @@ -856,15 +858,14 @@ impl<'a> WindowContext<'a> { &mut self, listener: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = FRAME_ARENA - .with_borrow_mut(|arena| { - arena.alloc(move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { - if let Some(event) = event.downcast_ref::() { - listener(event, phase, cx) - } - }) - }) - .map(|handler| handler as _); + let listener = frame_alloc(|| { + move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { + if let Some(event) = event.downcast_ref::() { + listener(event, phase, cx) + } + } + }) + .map(|handler| handler as _); self.window.next_frame.dispatch_tree.on_key_event(listener); } @@ -879,9 +880,7 @@ impl<'a> WindowContext<'a> { action_type: TypeId, listener: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = FRAME_ARENA - .with_borrow_mut(|arena| arena.alloc(listener)) - .map(|handler| handler as _); + let listener = frame_alloc(|| listener).map(|handler| handler as _); self.window .next_frame .dispatch_tree @@ -1286,15 +1285,12 @@ impl<'a> WindowContext<'a> { cx.with_key_dispatch(Some(KeyContext::default()), None, |_, cx| { for (action_type, action_listeners) in &cx.app.global_action_listeners { for action_listener in action_listeners.iter().cloned() { - let listener = FRAME_ARENA - .with_borrow_mut(|arena| { - arena.alloc( - move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { - action_listener(action, phase, cx) - }, - ) - }) - .map(|listener| listener as _); + let listener = frame_alloc(|| { + move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { + action_listener(action, phase, cx) + } + }) + .map(|listener| listener as _); cx.window .next_frame .dispatch_tree