Skip to content

Commit 1c75745

Browse files
committed
---
yaml --- r: 142523 b: refs/heads/try2 c: ba13482 h: refs/heads/master i: 142521: d5c001b 142519: aa50b97 v: v3
1 parent 32304b8 commit 1c75745

File tree

3 files changed

+145
-41
lines changed

3 files changed

+145
-41
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 1670a8cfb13fd384d9fd4ca47034cef99118c7a7
8+
refs/heads/try2: ba13482dfabe4d0022f1fc2375b500cce53a05ce
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libstd/ptr.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,30 @@ pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
142142
memset64(dst, c, count as u64);
143143
}
144144

145+
/**
146+
* Zeroes out `count` bytes of memory at `dst`
147+
*/
148+
#[inline]
149+
#[cfg(not(stage0))]
150+
pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
151+
set_memory(dst, 0, count);
152+
}
153+
154+
/**
155+
* Zeroes out `count * size_of::<T>` bytes of memory at `dst`
156+
*/
157+
#[inline]
158+
#[cfg(stage0)]
159+
pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
160+
let mut count = count * sys::size_of::<T>();
161+
let mut dst = dst as *mut u8;
162+
while count > 0 {
163+
*dst = 0;
164+
dst = mut_offset(dst, 1);
165+
count -= 1;
166+
}
167+
}
168+
145169
/**
146170
* Swap the values at two mutable locations of the same type, without
147171
* deinitialising or copying either one.
@@ -172,6 +196,32 @@ pub unsafe fn replace_ptr<T>(dest: *mut T, mut src: T) -> T {
172196
src
173197
}
174198

199+
/**
200+
* Reads the value from `*src` and returns it. Does not copy `*src`.
201+
*/
202+
#[inline(always)]
203+
pub unsafe fn read_ptr<T>(src: *mut T) -> T {
204+
let mut tmp: T = intrinsics::uninit();
205+
let t: *mut T = &mut tmp;
206+
copy_memory(t, src, 1);
207+
tmp
208+
}
209+
210+
/**
211+
* Reads the value from `*src` and nulls it out.
212+
* This currently prevents destructors from executing.
213+
*/
214+
#[inline(always)]
215+
pub unsafe fn read_and_zero_ptr<T>(dest: *mut T) -> T {
216+
// Copy the data out from `dest`:
217+
let tmp = read_ptr(dest);
218+
219+
// Now zero out `dest`:
220+
zero_memory(dest, 1);
221+
222+
tmp
223+
}
224+
175225
/// Transform a region pointer - &T - to an unsafe pointer - *T.
176226
#[inline]
177227
pub fn to_unsafe_ptr<T>(thing: &T) -> *T {

branches/try2/src/libstd/vec.rs

Lines changed: 94 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,16 +1256,15 @@ impl<T> OwnedVector<T> for ~[T] {
12561256
/// ~~~
12571257
#[inline]
12581258
fn push_all_move(&mut self, mut rhs: ~[T]) {
1259-
let new_len = self.len() + rhs.len();
1259+
let self_len = self.len();
1260+
let rhs_len = rhs.len();
1261+
let new_len = self_len + rhs_len;
12601262
self.reserve(new_len);
1261-
unsafe {
1262-
do rhs.as_mut_buf |p, len| {
1263-
for uint::range(0, len) |i| {
1264-
let x = ptr::replace_ptr(ptr::mut_offset(p, i),
1265-
intrinsics::uninit());
1266-
self.push(x);
1267-
}
1268-
}
1263+
unsafe { // Note: infallible.
1264+
let self_p = vec::raw::to_mut_ptr(*self);
1265+
let rhs_p = vec::raw::to_ptr(rhs);
1266+
ptr::copy_memory(ptr::mut_offset(self_p, self_len), rhs_p, rhs_len);
1267+
raw::set_len(self, new_len);
12691268
raw::set_len(&mut rhs, 0);
12701269
}
12711270
}
@@ -1277,9 +1276,8 @@ impl<T> OwnedVector<T> for ~[T] {
12771276
ln => {
12781277
let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]);
12791278
unsafe {
1280-
let val = ptr::replace_ptr(valptr, intrinsics::init());
1281-
raw::set_len(self, ln - 1u);
1282-
Some(val)
1279+
raw::set_len(v, ln - 1u);
1280+
ptr::read_ptr(valptr)
12831281
}
12841282
}
12851283
}
@@ -1410,7 +1408,7 @@ impl<T> OwnedVector<T> for ~[T] {
14101408
unsafe {
14111409
// This loop is optimized out for non-drop types.
14121410
for uint::range(newlen, oldlen) |i| {
1413-
ptr::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit());
1411+
ptr::read_and_zero_ptr(ptr::mut_offset(p, i))
14141412
}
14151413
}
14161414
}
@@ -1555,37 +1553,93 @@ pub trait OwnedEqVector<T:Eq> {
15551553

15561554
impl<T:Eq> OwnedEqVector<T> for ~[T] {
15571555
/**
1558-
* Remove consecutive repeated elements from a vector; if the vector is
1559-
* sorted, this removes all duplicates.
1560-
*/
1561-
pub fn dedup(&mut self) {
1556+
* Remove consecutive repeated elements from a vector; if the vector is
1557+
* sorted, this removes all duplicates.
1558+
*/
1559+
pub fn dedup<T:Eq>(&mut self) {
15621560
unsafe {
1563-
if self.len() == 0 { return; }
1564-
let mut last_written = 0;
1565-
let mut next_to_read = 1;
1566-
do self.as_mut_buf |p, ln| {
1567-
// last_written < next_to_read <= ln
1568-
while next_to_read < ln {
1569-
// last_written < next_to_read < ln
1570-
if *ptr::mut_offset(p, next_to_read) ==
1571-
*ptr::mut_offset(p, last_written) {
1572-
ptr::replace_ptr(ptr::mut_offset(p, next_to_read),
1573-
intrinsics::uninit());
1574-
} else {
1575-
last_written += 1;
1576-
// last_written <= next_to_read < ln
1577-
if next_to_read != last_written {
1578-
ptr::swap_ptr(ptr::mut_offset(p, last_written),
1579-
ptr::mut_offset(p, next_to_read));
1580-
}
1561+
// Although we have a mutable reference to `self`, we cannot make
1562+
// *arbitrary* changes. There exists the possibility that this
1563+
// vector is contained with an `@mut` box and hence is still
1564+
// readable by the outside world during the `Eq` comparisons.
1565+
// Moreover, those comparisons could fail, so we must ensure
1566+
// that the vector is in a valid state at all time.
1567+
//
1568+
// The way that we handle this is by using swaps; we iterate
1569+
// over all the elements, swapping as we go so that at the end
1570+
// the elements we wish to keep are in the front, and those we
1571+
// wish to reject are at the back. We can then truncate the
1572+
// vector. This operation is still O(n).
1573+
//
1574+
// Example: We start in this state, where `r` represents "next
1575+
// read" and `w` represents "next_write`.
1576+
//
1577+
// r
1578+
// +---+---+---+---+---+---+
1579+
// | 0 | 1 | 1 | 2 | 3 | 3 |
1580+
// +---+---+---+---+---+---+
1581+
// w
1582+
//
1583+
// Comparing self[r] against self[w-1], tis is not a duplicate, so
1584+
// we swap self[r] and self[w] (no effect as r==w) and then increment both
1585+
// r and w, leaving us with:
1586+
//
1587+
// r
1588+
// +---+---+---+---+---+---+
1589+
// | 0 | 1 | 1 | 2 | 3 | 3 |
1590+
// +---+---+---+---+---+---+
1591+
// w
1592+
//
1593+
// Comparing self[r] against self[w-1], this value is a duplicate,
1594+
// so we increment `r` but leave everything else unchanged:
1595+
//
1596+
// r
1597+
// +---+---+---+---+---+---+
1598+
// | 0 | 1 | 1 | 2 | 3 | 3 |
1599+
// +---+---+---+---+---+---+
1600+
// w
1601+
//
1602+
// Comparing self[r] against self[w-1], this is not a duplicate,
1603+
// so swap self[r] and self[w] and advance r and w:
1604+
//
1605+
// r
1606+
// +---+---+---+---+---+---+
1607+
// | 0 | 1 | 2 | 1 | 3 | 3 |
1608+
// +---+---+---+---+---+---+
1609+
// w
1610+
//
1611+
// Not a duplicate, repeat:
1612+
//
1613+
// r
1614+
// +---+---+---+---+---+---+
1615+
// | 0 | 1 | 2 | 3 | 1 | 3 |
1616+
// +---+---+---+---+---+---+
1617+
// w
1618+
//
1619+
// Duplicate, advance r. End of vec. Truncate to w.
1620+
1621+
let ln = self.len();
1622+
if ln < 1 { return; }
1623+
1624+
// Avoid bounds checks by using unsafe pointers.
1625+
let p = vec::raw::to_mut_ptr(*self);
1626+
let mut r = 1;
1627+
let mut w = 1;
1628+
1629+
while r < ln {
1630+
let p_r = ptr::mut_offset(p, r);
1631+
let p_wm1 = ptr::mut_offset(p, w - 1);
1632+
if *p_r != *p_wm1 {
1633+
if r != w {
1634+
let p_w = ptr::mut_offset(p_wm1, 1);
1635+
util::swap(&mut *p_r, &mut *p_w);
15811636
}
1582-
// last_written <= next_to_read < ln
1583-
next_to_read += 1;
1584-
// last_written < next_to_read <= ln
1637+
w += 1;
15851638
}
1639+
r += 1;
15861640
}
1587-
// last_written < next_to_read == ln
1588-
raw::set_len(self, last_written + 1);
1641+
1642+
self.truncate(w);
15891643
}
15901644
}
15911645
}

0 commit comments

Comments
 (0)