Skip to content

Commit 7bff028

Browse files
committed
optimize util::swap, &mut pointers never alias
1 parent a7f450a commit 7bff028

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

src/libstd/ptr.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,28 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
112112
memmove64(dst as *mut u8, src as *u8, n as u64);
113113
}
114114

115+
#[inline(always)]
116+
#[cfg(target_word_size = "32")]
117+
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
118+
#[cfg(stage0)]
119+
use memcpy32 = unstable::intrinsics::memmove32;
120+
#[cfg(not(stage0))]
121+
use unstable::intrinsics::memcpy32;
122+
let n = count * sys::size_of::<T>();
123+
memcpy32(dst as *mut u8, src as *u8, n as u32);
124+
}
125+
126+
#[inline(always)]
127+
#[cfg(target_word_size = "64")]
128+
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
129+
#[cfg(stage0)]
130+
use memcpy64 = unstable::intrinsics::memmove64;
131+
#[cfg(not(stage0))]
132+
use unstable::intrinsics::memcpy64;
133+
let n = count * sys::size_of::<T>();
134+
memcpy64(dst as *mut u8, src as *u8, n as u64);
135+
}
136+
115137
#[inline(always)]
116138
pub unsafe fn set_memory<T>(dst: *mut T, c: int, count: uint) {
117139
let n = count * sys::size_of::<T>();

src/libstd/unstable/intrinsics.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ A quick refresher on memory ordering:
3131
with atomic types and is equivalent to Java's `volatile`.
3232
3333
*/
34-
3534
#[abi = "rust-intrinsic"]
3635
pub extern "rust-intrinsic" {
3736

src/libstd/util.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,18 @@ pub fn with<T,R>(
5151
#[inline(always)]
5252
pub fn swap<T>(x: &mut T, y: &mut T) {
5353
unsafe {
54-
swap_ptr(ptr::to_mut_unsafe_ptr(x), ptr::to_mut_unsafe_ptr(y));
54+
// Give ourselves some scratch space to work with
55+
let mut tmp: T = intrinsics::uninit();
56+
let t: *mut T = &mut tmp;
57+
58+
// Perform the swap, `&mut` pointers never alias
59+
ptr::copy_nonoverlapping_memory(t, x, 1);
60+
ptr::copy_nonoverlapping_memory(x, y, 1);
61+
ptr::copy_nonoverlapping_memory(y, t, 1);
62+
63+
// y and t now point to the same thing, but we need to completely forget `tmp`
64+
// because it's no longer relevant.
65+
cast::forget(tmp);
5566
}
5667
}
5768

@@ -63,7 +74,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
6374
pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
6475
// Give ourselves some scratch space to work with
6576
let mut tmp: T = intrinsics::uninit();
66-
let t = ptr::to_mut_unsafe_ptr(&mut tmp);
77+
let t: *mut T = &mut tmp;
6778

6879
// Perform the swap
6980
ptr::copy_memory(t, x, 1);

0 commit comments

Comments
 (0)