about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorDjzin <djzin@users.noreply.github.com>2017-03-12 13:14:47 +0000
committerDjzin <djzin@users.noreply.github.com>2017-03-12 13:14:47 +0000
commit4bcfbc36c672f0f30176a31c5a6e529bebd6fbcc (patch)
tree78629ca780bd383b275fe14c297cf72f87699de2 /src/libcore
parentf84a5174833e39ca779fa7e49b34190e100e2e49 (diff)
downloadrust-4bcfbc36c672f0f30176a31c5a6e529bebd6fbcc.tar.gz
rust-4bcfbc36c672f0f30176a31c5a6e529bebd6fbcc.zip
speed up mem::swap
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/mem.rs21
1 files changed, 9 insertions, 12 deletions
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index f4ce4697d7c..a7c5d29c5a5 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -109,7 +109,7 @@ pub use intrinsics::transmute;
 /// [`Clone`][clone]. You need the value's destructor to run only once,
 /// because a double `free` is undefined behavior.
 ///
-/// An example is the definition of [`mem::swap`][swap] in this module:
+/// An example is the (old) definition of [`mem::swap`][swap] in this module:
 ///
 /// ```
 /// use std::mem;
@@ -447,18 +447,15 @@ 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: T = uninitialized();
+        let x = x as *mut T as *mut u8;
+        let y = y as *mut T as *mut u8;
 
-        // Perform the swap, `&mut` pointers never alias
-        ptr::copy_nonoverlapping(&*x, &mut t, 1);
-        ptr::copy_nonoverlapping(&*y, x, 1);
-        ptr::copy_nonoverlapping(&t, y, 1);
-
-        // y and t now point to the same thing, but we need to completely
-        // forget `t` because we do not want to run the destructor for `T`
-        // on its value, which is still owned somewhere outside this function.
-        forget(t);
+        // use an xor-swap as x & y are guaranteed to never alias
+        for i in 0..size_of::<T>() as isize {
+            *x.offset(i) ^= *y.offset(i);
+            *y.offset(i) ^= *x.offset(i);
+            *x.offset(i) ^= *y.offset(i);
+        }
     }
 }