Skip to content

Commit 4bcfbc3

Browse files
committed
speed up mem::swap
1 parent f84a517 commit 4bcfbc3

File tree

1 file changed

+9
-12
lines changed

1 file changed

+9
-12
lines changed

src/libcore/mem.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub use intrinsics::transmute;
109109
/// [`Clone`][clone]. You need the value's destructor to run only once,
110110
/// because a double `free` is undefined behavior.
111111
///
112-
/// An example is the definition of [`mem::swap`][swap] in this module:
112+
/// An example is the (old) definition of [`mem::swap`][swap] in this module:
113113
///
114114
/// ```
115115
/// use std::mem;
@@ -447,18 +447,15 @@ pub unsafe fn uninitialized<T>() -> T {
447447
#[stable(feature = "rust1", since = "1.0.0")]
448448
pub fn swap<T>(x: &mut T, y: &mut T) {
449449
unsafe {
450-
// Give ourselves some scratch space to work with
451-
let mut t: T = uninitialized();
450+
let x = x as *mut T as *mut u8;
451+
let y = y as *mut T as *mut u8;
452452

453-
// Perform the swap, `&mut` pointers never alias
454-
ptr::copy_nonoverlapping(&*x, &mut t, 1);
455-
ptr::copy_nonoverlapping(&*y, x, 1);
456-
ptr::copy_nonoverlapping(&t, y, 1);
457-
458-
// y and t now point to the same thing, but we need to completely
459-
// forget `t` because we do not want to run the destructor for `T`
460-
// on its value, which is still owned somewhere outside this function.
461-
forget(t);
453+
// use an xor-swap as x & y are guaranteed to never alias
454+
for i in 0..size_of::<T>() as isize {
455+
*x.offset(i) ^= *y.offset(i);
456+
*y.offset(i) ^= *x.offset(i);
457+
*x.offset(i) ^= *y.offset(i);
458+
}
462459
}
463460
}
464461

0 commit comments

Comments
 (0)