optimize util::swap, &mut pointers never alias

This commit is contained in:
Daniel Micay 2013-05-23 22:54:46 -04:00
parent a7f450ab22
commit 7bff0281c7
3 changed files with 35 additions and 3 deletions

View File

@ -112,6 +112,28 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
memmove64(dst as *mut u8, src as *u8, n as u64);
}
#[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>();

View File

@ -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" {

View File

@ -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);
}
}
@ -63,7 +74,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
// 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);