Skip to content

Commit

Permalink
refactor(data_structures): add len method to StackCommon trait (#…
Browse files Browse the repository at this point in the history
…6215)

`len` method is in common between all stack types. Move it into `StackCommon` trait.
  • Loading branch information
overlookmotel committed Oct 1, 2024
1 parent f7d1136 commit dbfa0bc
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 19 deletions.
11 changes: 7 additions & 4 deletions crates/oxc_data_structures/src/stack/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ use assert_unchecked::assert_unchecked;
use super::{NonNull, StackCapacity};

pub trait StackCommon<T>: StackCapacity<T> {
// Getter setter methods defined by implementer
// Getter + setter methods defined by implementer
fn start(&self) -> NonNull<T>;
fn end(&self) -> NonNull<T>;
fn cursor(&self) -> NonNull<T>;
fn set_start(&mut self, start: NonNull<T>);
fn set_end(&mut self, end: NonNull<T>);
fn set_cursor(&mut self, cursor: NonNull<T>);

// Defined by implementer
fn len(&self) -> usize;

/// Make allocation of `capacity_bytes` bytes, aligned for `T`.
///
/// # Panics
Expand Down Expand Up @@ -98,12 +101,12 @@ pub trait StackCommon<T>: StackCapacity<T> {
///
/// # 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.
Expand Down
25 changes: 15 additions & 10 deletions crates/oxc_data_structures/src/stack/non_empty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ impl<T> StackCommon<T> for NonEmptyStack<T> {
fn set_cursor(&mut self, cursor: NonNull<T>) {
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::<T>()`.
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<T> NonEmptyStack<T> {
Expand Down Expand Up @@ -275,15 +288,7 @@ impl<T> NonEmptyStack<T> {
/// 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::<T>()`.
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
<Self as StackCommon<T>>::len(self)
}

#[inline]
Expand All @@ -303,7 +308,7 @@ impl<T> Drop for NonEmptyStack<T> {
// 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.
Expand Down
14 changes: 9 additions & 5 deletions crates/oxc_data_structures/src/stack/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ impl<T> StackCommon<T> for Stack<T> {
fn set_cursor(&mut self, cursor: NonNull<T>) {
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::<T>()`.
unsafe { self.cursor_offset() }
}
}

impl<T> Stack<T> {
Expand Down Expand Up @@ -303,10 +310,7 @@ impl<T> Stack<T> {
/// 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::<T>()`.
unsafe { self.cursor_offset() }
<Self as StackCommon<T>>::len(self)
}

/// Get if stack is empty.
Expand All @@ -332,7 +336,7 @@ impl<T> Drop for Stack<T> {
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
Expand Down

0 comments on commit dbfa0bc

Please sign in to comment.