a new approach; ditch xor cuteness and maximize cache locality
This commit is contained in:
parent
85049e508b
commit
5702f436aa
1 changed files with 18 additions and 6 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue