Skip to content

Commit d4d3f53

Browse files
committed
better respect alignment for copying tail
1 parent 7475135 commit d4d3f53

File tree

1 file changed

+37
-25
lines changed

1 file changed

+37
-25
lines changed

src/libcore/mem.rs

+37-25
Original file line numberDiff line numberDiff line change
@@ -532,35 +532,47 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
532532
i += block_size as isize;
533533
}
534534

535-
// Swap remaining bytes 8 at a time if x & y are properly aligned
536-
if align_of::<T>() % 8 == 0 {
537-
while i + 8 <= len as isize {
538-
let t = *(x.offset(i) as *mut u64);
539-
*(x.offset(i) as *mut u64) = *(y.offset(i) as *mut u64);
540-
*(y.offset(i) as *mut u64) = t;
541-
i += 8;
542-
}
543-
}
544-
545-
// Swap remaining bytes 4 at a time if x & y are properly aligned
546-
if align_of::<T>() % 4 == 0 {
547-
while i + 4 <= len as isize {
548-
let t = *(x.offset(i) as *mut u32);
549-
*(x.offset(i) as *mut u32) = *(y.offset(i) as *mut u32);
550-
*(y.offset(i) as *mut u32) = t;
551-
i += 4;
552-
}
553-
}
554535

555536
if i < len {
556-
// Swap any remaining bytes
537+
// Swap any remaining bytes, using aligned types to copy
538+
// where appropriate (this information is lost by conversion
539+
// to *mut u8, so restore it manually here)
557540
let mut t: UnalignedBlock = uninitialized();
558-
let t = &mut t as *mut _ as *mut u8;
559-
560541
let rem = (len - i) as usize;
561-
ptr::copy_nonoverlapping(x.offset(i), t, rem);
562-
ptr::copy_nonoverlapping(y.offset(i), x.offset(i), rem);
563-
ptr::copy_nonoverlapping(t, y.offset(i), rem);
542+
543+
if align_of::<T>() % 8 == 0 && len % 8 == 0 {
544+
let t = &mut t as *mut _ as *mut u64;
545+
let x = x.offset(i) as *mut u64;
546+
let y = y.offset(i) as *mut u64;
547+
548+
ptr::copy_nonoverlapping(x, t, rem / 8);
549+
ptr::copy_nonoverlapping(y, x, rem / 8);
550+
ptr::copy_nonoverlapping(t, y, rem / 8);
551+
} else if align_of::<T>() % 4 == 0 && len % 4 == 0 {
552+
let t = &mut t as *mut _ as *mut u32;
553+
let x = x.offset(i) as *mut u32;
554+
let y = y.offset(i) as *mut u32;
555+
556+
ptr::copy_nonoverlapping(x, t, rem / 4);
557+
ptr::copy_nonoverlapping(y, x, rem / 4);
558+
ptr::copy_nonoverlapping(t, y, rem / 4);
559+
} else if align_of::<T>() % 2 == 0 && len % 2 == 0 {
560+
let t = &mut t as *mut _ as *mut u16;
561+
let x = x.offset(i) as *mut u16;
562+
let y = y.offset(i) as *mut u16;
563+
564+
ptr::copy_nonoverlapping(x, t, rem / 2);
565+
ptr::copy_nonoverlapping(y, x, rem / 2);
566+
ptr::copy_nonoverlapping(t, y, rem / 2);
567+
} else {
568+
let t = &mut t as *mut _ as *mut u8;
569+
let x = x.offset(i);
570+
let y = y.offset(i);
571+
572+
ptr::copy_nonoverlapping(x, t, rem);
573+
ptr::copy_nonoverlapping(y, x, rem);
574+
ptr::copy_nonoverlapping(t, y, rem);
575+
}
564576
}
565577
}
566578
}

0 commit comments

Comments
 (0)