about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-05-23 22:04:40 -0700
committerbors <bors@rust-lang.org>2013-05-23 22:04:40 -0700
commit212d6a2f61bbd3d0dae6e8768a9c0ea6c17de7a9 (patch)
tree60e419ffb5c3922a58dc201842f81fdab2abad6d /src/libstd
parent7c0cc9c47a3d95e058b3684c7ed14924f64ff808 (diff)
parent7bff0281c72d64ec5129871354a55d6a2070dd51 (diff)
downloadrust-212d6a2f61bbd3d0dae6e8768a9c0ea6c17de7a9.tar.gz
rust-212d6a2f61bbd3d0dae6e8768a9c0ea6c17de7a9.zip
auto merge of #6710 : thestinger/rust/swap, r=catamorphism
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/ptr.rs23
-rw-r--r--src/libstd/unstable/intrinsics.rs8
-rw-r--r--src/libstd/util.rs19
3 files changed, 44 insertions, 6 deletions
diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs
index f6cc00ccc86..d1c0ffe7953 100644
--- a/src/libstd/ptr.rs
+++ b/src/libstd/ptr.rs
@@ -103,6 +103,7 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
     let n = count * sys::size_of::<T>();
     memmove32(dst as *mut u8, src as *u8, n as u32);
 }
+
 #[inline(always)]
 #[cfg(target_word_size = "64")]
 pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
@@ -112,6 +113,28 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
 }
 
 #[inline(always)]
+#[cfg(target_word_size = "32")]
+pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
+    #[cfg(stage0)]
+    use memcpy32 = unstable::intrinsics::memmove32;
+    #[cfg(not(stage0))]
+    use unstable::intrinsics::memcpy32;
+    let n = count * sys::size_of::<T>();
+    memcpy32(dst as *mut u8, src as *u8, n as u32);
+}
+
+#[inline(always)]
+#[cfg(target_word_size = "64")]
+pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
+    #[cfg(stage0)]
+    use memcpy64 = unstable::intrinsics::memmove64;
+    #[cfg(not(stage0))]
+    use unstable::intrinsics::memcpy64;
+    let n = count * sys::size_of::<T>();
+    memcpy64(dst as *mut u8, src as *u8, n as u64);
+}
+
+#[inline(always)]
 pub unsafe fn set_memory<T>(dst: *mut T, c: int, count: uint) {
     let n = count * sys::size_of::<T>();
     libc_::memset(dst as *mut c_void, c as libc::c_int, n as size_t);
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index d476822819e..521708621fc 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -31,7 +31,6 @@ A quick refresher on memory ordering:
   with atomic types and is equivalent to Java's `volatile`.
 
 */
-
 #[abi = "rust-intrinsic"]
 pub extern "rust-intrinsic" {
 
@@ -128,6 +127,13 @@ pub extern "rust-intrinsic" {
     /// Get the address of the `__morestack` stack growth function.
     pub fn morestack_addr() -> *();
 
+    /// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic.
+    #[cfg(not(stage0))]
+    pub fn memcpy32(dst: *mut u8, src: *u8, size: u32);
+    /// Equivalent to the `llvm.memcpy.p0i8.0i8.i64` intrinsic.
+    #[cfg(not(stage0))]
+    pub fn memcpy64(dst: *mut u8, src: *u8, size: u64);
+
     /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic.
     pub fn memmove32(dst: *mut u8, src: *u8, size: u32);
     /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic.
diff --git a/src/libstd/util.rs b/src/libstd/util.rs
index e2b91594d12..400a13896be 100644
--- a/src/libstd/util.rs
+++ b/src/libstd/util.rs
@@ -51,7 +51,18 @@ pub fn with<T,R>(
 #[inline(always)]
 pub fn swap<T>(x: &mut T, y: &mut T) {
     unsafe {
-        swap_ptr(ptr::to_mut_unsafe_ptr(x), ptr::to_mut_unsafe_ptr(y));
+        // Give ourselves some scratch space to work with
+        let mut tmp: T = intrinsics::uninit();
+        let t: *mut T = &mut tmp;
+
+        // Perform the swap, `&mut` pointers never alias
+        ptr::copy_nonoverlapping_memory(t, x, 1);
+        ptr::copy_nonoverlapping_memory(x, y, 1);
+        ptr::copy_nonoverlapping_memory(y, t, 1);
+
+        // y and t now point to the same thing, but we need to completely forget `tmp`
+        // because it's no longer relevant.
+        cast::forget(tmp);
     }
 }
 
@@ -61,18 +72,16 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
  */
 #[inline]
 pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
-    if x == y { return }
-
     // Give ourselves some scratch space to work with
     let mut tmp: T = intrinsics::uninit();
-    let t = ptr::to_mut_unsafe_ptr(&mut tmp);
+    let t: *mut T = &mut tmp;
 
     // Perform the swap
     ptr::copy_memory(t, x, 1);
     ptr::copy_memory(x, y, 1);
     ptr::copy_memory(y, t, 1);
 
-    // y and t now point to the same thing, but we need to completely forget t
+    // y and t now point to the same thing, but we need to completely forget `tmp`
     // because it's no longer relevant.
     cast::forget(tmp);
 }