Skip to content

Commit

Permalink
perf(allocator): inline Box methods (#8572)
Browse files Browse the repository at this point in the history
Add `#[inline]` or `#[inline(always)]` to many of `Box`'s methods. In particular, `Box::new_in` should absolutely always be inlined, for the same reasons that `Allocator::alloc` should be.
  • Loading branch information
overlookmotel committed Jan 18, 2025
1 parent fae4cd2 commit 76ea52b
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions crates/oxc_allocator/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl<T> Box<'_, T> {
///
/// assert_eq!(i, 5);
/// ```
#[inline]
pub fn unbox(self) -> T {
// SAFETY:
// This pointer read is safe because the reference `self.0` is
Expand All @@ -70,6 +71,11 @@ impl<T> Box<'_, T> {
/// let arena = Allocator::default();
/// let in_arena: Box<i32> = Box::new_in(5, &arena);
/// ```
//
// `#[inline(always)]` because this is a hot path and `Allocator::alloc` is a very small function.
// We always want it to be inlined.
#[expect(clippy::inline_always)]
#[inline(always)]
pub fn new_in(value: T, allocator: &Allocator) -> Self {
const {
assert!(!needs_drop::<T>(), "Cannot create a Box<T> where T is a Drop type");
Expand Down Expand Up @@ -106,7 +112,10 @@ impl<T: ?Sized> Box<'_, T> {
/// with no other aliases. You must not, for example, create 2 `Box`es from the same pointer.
///
/// `ptr` must have been created from a `*mut T` or `&mut T` (not a `*const T` / `&T`).
#[inline]
//
// `#[inline(always)]` because this is a no-op
#[expect(clippy::inline_always)]
#[inline(always)]
pub(crate) const unsafe fn from_non_null(ptr: NonNull<T>) -> Self {
const {
assert!(!needs_drop::<T>(), "Cannot create a Box<T> where T is a Drop type");
Expand All @@ -116,8 +125,10 @@ impl<T: ?Sized> Box<'_, T> {
}

/// Consume a [`Box`] and return a [`NonNull`] pointer to its contents.
#[inline]
#[expect(clippy::needless_pass_by_value)]
//
// `#[inline(always)]` because this is a no-op
#[expect(clippy::inline_always, clippy::needless_pass_by_value)]
#[inline(always)]
pub fn into_non_null(boxed: Self) -> NonNull<T> {
boxed.0
}
Expand All @@ -126,32 +137,37 @@ impl<T: ?Sized> Box<'_, T> {
impl<T: ?Sized> ops::Deref for Box<'_, T> {
type Target = T;

#[inline]
fn deref(&self) -> &T {
// SAFETY: self.0 is always a unique reference allocated from a Bump in Box::new_in
unsafe { self.0.as_ref() }
}
}

impl<T: ?Sized> ops::DerefMut for Box<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
// SAFETY: self.0 is always a unique reference allocated from a Bump in Box::new_in
unsafe { self.0.as_mut() }
}
}

impl<T: ?Sized> AsRef<T> for Box<'_, T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}

impl<T: ?Sized> AsMut<T> for Box<'_, T> {
#[inline]
fn as_mut(&mut self) -> &mut T {
self
}
}

impl<T: ?Sized + Debug> Debug for Box<'_, T> {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.deref().fmt(f)
}
Expand Down Expand Up @@ -181,6 +197,7 @@ where
}

impl<T: Hash> Hash for Box<'_, T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.deref().hash(state);
}
Expand Down

0 comments on commit 76ea52b

Please sign in to comment.