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

Optimize BinaryHeap bounds checking #36072

Merged
merged 1 commit into from
Sep 3, 2016
Merged
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
43 changes: 23 additions & 20 deletions src/libcollections/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -884,58 +884,61 @@ struct Hole<'a, T: 'a> {

impl<'a, T> Hole<'a, T> {
/// Create a new Hole at index `pos`.
fn new(data: &'a mut [T], pos: usize) -> Self {
unsafe {
let elt = ptr::read(&data[pos]);
Hole {
data: data,
elt: Some(elt),
pos: pos,
}
///
/// Unsafe because pos must be within the data slice.
#[inline]
unsafe fn new(data: &'a mut [T], pos: usize) -> Self {
debug_assert!(pos < data.len());
let elt = ptr::read(&data[pos]);
Hole {
data: data,
elt: Some(elt),
pos: pos,
}
}

#[inline(always)]
#[inline]
fn pos(&self) -> usize {
self.pos
}

/// Return a reference to the element removed
#[inline(always)]
#[inline]
fn element(&self) -> &T {
self.elt.as_ref().unwrap()
}

/// Return a reference to the element at `index`.
///
/// Panics if the index is out of bounds.
///
/// Unsafe because index must not equal pos.
#[inline(always)]
/// Unsafe because index must be within the data slice and not equal to pos.
#[inline]
unsafe fn get(&self, index: usize) -> &T {
debug_assert!(index != self.pos);
&self.data[index]
debug_assert!(index < self.data.len());
self.data.get_unchecked(index)
}

/// Move hole to new location
///
/// Unsafe because index must not equal pos.
#[inline(always)]
/// Unsafe because index must be within the data slice and not equal to pos.
#[inline]
unsafe fn move_to(&mut self, index: usize) {
debug_assert!(index != self.pos);
let index_ptr: *const _ = &self.data[index];
let hole_ptr = &mut self.data[self.pos];
debug_assert!(index < self.data.len());
let index_ptr: *const _ = self.data.get_unchecked(index);
let hole_ptr = self.data.get_unchecked_mut(self.pos);
ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1);
self.pos = index;
}
}

impl<'a, T> Drop for Hole<'a, T> {
#[inline]
fn drop(&mut self) {
// fill the hole again
unsafe {
let pos = self.pos;
ptr::write(&mut self.data[pos], self.elt.take().unwrap());
ptr::write(self.data.get_unchecked_mut(pos), self.elt.take().unwrap());
}
}
}
Expand Down