Skip to content

Commit

Permalink
a new approach; ditch xor cuteness and maximize cache locality
Browse files Browse the repository at this point in the history
  • Loading branch information
djzin committed Mar 12, 2017
1 parent 85049e5 commit 5702f43
Showing 1 changed file with 18 additions and 6 deletions.
24 changes: 18 additions & 6 deletions src/libcore/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,17 +447,29 @@ pub unsafe fn uninitialized<T>() -> T {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
// Give ourselves some scratch space to work with
let mut t: [u8; 16] = mem::uninitialized();

let x = x as *mut T as *mut u8;
let y = y as *mut T as *mut u8;
let t = &mut t as *mut _ as *mut u8;

// can't use a for loop as the `range` impl calls `mem::swap` recursively
let len = size_of::<T>() as isize;
let mut i = 0;
while i < size_of::<T>() as isize {
// use an xor-swap as x & y are guaranteed to never alias
*x.offset(i) ^= *y.offset(i);
*y.offset(i) ^= *x.offset(i);
*x.offset(i) ^= *y.offset(i);
i += 1;
while i + 16 <= len {
// Perform the swap 16 bytes at a time, `&mut` pointers never alias
ptr::copy_nonoverlapping(x.offset(i), t, 16);
ptr::copy_nonoverlapping(y.offset(i), x.offset(i), 16);
ptr::copy_nonoverlapping(t, y.offset(i), 16);
i += 16;
}
if i < len {
// Swap any remaining bytes
let rem = (len - i) as usize;
ptr::copy_nonoverlapping(x.offset(i), t, rem);
ptr::copy_nonoverlapping(y.offset(i), x.offset(i), rem);
ptr::copy_nonoverlapping(t, y.offset(i), rem);
}
}
}
Expand Down

0 comments on commit 5702f43

Please sign in to comment.