Skip to content

Commit 9f106a6

Browse files
committed
auto merge of #6260 : alexcrichton/rust/issue-3466-no-swap, r=pcwalton
There may be a more efficient implementation of `core::util::swap_ptr`. The issue mentioned using `move_val_init`, but I couldn't figure out what that did, so I just used `copy_memory` a few times instead. I'm not exactly the best at reading LLVM generated by rust, but this does appear to be optimized away just as expected (when possible).
2 parents c49cf8b + 60803e5 commit 9f106a6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+296
-430
lines changed

doc/rust.md

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,35 +1946,6 @@ fn avg(v: &[float]) -> float {
19461946
}
19471947
~~~~
19481948

1949-
#### Swap expressions
1950-
1951-
A _swap expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) followed by a bi-directional arrow (`<->`) and another [lvalue](#lvalues-rvalues-and-temporaries).
1952-
1953-
Evaluating a swap expression causes, as a side effect, the values held in the left-hand-side and right-hand-side [lvalues](#lvalues-rvalues-and-temporaries) to be exchanged indivisibly.
1954-
1955-
Evaluating a swap expression neither changes reference counts,
1956-
nor deeply copies any owned structure pointed to by the moved [rvalue](#lvalues-rvalues-and-temporaries).
1957-
Instead, the swap expression represents an indivisible *exchange of ownership*,
1958-
between the right-hand-side and the left-hand-side of the expression.
1959-
No allocation or destruction is entailed.
1960-
1961-
An example of three different swap expressions:
1962-
1963-
~~~~~~~~
1964-
# let mut x = &mut [0];
1965-
# let mut a = &mut [0];
1966-
# let i = 0;
1967-
# struct S1 { z: int };
1968-
# struct S2 { c: int };
1969-
# let mut y = S1{z: 0};
1970-
# let mut b = S2{c: 0};
1971-
1972-
x <-> a;
1973-
x[i] <-> a[i];
1974-
y.z <-> b.c;
1975-
~~~~~~~~
1976-
1977-
19781949
#### Assignment expressions
19791950

19801951
An _assignment expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) expression followed by an
@@ -2015,7 +1986,7 @@ as
20151986
== !=
20161987
&&
20171988
||
2018-
= <->
1989+
=
20191990
~~~~
20201991

20211992
Operators at the same precedence level are evaluated left-to-right.

doc/tutorial-ffi.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ wrapping `malloc` and `free`:
151151
~~~~
152152
use core::libc::{c_void, size_t, malloc, free};
153153
use core::unstable::intrinsics;
154+
use core::util;
154155
155156
// a wrapper around the handle returned by the foreign code
156157
pub struct Unique<T> {
@@ -184,7 +185,8 @@ impl<T: Owned> Drop for Unique<T> {
184185
fn finalize(&self) {
185186
unsafe {
186187
let mut x = intrinsics::init(); // dummy value to swap in
187-
x <-> *self.ptr; // moving the object out is needed to call the destructor
188+
// moving the object out is needed to call the destructor
189+
util::replace_ptr(self.ptr, x);
188190
free(self.ptr as *c_void)
189191
}
190192
}

src/libcore/cell.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
use cast::transmute_mut;
1414
use prelude::*;
15+
use util::replace;
1516

1617
/*
1718
A dynamic, mutable location.
@@ -48,9 +49,7 @@ pub impl<T> Cell<T> {
4849
fail!(~"attempt to take an empty cell");
4950
}
5051
51-
let mut value = None;
52-
value <-> self.value;
53-
value.unwrap()
52+
replace(&mut self.value, None).unwrap()
5453
}
5554
5655
/// Returns the value, failing if the cell is full.

src/libcore/comm.rs

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use uint;
2121
use unstable;
2222
use vec;
2323
use unstable::Exclusive;
24+
use util::replace;
2425

2526
use pipes::{recv, try_recv, wait_many, peek, PacketHeader};
2627

@@ -149,9 +150,8 @@ impl<T: Owned> GenericChan<T> for Chan<T> {
149150
#[inline(always)]
150151
fn send(&self, x: T) {
151152
unsafe {
152-
let mut endp = None;
153153
let mut self_endp = transmute_mut(&self.endp);
154-
endp <-> *self_endp;
154+
let endp = replace(self_endp, None);
155155
*self_endp = Some(streamp::client::data(endp.unwrap(), x))
156156
}
157157
}
@@ -161,9 +161,8 @@ impl<T: Owned> GenericSmartChan<T> for Chan<T> {
161161
#[inline(always)]
162162
fn try_send(&self, x: T) -> bool {
163163
unsafe {
164-
let mut endp = None;
165164
let mut self_endp = transmute_mut(&self.endp);
166-
endp <-> *self_endp;
165+
let endp = replace(self_endp, None);
167166
match streamp::client::try_data(endp.unwrap(), x) {
168167
Some(next) => {
169168
*self_endp = Some(next);
@@ -179,9 +178,8 @@ impl<T: Owned> GenericPort<T> for Port<T> {
179178
#[inline(always)]
180179
fn recv(&self) -> T {
181180
unsafe {
182-
let mut endp = None;
183181
let mut self_endp = transmute_mut(&self.endp);
184-
endp <-> *self_endp;
182+
let endp = replace(self_endp, None);
185183
let streamp::data(x, endp) = recv(endp.unwrap());
186184
*self_endp = Some(endp);
187185
x
@@ -191,9 +189,8 @@ impl<T: Owned> GenericPort<T> for Port<T> {
191189
#[inline(always)]
192190
fn try_recv(&self) -> Option<T> {
193191
unsafe {
194-
let mut endp = None;
195192
let mut self_endp = transmute_mut(&self.endp);
196-
endp <-> *self_endp;
193+
let endp = replace(self_endp, None);
197194
match try_recv(endp.unwrap()) {
198195
Some(streamp::data(x, endp)) => {
199196
*self_endp = Some(endp);
@@ -209,14 +206,13 @@ impl<T: Owned> Peekable<T> for Port<T> {
209206
#[inline(always)]
210207
fn peek(&self) -> bool {
211208
unsafe {
212-
let mut endp = None;
213209
let mut self_endp = transmute_mut(&self.endp);
214-
endp <-> *self_endp;
210+
let mut endp = replace(self_endp, None);
215211
let peek = match endp {
216212
Some(ref mut endp) => peek(endp),
217213
None => fail!(~"peeking empty stream")
218214
};
219-
*self_endp <-> endp;
215+
*self_endp = endp;
220216
peek
221217
}
222218
}
@@ -267,8 +263,7 @@ impl<T:Owned> GenericPort<T> for PortSet<T> {
267263
let mut result = None;
268264
// we have to swap the ports array so we aren't borrowing
269265
// aliasable mutable memory.
270-
let mut ports = ~[];
271-
ports <-> *self_ports;
266+
let mut ports = replace(self_ports, ~[]);
272267
while result.is_none() && ports.len() > 0 {
273268
let i = wait_many(ports);
274269
match ports[i].try_recv() {
@@ -281,7 +276,7 @@ impl<T:Owned> GenericPort<T> for PortSet<T> {
281276
}
282277
}
283278
}
284-
ports <-> *self_ports;
279+
*self_ports = ports;
285280
result
286281
}
287282
}
@@ -320,8 +315,7 @@ impl<T: Owned> GenericChan<T> for SharedChan<T> {
320315
fn send(&self, x: T) {
321316
let mut xx = Some(x);
322317
do self.ch.with_imm |chan| {
323-
let mut x = None;
324-
x <-> xx;
318+
let x = replace(&mut xx, None);
325319
chan.send(x.unwrap())
326320
}
327321
}
@@ -331,8 +325,7 @@ impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
331325
fn try_send(&self, x: T) -> bool {
332326
let mut xx = Some(x);
333327
do self.ch.with_imm |chan| {
334-
let mut x = None;
335-
x <-> xx;
328+
let x = replace(&mut xx, None);
336329
chan.try_send(x.unwrap())
337330
}
338331
}

src/libcore/hashmap.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -176,16 +176,13 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
176176
/// Expands the capacity of the array and re-insert each of the
177177
/// existing buckets.
178178
fn resize(&mut self, new_capacity: uint) {
179-
let old_capacity = self.buckets.len();
180179
self.resize_at = resize_at(new_capacity);
181180

182-
let mut old_buckets = vec::from_fn(new_capacity, |_| None);
183-
self.buckets <-> old_buckets;
181+
let old_buckets = replace(&mut self.buckets,
182+
vec::from_fn(new_capacity, |_| None));
184183

185184
self.size = 0;
186-
for uint::range(0, old_capacity) |i| {
187-
let mut bucket = None;
188-
bucket <-> old_buckets[i];
185+
do vec::consume(old_buckets) |_, bucket| {
189186
self.insert_opt_bucket(bucket);
190187
}
191188
}
@@ -265,13 +262,11 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
265262
};
266263
267264
let len_buckets = self.buckets.len();
268-
let mut bucket = None;
269-
self.buckets[idx] <-> bucket;
265+
let bucket = replace(&mut self.buckets[idx], None);
270266
271267
let value = match bucket {
272268
None => None,
273-
Some(bucket) => {
274-
let Bucket{value: value, _} = bucket;
269+
Some(Bucket{value, _}) => {
275270
Some(value)
276271
},
277272
};
@@ -281,8 +276,7 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
281276
let size = self.size - 1;
282277
idx = self.next_bucket(idx, len_buckets);
283278
while self.buckets[idx].is_some() {
284-
let mut bucket = None;
285-
bucket <-> self.buckets[idx];
279+
let bucket = replace(&mut self.buckets[idx], None);
286280
self.insert_opt_bucket(bucket);
287281
idx = self.next_bucket(idx, len_buckets);
288282
}
@@ -613,15 +607,13 @@ pub impl<K: Hash + Eq, V> HashMap<K, V> {
613607
}
614608
615609
fn consume(&mut self, f: &fn(K, V)) {
616-
let mut buckets = ~[];
617-
self.buckets <-> buckets;
610+
let buckets = replace(&mut self.buckets, ~[]);
618611
self.size = 0;
619612
620613
do vec::consume(buckets) |_, bucket| {
621614
match bucket {
622615
None => {},
623-
Some(bucket) => {
624-
let Bucket{key: key, value: value, _} = bucket;
616+
Some(Bucket{key, value, _}) => {
625617
f(key, value)
626618
}
627619
}

src/libcore/pipes.rs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ use unstable::intrinsics;
9393
use ptr;
9494
use task;
9595
use vec;
96+
use util::replace;
9697

9798
static SPIN_COUNT: uint = 0;
9899

@@ -428,8 +429,7 @@ fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
428429
// optimistic path
429430
match p.header.state {
430431
Full => {
431-
let mut payload = None;
432-
payload <-> p.payload;
432+
let payload = replace(&mut p.payload, None);
433433
p.header.state = Empty;
434434
return Some(payload.unwrap())
435435
},
@@ -480,8 +480,7 @@ fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
480480
fail!(~"blocking on already blocked packet")
481481
},
482482
Full => {
483-
let mut payload = None;
484-
payload <-> p.payload;
483+
let payload = replace(&mut p.payload, None);
485484
let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
486485
if !old_task.is_null() {
487486
unsafe {
@@ -675,8 +674,7 @@ impl<T:Owned,Tbuffer:Owned> Drop for SendPacketBuffered<T,Tbuffer> {
675674
unsafe {
676675
let this: &mut SendPacketBuffered<T,Tbuffer> = transmute(self);
677676
if this.p != None {
678-
let mut p = None;
679-
p <-> this.p;
677+
let p = replace(&mut this.p, None);
680678
sender_terminate(p.unwrap())
681679
}
682680
}
@@ -695,9 +693,7 @@ pub fn SendPacketBuffered<T,Tbuffer>(p: *mut Packet<T>)
695693
696694
pub impl<T,Tbuffer> SendPacketBuffered<T,Tbuffer> {
697695
fn unwrap(&mut self) -> *mut Packet<T> {
698-
let mut p = None;
699-
p <-> self.p;
700-
p.unwrap()
696+
replace(&mut self.p, None).unwrap()
701697
}
702698
703699
fn header(&mut self) -> *mut PacketHeader {
@@ -713,9 +709,7 @@ pub impl<T,Tbuffer> SendPacketBuffered<T,Tbuffer> {
713709
714710
fn reuse_buffer(&mut self) -> BufferResource<Tbuffer> {
715711
//error!("send reuse_buffer");
716-
let mut tmp = None;
717-
tmp <-> self.buffer;
718-
tmp.unwrap()
712+
replace(&mut self.buffer, None).unwrap()
719713
}
720714
}
721715
@@ -738,8 +732,7 @@ impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
738732
unsafe {
739733
let this: &mut RecvPacketBuffered<T,Tbuffer> = transmute(self);
740734
if this.p != None {
741-
let mut p = None;
742-
p <-> this.p;
735+
let p = replace(&mut this.p, None);
743736
receiver_terminate(p.unwrap())
744737
}
745738
}
@@ -748,15 +741,11 @@ impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
748741
749742
pub impl<T:Owned,Tbuffer:Owned> RecvPacketBuffered<T, Tbuffer> {
750743
fn unwrap(&mut self) -> *mut Packet<T> {
751-
let mut p = None;
752-
p <-> self.p;
753-
p.unwrap()
744+
replace(&mut self.p, None).unwrap()
754745
}
755746
756747
fn reuse_buffer(&mut self) -> BufferResource<Tbuffer> {
757-
let mut tmp = None;
758-
tmp <-> self.buffer;
759-
tmp.unwrap()
748+
replace(&mut self.buffer, None).unwrap()
760749
}
761750
}
762751

0 commit comments

Comments
 (0)