diff options
| author | bors <bors@rust-lang.org> | 2013-05-23 22:04:40 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-05-23 22:04:40 -0700 |
| commit | 212d6a2f61bbd3d0dae6e8768a9c0ea6c17de7a9 (patch) | |
| tree | 60e419ffb5c3922a58dc201842f81fdab2abad6d /src/libstd | |
| parent | 7c0cc9c47a3d95e058b3684c7ed14924f64ff808 (diff) | |
| parent | 7bff0281c72d64ec5129871354a55d6a2070dd51 (diff) | |
| download | rust-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.rs | 23 | ||||
| -rw-r--r-- | src/libstd/unstable/intrinsics.rs | 8 | ||||
| -rw-r--r-- | src/libstd/util.rs | 19 |
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); } |
