diff --git a/crates/oxc_data_structures/src/stack/common.rs b/crates/oxc_data_structures/src/stack/common.rs index 5499b416c..0fdfb98a0 100644 --- a/crates/oxc_data_structures/src/stack/common.rs +++ b/crates/oxc_data_structures/src/stack/common.rs @@ -11,7 +11,7 @@ use assert_unchecked::assert_unchecked; use super::{NonNull, StackCapacity}; pub trait StackCommon: StackCapacity { - // Getter setter methods defined by implementer + // Getter + setter methods defined by implementer fn start(&self) -> NonNull; fn end(&self) -> NonNull; fn cursor(&self) -> NonNull; @@ -19,6 +19,9 @@ pub trait StackCommon: StackCapacity { fn set_end(&mut self, end: NonNull); fn set_cursor(&mut self, cursor: NonNull); + // Defined by implementer + fn len(&self) -> usize; + /// Make allocation of `capacity_bytes` bytes, aligned for `T`. /// /// # Panics @@ -98,12 +101,12 @@ pub trait StackCommon: StackCapacity { /// /// # SAFETY /// * Stack must be allocated. - /// * Stack must contain `len` initialized entries, starting at `self.start()`. + /// * Stack must contain `self.len()` initialized entries, starting at `self.start()`. #[inline] - unsafe fn drop_contents(&self, len: usize) { + unsafe fn drop_contents(&self) { // Drop contents. Next line copied from `std`'s `Vec`. // SAFETY: Caller guarantees stack contains `len` initialized entries, starting at `start`. - ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.start().as_ptr(), len)); + ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.start().as_ptr(), self.len())); } /// Get layout for allocation of `capacity_bytes` bytes. diff --git a/crates/oxc_data_structures/src/stack/non_empty.rs b/crates/oxc_data_structures/src/stack/non_empty.rs index c18724abe..e248cd9c4 100644 --- a/crates/oxc_data_structures/src/stack/non_empty.rs +++ b/crates/oxc_data_structures/src/stack/non_empty.rs @@ -86,6 +86,19 @@ impl StackCommon for NonEmptyStack { fn set_cursor(&mut self, cursor: NonNull) { self.cursor = cursor; } + + #[inline] + fn len(&self) -> usize { + // SAFETY: `self.start` and `self.cursor` are both derived from same pointer. + // `self.cursor` is always >= `self.start`. + // Distance between pointers is always a multiple of `size_of::()`. + let offset = unsafe { self.cursor_offset() }; + + // When stack has 1 entry, `start - cursor == 0`, so add 1 to get number of entries. + // SAFETY: Capacity cannot exceed `Self::MAX_CAPACITY`, which is `<= isize::MAX`, + // and offset can't exceed capacity, so `+ 1` cannot wrap around. + offset + 1 + } } impl NonEmptyStack { @@ -275,15 +288,7 @@ impl NonEmptyStack { /// Number of entries is always at least 1. Stack is never empty. #[inline] pub fn len(&self) -> usize { - // SAFETY: `self.start` and `self.cursor` are both derived from same pointer. - // `self.cursor` is always >= `self.start`. - // Distance between pointers is always a multiple of `size_of::()`. - let offset = unsafe { self.cursor_offset() }; - - // When stack has 1 entry, `start - cursor == 0`, so add 1 to get number of entries. - // SAFETY: Capacity cannot exceed `Self::MAX_CAPACITY`, which is `<= isize::MAX`, - // and offset can't exceed capacity, so `+ 1` cannot wrap around. - offset + 1 + >::len(self) } #[inline] @@ -303,7 +308,7 @@ impl Drop for NonEmptyStack { // Drop contents. // SAFETY: Stack is always allocated, and contains `self.len()` initialized entries, // starting at `self.start`. - unsafe { self.drop_contents(self.len()) }; + unsafe { self.drop_contents() }; // Drop the memory // SAFETY: Stack is always allocated. diff --git a/crates/oxc_data_structures/src/stack/standard.rs b/crates/oxc_data_structures/src/stack/standard.rs index b6042f47c..dddd17dc5 100644 --- a/crates/oxc_data_structures/src/stack/standard.rs +++ b/crates/oxc_data_structures/src/stack/standard.rs @@ -74,6 +74,13 @@ impl StackCommon for Stack { fn set_cursor(&mut self, cursor: NonNull) { self.cursor = cursor; } + + fn len(&self) -> usize { + // SAFETY: `self.start` and `self.cursor` are both derived from same pointer. + // `self.cursor` is always >= `self.start`. + // Distance between pointers is always a multiple of `size_of::()`. + unsafe { self.cursor_offset() } + } } impl Stack { @@ -303,10 +310,7 @@ impl Stack { /// Get number of entries on stack. #[inline] pub fn len(&self) -> usize { - // SAFETY: `self.start` and `self.cursor` are both derived from same pointer. - // `self.cursor` is always >= `self.start`. - // Distance between pointers is always a multiple of `size_of::()`. - unsafe { self.cursor_offset() } + >::len(self) } /// Get if stack is empty. @@ -332,7 +336,7 @@ impl Drop for Stack { if !self.is_empty() { // SAFETY: Checked above that stack is allocated. // Stack contains `self.len()` initialized entries, starting at `self.start` - unsafe { self.drop_contents(self.len()) }; + unsafe { self.drop_contents() }; } // Drop the memory