a new approach; ditch xor cuteness and maximize cache locality

This commit is contained in:
Djzin 2017-03-12 18:32:20 +00:00
parent 85049e508b
commit 5702f436aa

View file

@ -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);
}
}
}