Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(data_structures): add len method to StackCommon trait #6215

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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